1

2 つのコマンドとその引数 (最大 5 つ) を受け取る代入を作成し、一方の出力を他方にパイプします。その後ループし、quit が入力されるまで再び 2 つのコマンドを要求します。

私が抱えている問題は、2番目のループで値を入力した後、2番目のコマンドを入力した直後に「Enter Command 1」を出力するなど、奇妙なことが起こることです(両方が同じ行に表示されます)。また、たとえば ls -l を入力してから cat を入力すると機能することにも気付きましたが、ls -l を入力してから wc を入力すると問題が発生します。誰かが見て、おそらく私を手伝ってくれませんか?私は一日中それに取り組んでいて、それを終えるのに1時間強残っています.

補足: はい、実行コマンドのセットアップが少しばかげていることは認識していますが、時間がなく、それをいじる時間がありません。できます。

#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sstream>
using namespace std;

int main(){
//Our imput strings that the user enters.
string input1;
string input2;

//Temporary string.
string s;  

//Array to hold the items passed in.
string arg1[6];
string arg2[6];

//A count of how many items they passed in.
int carg1;
int carg2;

//Loop until quit.
while(true){
    //Set all our values to empty/zero
    carg1 = 0;
    carg2 = 0;
    input1.clear();
    input2.clear();

    //Prompt for first command.
    while(input1.empty()){
        cout << "Command One (or quit): ";
        getline(cin, input1);
    }

    //Split the string by the space to get the pieces of the command.
    istringstream iss1(input1); 
    while (getline(iss1, s, ' ')) {
        arg1[carg1] = s;
        carg1++;
    }

    //Check if command is quit and exit if true.
    if(arg1[0].compare("quit") == 0){
        return 0;
    }

    //Prompt for command 2.
    while(input2.empty()){  
        cout << "Command Two: ";
        cin >> input2;
    }

    //Once again, split based on spaces.
    istringstream iss2(input2); 
    while (getline(iss2, s, ' ')) {
        //arg2.push_front(s);
        arg2[carg2] = s;
        carg2++;
    }

    //Initialize the pipe.
    int pipefd[2];
    if(pipe(pipefd) == -1){
        perror("Pipe");
        exit(EXIT_FAILURE);
    }

    //Create the fork to two processes.
    int pid = fork();

    //Switch to check for parent and child.
    switch(pid){
        case 0: //Child process
            //Close the read pipe and standard input.
            close(pipefd[0]);
            close(1);

            //Copy data
            dup(pipefd[1]);

            //Close other end of the pipe
            close(pipefd[1]);

            //Execute the first command. Based on how many params, call different ones.
            switch(carg1){
                case 1:
                    execlp(arg1[0].c_str(), arg1[0].c_str(), (char*)NULL);
                    break;
                case 2:
                    execlp(arg1[0].c_str(), arg1[0].c_str(), arg1[1].c_str(), (char*)NULL);
                    break;
                case 3:
                    execlp(arg1[0].c_str(), arg1[0].c_str(), arg1[1].c_str(), arg1[2].c_str(), (char*)NULL);
                    break;
                case 4:
                    execlp(arg1[0].c_str(), arg1[0].c_str(), arg1[1].c_str(), arg1[2].c_str(), arg1[3].c_str(), (char*)NULL);
                    break;
                case 5:
                    execlp(arg1[0].c_str(), arg1[0].c_str(), arg1[1].c_str(), arg1[2].c_str(), arg1[3].c_str(), arg1[4].c_str(), (char*)NULL);
                    break;
                case 6:
                    execlp(arg1[0].c_str(), arg1[0].c_str(), arg1[1].c_str(), arg1[2].c_str(), arg1[3].c_str(), arg1[4].c_str(), arg1[5].c_str(), (char*)NULL);
                    break;
                case 7:
                    execlp(arg1[0].c_str(), arg1[0].c_str(), arg1[1].c_str(), arg1[2].c_str(), arg1[3].c_str(), arg1[4].c_str(), arg1[5].c_str(), arg1[6].c_str(), (char*)NULL);
                    break;
            }
            return 0;
        case -1: //Error
            perror("fork");
            exit(EXIT_FAILURE);
        default: //Parent Process
            //Wait for initial command to execute.
            wait(&pid);

            //Fork into two processes.
            int pid2 = fork();

            //Switch based on child and parent.
            switch(pid2){
                case 0: //Child process
                    //Close write end of pipe and standard output.
                    close(pipefd[1]);
                    close(0);

                    //Duplicate to standard input
                    dup(pipefd[0]);

                    //Close read end.
                    close(pipefd[0]);

                    //Execute proper command based on params
                    switch(carg2){
                        case 1:
                            execlp(arg2[0].c_str(), arg2[0].c_str(), (char*)NULL);
                            break;
                        case 2:
                            execlp(arg2[0].c_str(), arg2[0].c_str(), arg2[1].c_str(), (char*)NULL);
                            break;
                        case 3:
                            execlp(arg2[0].c_str(), arg2[0].c_str(), arg2[1].c_str(), arg2[2].c_str(), (char*)NULL);
                            break;
                        case 4:
                            execlp(arg2[0].c_str(), arg2[0].c_str(), arg2[1].c_str(), arg2[2].c_str(), arg2[3].c_str(), (char*)NULL);
                            break;
                        case 5:
                            execlp(arg2[0].c_str(), arg2[0].c_str(), arg2[1].c_str(), arg2[2].c_str(), arg2[3].c_str(), arg2[4].c_str(), (char*)NULL);
                            break;
                        case 6:
                            execlp(arg2[0].c_str(), arg2[0].c_str(), arg2[1].c_str(), arg2[2].c_str(), arg2[3].c_str(), arg2[4].c_str(), arg2[5].c_str(), (char*)NULL);
                            break;
                        case 7:
                            execlp(arg2[0].c_str(), arg2[0].c_str(), arg2[1].c_str(), arg2[2].c_str(), arg2[3].c_str(), arg2[4].c_str(), arg2[5].c_str(), arg2[6].c_str(), (char*)NULL);
                            break;
                    }
                    return 0;
                case -1: //Error
                    perror("fork");
                    exit(EXIT_FAILURE);
                default: //Parent Process
                    //wait(&pid2);
                    break;
            }
    }   
}
}

