我需要能够在程序中解析以下两个字符串:
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搞乱了两个小时,我正在撞墙。有人有什么想法吗?
答案 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