2016-09-22 35 views
-3

程序应该执行一些循环:的Unix/C++代码读取文本行,将它们分解成单词,并运行结果

  1. 发出提示和读一行文本。

  2. 将该行分成单词。

  3. 如果该命令是内置的,请亲自处理,然后返回到读取步骤。否则,

  4. 执行一个fork创建一个新的进程。报告任何失败的原因(并且 - 当然,如果分叉失败,不要执行)。

  5. 子进程将列表中的第一个单词当作命令的名称,并使用exec调用运行它。将整个列表作为参数发送给程序。报告任何失败的原因。

  6. 父进程等待子进程退出,然后报告其状态。

  7. 回到读取下一个命令。

我写的头,身体和下面

执行这行解析类:

#include <string> 

using namespace std; 

/* 
* This class takes a C++ string and provides an array of plain C strings 
* (array of pointers to char) representing the words in the line. 
*/ 

class LineBreaker { 
public: 
     // Construct the object, providing the line of text to be 
     // broken up. 
     LineBreaker(const string &s); 

     // Clean up. 
     ~LineBreaker() { 
       delete [] m_data; 
       delete [] m_parmlist; 
     } 

     // Return an pointer to the first slot of an array of pointers 
     // containing the words in the string sent to the constructor. 
     // The list is terminated with a NULL pointer. 
     char **parmlist() { return m_parmlist; } 
private: 
     char *m_data;   // Dyn array of characters from the string. 
     char **m_parmlist;  // Array of words 
}; 

这是亚军方案,这是身体:

/* 
    * Simple program to demonstrate the fork/exec/run sequence for creating 
    * processes in Unix. 
    */ 

    #include <iostream> 
    #include <string> 
    using namespace std; 

    #include <unistd.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include <sys/types.h> 
    #include <sys/wait.h> 

    #include "linebreaker.h" 

main() 
{ 
     /* Ask for a program to run. This is just the file name of an 
      executable. */ 
     cout << "Your command? "; 
     string cmd; 
     getline(cin, cmd); 

     LineBreaker breaker(cmd); 

     /* Create a child process and try to run the program in it. */ 
     if(fork() == 0) { 
       execv(breaker.parmlist()[0], breaker.parmlist()); 
       cout << "Sorry, the exec failed." << endl; 
       exit(1); 
     } 

     /* See what was the cause of the child processes' demise. */ 
     int status; 
     wait(&status); /*we only need to change this part, and use something like this if(string(breaker.parlist()[0]) == "exit") */ 
     if(WIFEXITED(status)) cout << "Exited." << endl; 
     else if(WIFSIGNALED(status)) cout << "Killed." << endl; 
     else cout << "Mysteriously vanished." << endl; 
} 

/* 
* Note: This program really should check the return values for fork() and for 
* exec() to make sure they succeeded, and print an error message if not. 
* Failure is indicated by a negative return value. It would also help to use 
* errno and strerror() to print a descriptive error message in place of the 
* existing exec() failure message, or for the new messages. 
* 
* It also uses uses gets() and fixed-size buffers, which creates a risk of 
* buffer overflow. 
*/ 

这是执行:

#include <string> 
#include <cstring> 
#include <cctype> 
#include <algorithm> 
#include <list> 

#include "linebreaker.h" 

LineBreaker::LineBreaker(const string &s) 
{ 
     // Copy the string as a character array. 
     m_data = new char[s.length()+1]; 
     strcpy(m_data, s.c_str()); 

     // Find all the words. 
     char last = ' '; 
     list<char *> parts; 
     for(char *scan = m_data; *scan; ++scan) { 
       char curr = *scan; 

       if(isspace(last) && !isspace(curr)) 
         parts.push_back(scan); 
       else if(!isspace(last) && isspace(curr)) 
         *scan = '\0'; 

       last = curr; 
     } 

     // Allocate the array of pointers for exec, and copy the 
     // pointer into it. Then add the NULL terminator. 
     m_parmlist = new char * [parts.size()+1]; 
     copy(parts.begin(), parts.end(), m_parmlist); 
     m_parmlist[parts.size()] = NULL; 
} 

我想在一个while循环中包装现有runner程序的大部分代码,这样它将反复读取和执行一个命令,而不是读取一个并退出。

在转轮程序,输入一个空行创建一个错误(EXEC将失败)。改变程序,所以输入一个空行(无字,因此没有命令名),不运行任何命令,但程序只是返回到promp,然后读取另一个命令。

该版本在通常位置搜索命令文件,因此不必查找要执​​行的文件的完整路径。跑步者程序使用execv;只需用execvp替换即可。

检查从每一个岔路口,EXEC的返回码,或等待调用检查是否存在故障。我想用errno和strerror打印一条消息,指出失败的原因。实现两个无法使用fork/exec运行的命令。这些是退出命令和cd命令。这些是shell必须执行的内置命令。对于状态报告,如果程序以非0的代码退出(错误退出),或者崩溃,请报告该错误。对于正常的退出,什么也不说。报告退出代码或崩溃原因。更多关于下面的内容。

+2

是什么问题????????????????? – jdweng

+0

问题是把runner程序换成while循环,所以它可以解决列出的8个问题 –

+0

所以你基本上想把'main()'中的所有内容放在一个循环中。对于编写所有代码的人来说似乎很容易,问题到底是什么? – Havenard

回答

0

不是一个完整的答案,因为这是家庭作业,但这里有一个提示:while (std::getline(std::cin, cmd))

这工作,因为getline()返回到输入流的引用,当你投的是一个bool值,它将返回true而流尚未遇到文件结束或错误。

相关问题