保存结果时,按分隔符拆分char数组?

时间:2013-03-20 01:41:37

标签: c++ c delimiter strtok execvp

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

cat myfile || sort
more myfile || grep DeKalb

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

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

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

我需要char * left来保持左侧的第一个单词,然后char * const leftArgv []来保留左侧的两个单词。然后我需要同样的东西。我现在已经和strtok搞乱了两个小时,我正在撞墙。有人有什么想法吗?

3 个答案:

答案 0 :(得分:1)

我建议您详细了解regular expressions。为了无痛地解决您的问题,您可以使用提供强大的正则表达式引擎的Boost.Regex库。解决方案只是几行代码,但我鼓励你自己做 - 这将是一个很好的练习。如果您仍然遇到问题,请回过头来查看结果,并明确说明您被困的地方。

答案 1 :(得分: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是一个函数指针(实际上,std :: function允许函子和lambda支持)一个函数拿一个char,并返回一个bool。它可以像这样使用:

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

并会返回结果: {“喵喵”,“绿色”,“蓝色”,“小猫!”}

保留'Meow meow'的内部空白,但删除变量周围的空格和制表符以及换行符,并用逗号分隔。

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

对于字符串文字,我只是把它扔进std :: string()然后将它传递给函数,除非需要极端的性能。打破delimeters相当容易自己动手 - 上面的功能只是根据我的项目的典型用法和要求进行定制,但可以随意修改并自行声明。

答案 2 :(得分: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