使用strtok的C ++拆分字符串忽略最后一个条目

时间:2011-12-10 13:10:27

标签: c++ visual-studio

我有以下代码,用于分割字符串并将其插入数组:

 char *t; 
 char *tmpLine = (char *)line.c_str();
 t = strtok(tmpLine, "\t"); 
 int counter = 0;
 while(t != NULL) { 
     tempGrade[counter] = atoi(t);
     counter++;
     t = strtok(NULL, "\t"); 
 }

但由于某种原因,line的最后一个条目被忽略而未插入。也行是:

string line = "1 90 74 84 48 76 76 80 85"; 注意:空格是原始文件中的制表符空间(\ t)。

5 个答案:

答案 0 :(得分:5)

因为您已将此问题标记为C ++。我会说完全避免这样做,看看this接受的答案。

答案 1 :(得分:3)

你的代码错了,它会让我眼前一亮。

出了什么问题?

char *tmpLine = (char *)line.c_str();

首先,你是(除非我错了)丢弃了std :: string的常量,这是一个非常糟糕的主意。无论如何,抛弃修改尝试的常量气味......

t = strtok(tmpLine, "\t");

我们在这里......

您正在修改std::string提供的缓冲区,因为strtok会破坏为其提供的字符串。

不好主意:您不是std::string内部缓冲区的所有者,因此您不应该修改它(您不想破坏您的字符串,并引发错误,想要你吗?),

返回代码:

t = strtok(tmpLine, "\t");

好的,您正在使用strtok,这不是可重入的功能。

我不知道你正在使用什么编译器,但我想大多数会有更安全(即不那么愚蠢)的选择。例如,Visual C ++提供strtok_s。如果您没有提供,则最佳解决方案是编写您自己的strtok,或使用其他标记化API。

事实上,strtok是为数不多的反例之一,而不是重新发明轮子":在这种情况下,重写自己将永远比原来更好标准C函数,如果你有一些C或C ++经验。

好的,但是,关于原来的问题?

其他人提供了有关替代方案的见解,甚至是您提供的不完整代码示例似乎完整的事实,因此我将在此处停止我的分析,让您考虑他们的答案。

我不知道你的代码是什么,但这是完全错误的,即使你报告的错误(遗失的令牌)不存在也是如此。不要在生产代码上使用它。

答案 2 :(得分:2)

  

但你可以给我一个快速的黑客攻击吗?因为这不是一个重要的项目,我必须改变很多,就像在那个问题中那样做

不,你没有。假设tempGradeint数组,这会做同样的事情:

istringstream iss(line);
int counter = copy(istream_iterator<int>(iss),
         istream_iterator<int>(),
         tempGrade) - tempGrade;

但最好将tempGrade更改为vector并使用与Moo-Juice相关联的答案中的代码。

答案 3 :(得分:0)

正如其他人所说,我建议你采取the recommended C++ approach to this problem

但我尝试了你的代码,我不知道它有什么问题。我不会在我的问题上重复你的问题:

  

1
  90个
  74个
  84个
  48个
  76个
  76个
  80个
  85

也许您打印循环的迭代太短,或者您的tempGrade数组太小?或许你最后的“标签”可能不是一个标签字符?

这是我编译以检查此代码的代码。

#include<iostream>

int main(int argc, char* argv[])
{
    std::string line = "1\t90\t74\t84\t48\t76\t76\t80\t85";
    char *t; 
    char *tmpLine = (char *)line.c_str();
    t = strtok(tmpLine, "\t"); 
    int counter = 0;
    int tempGrade[9];
    while(t != NULL) { 
        tempGrade[counter] = atoi(t);
        counter++;
        t = strtok(NULL, "\t"); 
    }
    for(int i = 0; i < 9; ++i) {
        std::cout << tempGrade[i] << "\n";
    }
}

答案 4 :(得分:0)

这是一个非常简单的示例,展示了如何使用流提取运算符和vector以更惯用的C ++方式执行此操作:

#include <string>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

void parse(string line)
{
    stringstream stream(line);
    int score;
    vector<int> scores;
    while (stream >> score)
        scores.push_back(score);

    for (vector<int>::iterator itr = scores.begin(); itr != scores.end(); ++itr)
        cout << *itr << endl;
}

int main(int argc, char* argv[])
{
    parse("1\t90\t74\t84\t48\t76\t76\t80\t85");
    return 0;
}