1

プログラムで次の2つの文字列を解析できる必要があります。

cat myfile || sort
more myfile || grep DeKalb

文字列はcharbuffer[1024]に保存されています。最終的に必要なのは、左側のchar配列へのポインターと、右側のchar配列へのポインターです。これを使用して、それぞれの側で以下を呼び出すことができます。

int execvp(const char *file, char *const argv[]); 

上記の2つの文字列が文字バッファcharbuffer[1024]に保存されている場合、execvpコマンドの正しい引数を取得する方法については誰でもアイデアがあります。?

左側の最初の単語を保持するためにchar*leftが必要であり、次に左側の両方の単語を保持するためにchar * constleftArgv[]が必要です。それから私は権利のために同じものが必要です。私は今2時間ほどstrtokをいじっていて、壁にぶつかっています。誰かアイデアはありますか?

4

3 に答える 3

1

std :: getline(stream、stringToReadInto、delimeter)を使用できます。

私は個人的に、次のようないくつかの追加機能が組み込まれた独自の関数を使用しています。

StringList Seperate(const std::string &str, char divider, SeperationFlags seperationFlags, CharValidatorFunc whitespaceFunc)
{
    return Seperate(str, CV_IS(divider), seperationFlags, whitespaceFunc);
}

StringList Seperate(const std::string &str, CharValidatorFunc isDividerFunc, SeperationFlags seperationFlags, CharValidatorFunc whitespaceFunc)
{
    bool keepEmptySegments     = (seperationFlags & String::KeepEmptySegments);
    bool keepWhitespacePadding = (seperationFlags & String::KeepWhitespacePadding);

    StringList stringList;

    size_t startOfSegment = 0;
    for(size_t pos = 0; pos < str.size(); pos++)
    {
        if(isDividerFunc(str[pos]))
        {
            //Grab the past segment.
            std::string segment = str.substr(startOfSegment, (pos - startOfSegment));
            if(!keepWhitespacePadding)
            {
                segment = String::RemovePadding(segment);
            }

            if(keepEmptySegments || !segment.empty())
            {
                stringList.push_back(segment);
            }

            //If we aren't keeping empty segments, speedily check for multiple seperators in a row.
            if(!keepEmptySegments)
            {
                //Keep looping until we don't find a divider.
                do
                {
                    //Increment and mark this as the (potential) beginning of a new segment.
                    startOfSegment = ++pos;

                    //Check if we've reached the end of the string.
                    if(pos >= str.size())
                    {
                        break;
                    }
                }
                while(isDividerFunc(str[pos]));
            }
            else
            {
                //Mark the beginning of a new segment.
                startOfSegment = (pos + 1);
            }
        }
    }

    //The final segment.
    std::string lastSegment = str.substr(startOfSegment, (str.size() - startOfSegment));
    if(keepEmptySegments || !lastSegment.empty())
    {
        stringList.push_back(lastSegment);
    }

    return stringList;
}

ここで、'StringList'はstd:: vectorのtypedefであり、CharValidatorFuncは、1つのcharを受け取り、boolを返す関数の関数ポインター(実際には、ファンクターとラムダのサポートを可能にするstd :: function)です。次のように使用できます。

StringList results = String::Seperate(" Meow meow , Green, \t\t\nblue\n   \n, Kitties!", ',' /* delimeter */, DefaultFlags, is_whitespace);

そして、結果を返します:{"Meow meow"、 "Green"、 "blue"、 "Kitties!"}

'Meow meow'の内部空白を保持しますが、変数を囲むスペースとタブおよび改行を削除し、コンマで分割します。

(CV_ISは、文字列リテラルとして取得された特定の文字または文字の特定のコレクションを照合するためのファンクターオブジェクトです。文字検証関数を組み合わせるためのCV_ANDおよびCV_ORもあります)

文字列リテラルの場合、極端なパフォーマンスが必要な場合を除いて、std :: string()に入れてから、関数に渡します。デリメータを壊すのはかなり簡単です-上記の関数は私のプロジェクトの典型的な使用法と要件に合わせてカスタマイズされていますが、自由に変更して自分で主張してください。

于 2013-03-20T02:11:17.737 に答える
1

正規表現についてもっと学ぶことをお勧めします。また、問題を簡単に解決するために、強力な正規表現エンジンを提供するBoost.Regexライブラリを利用できます。解決策はほんの数行のコードですが、自分でそれを行うことをお勧めします-それは良い練習になるでしょう。それでも問題が解決しない場合は、いくつかの結果を返して、行き詰まった場所を明確に述べてください。

于 2013-03-20T01:51:34.387 に答える
0

これが他の誰かに悲しみを与える場合、これは私が問題を解決した方法です:

//variables for the input and arguments
char *command[2];
char *ptr;
char *LeftArg[3];
char *RightArg[3];

char buf[1024]; //input buffer

//parse left and right of the ||
number = 0;
command[0] = strtok(buf, "||");

//split left and right
while((ptr=strtok(NULL, "||")) != NULL)
{
    number++;
    command[number]=ptr;
}

//parse the spaces out of the left side
number = 0;
LeftArg[0] = strtok(command[0], " ");

//split the arguments
while((ptr=strtok(NULL, " ")) != NULL)
{
    number++;
    LeftArg[number]=ptr;
}

//put null at the end of the array
number++;
LeftArg[number] = NULL;

//parse the spaces out of the right side
number = 0;
RightArg[0] = strtok(command[1], " ");

//split the arguments
while((ptr=strtok(NULL, " ")) != NULL)
{
        number++;
        RightArg[number]=ptr;
}

//put null at the end of the array
number++;
RightArg[number] = NULL;

これで、配管を正しく行った後、コマンドでLeftArgとRightArgを使用できます。

execvp(LeftArg[0], LeftArg);//execute left side of the command

次に、コマンドの右側にパイプして実行します

execvp(RightArg[0], RightArg);//execute right side of command
于 2013-03-20T14:57:23.373 に答える