0

所以,我正在尝试编写一个返回 a 的函数vector<char**>,如下所示:

vector<char**> test(string mystr) {

  char*temp=new char[mystr.size()+1];

  strcpy(temp,mystr.c_str());

  char*subStr=strtok(temp,":");

  while(subStr!=NULL) {

    int i=0;

    char**args=new char*[200];

    char*tempsta=newchar[strlen(subStr)+1];

    strcpy(tempsta, subStr);

    args[i]=strtok(tempsta," ");

    while(args[i]!=NULL) {

      i++;

      args[i]=strtok(NULL," ");

    }

    fullVec.push_back(args);

    //cout<<subStr<<endl;

    subStr=strtok(NULL,":");

  }
return fullVec;
}

所以我想用分隔符split把参数串起来":",然后用“”分隔符。在cout<<subStr通话中,如果我注释掉从int i=0到的所有内容,我会得到预期的结果fullVec.push_back(args)。如果我不注释掉所有这些行,我只会得到第一行substring(直到遇到第一个“:”),然后最大的 while 循环退出。

我的意思是预期的;让我们假设参数是“我的名字是:bon jovi:xxx ab”,如果所有内容都被注释掉,将打印以下行:

my name is
 bon jovi
 xxx ab

如果我保持原样,将会发生的只是

my name is

将打印,大循环将退出

任何帮助表示赞赏,谢谢!(是的,我知道这似乎是一个愚蠢的练习,可以更优雅/更轻松地完成......但是我希望在我使用字符串等娱乐之前让这个解决方案起作用。)

4

3 回答 3

3

您的问题是 strtok() 在调用之间保持状态。

如果第一个参数不为 NULL,则它用于重置状态,否则它使用已保存的状态从中断处继续解析。

由于您有两个对 strtok() 的嵌套调用,因此第二个调用弄乱了外部调用的状态。

这个电话:

args[i]=strtok(tempsta," ");

正在重置 strtok() 的内部状态。它现在不再知道你的外部调用中的任何状态。因此,当您到达内部循环中的字符串末尾时。

这个电话:

subStr=strtok(NULL,":");

现在正在使用内循环的已保存状态。因此,它基本上只是在您已经到达该标记化流的末尾时终止。

于 2013-02-16T17:34:13.210 回答
2

正如Loki已经完美指出的那样,您不应该混合使用 C 和 C++。如果您需要 C++ 解决方案来解决您的问题,那么最好坚持使用 STL 类来为您处理丑陋的内存管理(参见RAII idiom),例如std::string, std::vector, std::istringstream.

这就是您的函数的样子:

typedef std::vector<std::string> Line;

std::vector<Line> parse(std::string inputString)
{
    std::vector<Line> lines;
    std::istringstream inputStream(inputString);
    for (std::string line; std::getline(inputStream, line, ':'); )
    {
        if (!line.empty())
        {
            lines.push_back(Line());
            std::istringstream lineStream(line);
            for (std::string word; std::getline(lineStream, word, ' '); )
            {
                if (!word.empty())
                    lines.back().push_back(word);
            }
        }
    }
    return lines;
}

使用示例:

std::vector<Line> lines = parse("my name is: bon jovi: xxx ab");

for (int li = 0; li < lines.size(); ++li)
{
    for (int wi = 0; wi < lines[li].size(); ++wi)
        std::cout << lines[li][wi] << "_";
    std::cout << std::endl;
}

输出

my_name_is_
bon_jovi_
xxx_ab_

希望这可以帮助 :)

于 2013-02-16T17:56:51.853 回答
0

正如评论中提到的,您正在混合 C 风格和 C++ 风格的代码,这会导致相当混乱。除非你有“充分的理由”来char* 代替std::stringthen ,否则最好使用stlor boost

boost方式:

std::string delims = " :";
boost::split(vector, mystr, boost::is_any_of(delims));

stl方式:

  vector<string> result;
  std::string delims = " :";
  std::istringstream ss( mystr );
  while (!ss.eof())
  {
    getline( ss, field, delims);
    if ((empties == split::no_empties) && field.empty()) continue;
    result.push_back( field );
  }

有关更多方法和良好比较,请参阅此cplusplus 文章

于 2013-02-16T17:41:02.043 回答