1

我需要能够在我的程序中解析以下两个字符串:

cat myfile || sort
more myfile || grep DeKalb

字符串被保存在字符缓冲区 [1024] 中。我最终需要的是一个指向左侧的 char 数组的指针和一个指向右侧的 char 数组的指针,以便我可以使用它们为每一侧调用以下内容:

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

如果上面的两个字符串保存在字符缓冲区 char buffer[1024] 中,任何人都知道如何为 execvp 命令获取正确的参数;?

我需要 char *left 来保存左侧的第一个单词,然后 char *const leftArgv[] 来保存左侧的两个单词。然后我需要同样的东西来做正确的事情。我已经在 strtok 上玩了两个小时了,我正在碰壁。有人有想法么?

4

3 回答 3

1

我建议您了解更多关于正则表达式的知识。为了轻松解决您的问题,您可以使用Boost.Regex库,它提供了强大的正则表达式引擎。解决方案只是几行代码,但我鼓励你自己做——这将是一个很好的练习。如果您仍然有问题,请返回一些结果并明确说明您卡在哪里。

于 2013-03-20T01:51:34.387 回答
1

您可以使用 std::getline(stream, stringToReadInto, demeter)。

我个人使用我自己的函数,其中包含一些附加功能,如下所示:

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 是一个函数指针(实际上是 std::function 允许仿函数和 lambda 支持),用于一个函数,该函数采用一个字符并返回一个布尔值。它可以像这样使用:

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

并会返回结果:{"Meow meow", "Green", "blue", "Kitties!"}

保留“喵喵”的内部空白,但删除变量周围的空格、制表符和换行符,并以逗号分隔。

(CV_IS 是一个仿函数对象,用于匹配特定字符或作为字符串文字的特定字符集合。我还有 CV_AND 和 CV_OR 用于组合字符验证器函数)

对于字符串文字,我只需将其放入 std::string() 中,然后将其传递给函数,除非需要极高的性能。打破分隔符很容易自己滚动 - 上述功能只是根据我的项目的典型用法和要求定制的,但您可以随意修改它并为自己声明。

于 2013-03-20T02:11:17.737 回答
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 回答