出力例:

nick@nick-VirtualBox ~/Documents/Assign10 $ ./z1615629
Command One (or quit): ls -l
Command Two: wc
Command One (or quit): Command One (or quit): quit

出力例:

nick@nick-VirtualBox ~/Documents/Assign10 $ ./z1615629
Command One (or quit): ls -l
Command Two: cat
Command One (or quit): Command One (or quit): 
total 32
-rwxr-xr-x 1 nick nick 13358 Nov 20 15:46 z1615629
-rw-r--r-- 1 nick nick  4544 Nov 20 15:46 z1615629.cxx
-rw-r--r-- 1 nick nick  8104 Nov 20 15:46 z1615629.o
4

2 に答える 2

1

関数を使用しないため、コマンド プロンプトと読み取りループで非対称の動作が発生します。

//Prompt for first command.
while (input1.empty()){
    cout << "Command One (or quit): ";
    getline(cin, input1);
}

...

//Prompt for command 2.
while (input2.empty()){  
    cout << "Command Two: ";
    cin >> input2;
}

2 番目のコマンドには、1 つの単語しか含まれていません。改行が取り残され、次のサイクルで二重のプロンプトが表示されます。getline(cin, input2)2 番目のプロンプト ループで使用します。関数を使用すると、一貫性が得られます — 関数は人生を難しくするのではなく、楽にします。

親プロセスのパイプを閉じる必要があります。また、次の場所で行う必要がありますwait()

          default: //Parent Process
                //wait(&pid2);
                break;

使用:

          default: // Parent process
               close(pipefd[0]);
               close(pipefd[1]);
               while (wait(0) != -1)
                   ;
               break;
于 2012-11-20T22:39:49.987 に答える
1

質問に対応していないことはわかっていますが、C++ 化された元のコードを次に示します。

C++03 との互換性を維持するように注意しました。バインドには TR1 のみを想定しています (ただし、me​​m_fun_ref を使用した呪文は非常に簡単に記述できるはずです)。

サイズの縮小に注意してください: 88 LoC (>50%) を削除します

#include <iostream>
#include <string>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sstream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <tr1/functional>
using namespace std;

void execute(std::vector<string> const& arg1) {
    vector<char const*> argv(arg1.size());
    transform(arg1.begin(), arg1.end(), argv.begin(), tr1::bind(&std::string::c_str, tr1::placeholders::_1));
    argv.push_back(NULL);
    execvp(argv[0], (char* const*) &argv[0]); // TODO FIXME error handling?
    exit(EXIT_FAILURE);
}

std::vector<string> getinput(std::string prompt) {
    vector<string> result;
    string input;
    //Prompt for first command.
    while(input.empty()) {
        cout << prompt;
        getline(cin, input);
    }
    //Split the string by the space to get the pieces of the command.
    {
        istringstream iss(input);
        copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(result));
    }
    return result;
}

int main() {
    //Loop until quit.
    while(true) {
        const std::vector<string> cmd1 = getinput("Command One (or quit): ");
        if(cmd1.empty() || cmd1[0] == "quit") {
            return 0;
        }
        const std::vector<string> cmd2 = getinput("Command Two: ");

        //Initialize the pipe.
        int pipefd[2];
        if(pipe(pipefd) == -1) {
            perror("Pipe");
            exit(EXIT_FAILURE);
        }
        int pid = fork();               //Create the fork to two processes.
        switch(pid) {                   // Switch to check for parent and child.
            case 0:                     // Child process
                close(pipefd[0]);       // Close the read pipe and standard input.
                close(1);
                dup(pipefd[1]);         // Copy data
                close(pipefd[1]);       // Close other end of the pipe
                execute(cmd1);
                return 0;
            case -1:                    // Error
                perror("fork");
                exit(EXIT_FAILURE);
            default:                    // Parent Process
                wait(&pid);             // Wait for initial command to execute.
                int pid2 = fork();      // Fork into two processes.
                switch(pid2) {          // Switch based on child and parent.
                case 0:                 // Child process
                    close(pipefd[1]);   // Close write end of pipe and standard output.
                    close(0);
                    dup(pipefd[0]);     // Duplicate to standard input
                    close(pipefd[0]);   // Close read end.
                    execute(cmd2);      // Execute proper command based on params
                    return 0;
                case -1:                // Error
                    perror("fork");
                    exit(EXIT_FAILURE);
                default:                // Parent Process
                    //wait(&pid2);
                    break;
                }
        }
    }
}

免責事項これはコンパイルされますが、実行していません (どの入力をどのようにフィードするかはわかりません)。

于 2012-11-20T22:48:23.133 に答える