读取整数行而忽略不正确的数据(c ++)

时间:2012-03-31 17:37:39

标签: c++ stream

我正在使用istringstreams读取输入,以便从字符串转换为整数。我在阅读包含错误的行时遇到问题,例如“1 45 3 XXXX 45 X”,我希望它只是忽略这些字母。通常,我没有任何错误,我会做:

string s = "1 2 34 5 6";
istringstream stream(s);
int temp;

cout << s << " -> ";

while(stream >> temp){
    //do something with temp for ex:
    cout << temp << " ";
}

这会给出

 "1 2 34 5 6" -> 1 2 34 5 6

显然,当我有一个“1 45 3 XXXX 45 X”形式的字符串时,这不会起作用,因为它会在XXXX处断开而不会继续。但我想得到的是:

"1 45 3 XXXX 45 X" -> 1 45 3 45

所以,我知道这个问题,但我坚持如何解决它。我有这种感觉应该有一个非常简单的解决方案,但我无法弄清楚,并且我在网上搜索的大多数例子不会考虑数据中的错误或者根据我的需要太高级。

5 个答案:

答案 0 :(得分:4)

如果您要处理string并获得看似int的所有内容 - 请尝试以下方法:

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


int main() {
    std::string s = "1 45 3 XXXX 45 X 11111111111111111111 2.3";
    std::istringstream stream(s);
    int foo;

    while(true) {
        if(stream >> foo) {
            std::cout << foo << std::endl; // do something with the int
        } else if (stream.eof()) {
            break; // We're done
        } else {
            // We've hit a non-int
            stream.clear(); // clear the error flags
            stream.ignore(); // ignore everything till the delimeter
        }
    }
}

或者使用例外的版本:

int main() {
    std::string s = "1 45 3 XXXX 45 X 11111111111111111111 2.3";
    std::istringstream stream(s);
    stream.exceptions(std::ios::failbit | std::ios::badbit);
    int foo;

    while(!stream.eof()) {
        try {
            stream >> foo;
            std::cout << foo << std::endl;
        } catch (const std::ios::failure & e) {
            stream.clear();
            stream.ignore();
        }
    }
}

输出:

1
45
3
45
2
3

答案 1 :(得分:1)

在解析之前从字符串中删除任何不是数字或空格的内容可以解决您的问题。你考虑过吗?

这样的事情应该这样做。

void filter(string * input) {
    for(int i = 0; i < input->length(); i++) {
        char val = input->at(i);
        if (val != ' ' && !isdigit(val)) {
            // not a valid character
            input->erase(i, 1);
            i--;
        }
    }
}

答案 2 :(得分:0)

在传递给istringstrem之前过滤字符串中的字母,如下所示

string s = "1 2 34 xxx 5 6"; 
string data;

for (unsigned int i = 0; i < sizeof(s); i++)
{
  if ((std::isdigit(s[i])) || (s[i] = ' '))
  data += s[i];
}
istringstream stream(data); 
cout << data << " -> ";  

答案 3 :(得分:0)

您可以简单地将其转换为C样式字符串并扫描以查看是否至少有一个非数字。如果是这样,请打破&amp;不要打印字符串。

char *cstr;
bool flag = true;

while(stream >> temp){
    i=0;
    flag = true;
    cstr = new char[temp.size()+1];
    strcpy (cstr, temp.c_str());
    while(cstr[i]) {
     if(!isdigit(cstr[i])) { 
       flag = false;
       break;
     }
    i++;
    }
    if(flag) 
    cout << temp << " ";
}

不确定这是否是有效的方式,但我的猜测是,即使使用任何其他库函数,您可能必须以这种或那种方式进行等效扫描。所以我认为这很好。

答案 4 :(得分:0)

如果不受欢迎的文本(或更好,理想的整数)始终位于相同的位置,我只会使用sscanf()代替:

std::string s = "1 45 3 XXXX 45 X";
int temp[4] = {0}; 

cout << s << " -> "; 

sscanf(s.c_str(), "%d %d %d %*s %d", &temp[0], &temp[1], &temp[2], &temp[3]);

for(int i = 0; i < 4; ++i)
{ 
    cout << temp[i] << " "; 
}