将包含数字的字符串解析为整数数组

21

给定一个由数字组成的字符串作为输入,我想在C++中将其转换为整数数组。

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

using std::string;
using std::stringstream;
using std::cout;
using std::endl;

int main(int argc,char** argv) {

    string num="-24 2 90 24 50 76";

    stringstream stream(num);

    while(stream){
        int n;
        stream>>n;
        cout<<n<<endl;
    }

    return 0;
}

输出(GCC) :

-24 2 90 24 50 76 76

为什么我得到了额外的值,如何高效地将它们转换为整数数组?

更新:

如果字符串流中包含除空格以外的定界符,该如何解析它们? 例如: string num="-24,2,90,24,50,76";


不,将它们存储在向量中是一个很好的方法,可以使它们进入某些方面上等同于数组的东西。 - Mats Petersson
3个回答

22

在成功解析时,文件结束条件不会被设置,你需要在解析后检查流的状态。

第二个76基本上只是纯粹的偶然。解析失败会让目标操作数不受影响,并且因为你没有初始化n,它可以是任何值。

快速修复:

stream>>n;
if (stream)
    cout<<n<<endl;

一个更加简洁的解决方案:
int n;
while(stream >> n){
    cout<<n<<endl;
}

如果元素数量未知,存储这些整数的规范方式是使用 std::vector。以下是一个使用示例:

std::vector<int> values;
int n;
while(stream >> n){
    ...do something with n...
    values.push_back(n);
}

然而,您可以在流上使用迭代器,并使用以下内容:

// Use std::vector's range constructor
std::vector<int> values(
     (std::istream_iterator<int>(stream)), // begin
     (std::istream_iterator<int>()));      // end

1
实际上,这个值并没有被定义为未定义的。对于数字输入转换,标准保证如果有错误发生,目标变量将不会被修改。因此,他能够看到最后读取的值。 - James Kanze
而且重要的一点是,他在没有检查输入是否成功的情况下使用了该值。(这在您的代码中是隐含的,但明确说明是值得的。) - James Kanze
3
最后,如果你想要一个整型向量,标准的方法是:std::vector<int> values( (std::istream_iterator<int>(stream)), (std::istream_iterator<int>()) );。没有循环,没有push_back,所有操作都在构造函数中完成。 - James Kanze
2
@JamesKanze:但是它是未定义的,因为n没有被初始化;我稍微详细解释了一下。第二个和第三个点很好,很高兴你审查了我的答案。 - Sebastian Mach
啊,是的。因为他每次都定义了一个新的n。我想到的是类似于int n; while ( !stream.eof() )这样的东西(我们经常看到)。 - James Kanze
显示剩余3条评论

5

使用向量处理以字符分隔的整数列表的另一种方法,甚至更简单,可能更像这样:

string str = "50,2,25,38,9,16";
vector<int> ints;
stringstream ss(str);
int n;
char ch;

while(ss >> n) {
    if(ss >> ch)
        ints.push_back(n);
    else
        ints.push_back(n);
}

那么,您可以先跳过任何字符分隔符(如果存在的话),然后再回到抓取整数并将它们添加到列表中(也就是列表末尾)。

那个内部的if语句是怎么回事?不管怎么样都一样吗? - Managarm

2

我不知道你是否已经找到了针对你更新的问题的答案。如果没有,你可以通过以下代码轻松解决:

for (string::iterator it = num.begin(); it != num.end(); ++it) {
    if (*it == ',') {
        *it = ' ';
    }
    else continue;
}

这段代码会将所有的冒号替换成空格,然后您就可以按照正常方式操作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接