没有正确读取字符串

时间:2013-04-17 13:40:50

标签: c++ string

我在练习用户输入处理。我的目标是让用户输入由空格(“”)分隔的整数行,将它们作为整数读取,存储它们并在以后处理它们。我偶然发现了一个有趣的问题(我的意见中的Atleast),我的方式似乎总是没有读取用户输入的最后一个数字。我将在这里发布整个程序(因为有一些额外的libreries包括在内)。 我在程序中留下了一些评论

#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>

using namespace std;

int main()
{
    //this vector will store the integers
    vector<int> a;
    // this will store the user input
    string inp;
    getline(cin, inp);
    // this string will temporarily store the digits
    string tmp;
    //be sure that the reading part is okay
    cout << inp << endl;
     //until you meet something different than a digit, read char by char and add to string
     for(int i = 0; i < inp.length(); i++)
    {
        if(isdigit(inp[i]))
        {
            tmp +=inp[i];
        }
        else
        {
            // when it is not a character, turn to integer, empty string
            int value = atoi(tmp.c_str());
            a.push_back(value);
            tmp = "";
        }
    }
    // paste the entire vector of integers
    for(int i = 0; i < a.size(); i++)
    {
        cout << a[i] << endl;
    }
    return 0;
}

9 个答案:

答案 0 :(得分:6)

替换此行

for(int i = 0; i <inp.length(); i++)

通过

for(int i = 0; i <= inp.length(); i++)

DEMO IDEONE

您的代码存在的问题是:只要 i = 7 tmp = 46 ,示例25 30 46你没有在向量中推送46 ,因为inp[8]是换行符,所以你的for循环在我变为7后终止。

请注意 i&lt; = inp.length()在大多数编译器中运行完美,因为\ 0被用作/被视为sentinel。但是,编译器很少(如Microsoft Visual C ++)可能会显示Assertion错误:字符串下标超出范围。

答案 1 :(得分:3)

如果该行的最后一位是数字,则不会在最后一次迭代中点击else,并且最后一个数字永远不会被推入vector。 最简单的解决方案是在循环之后复制非数字逻辑:

 if (!tmp.empty()) // If tmp has content, we need to put it in the vector.
 {
        int value = atoi(tmp.c_str());
        a.push_back(value);
        tmp = "";
 }

虽然我确信你能想出一种更好的结构方法。

以下是我使用std::stringstream提出的版本,这也避免了atoi

int main()
{
    std::vector<int> ints;
    std::string line;
    std::getline (std::cin, line);
    std::cout << "Read \"" << line << "\"\n";
    std::stringstream ss(line);

    int remaining = line.size();
    while (remaining)
    {
        if(std::isdigit(ss.peek())) // Read straight into an int
        {
            int tmp;
            ss >> tmp;
            ints.push_back(tmp);
        }
        else
        {
            ss.get(); // Eat useless characters
        }

        remaining = line.size()-ss.tellg();
    }

    for (auto i : ints)
        std::cout << i << '\n';

    return 0;
}

运行:

$ ./a.out <<< "12 34 56"
Read "12 34 56"
12
34
56

请注意,这是专门用于处理数字之间任何旧的乱码:

$ ./a.out <<< "12-abc34-56"
Read "12-abc34-56"
12
34
56

如果只有空格,这就更容易了,因为从int读取stringstream会自动忽略它。在这种情况下,您只需要:

int tmp;
while (ss >> tmp)
{
    ints.push_back(tmp);
}

答案 2 :(得分:1)

您的程序需要一个以非数字字符结尾的字符串才能正常工作。尝试使用此字符串“1 12 14587 15”,因为在算法中忘记了最后一个空格时,程序会将数字存储到tmp字符串中,但不将其保存到向量中。要纠正这一点,您需要在第一次循环后添加最后一次push_back。

答案 3 :(得分:1)

只有在找到非数字时,才会使用新值更新a。因此,如果您的字符串以数字结尾,tmp将包含数字字符串,但您永远不会得到应该执行push_back的其他字符串。您可以通过在for循环

之后添加以下代码来解决此问题
if(!tmp.empty()){
    // when it is not a character, turn to integer, empty string
    int value = atoi(tmp.c_str());
    a.push_back(value);
    tmp = "";
}

答案 4 :(得分:1)

在开始循环之前,在字符串中添加一个空格以确保推送最后一个数字:inp.push_back(' ')

答案 5 :(得分:1)

在读取最后一位数字后,您的循环结束,因此最后一位数字永远不会变为整数。只需在原始for循环之后添加一些代码。

for(int i = 0; i < inp.length(); i++)
{
    /* ...... */
}
// add this to read the last digit
if(tmp.length() > 0){
    int value = atoi(tmp.c_str());
    a.push_back(value);
    tmp = "";
}

答案 6 :(得分:0)

你永远不会推迟你的最后一个价值。例如,考虑这个输入

40 36

然后在你读书的时候,你会向第一个空间推回去。但你永远不会推36,因为没有更多的角色。

for()循环结束后,您可以尝试:

if(!tmp.empty()) {
  a.push_back(tmp);
}

答案 7 :(得分:0)

当最后一个数字的最后一个数字存储在tmp中之后,循环结束,因为您已经读取了整个字符串的最后一个字符。当循环结束时,tmp仍包含最后一个数字。

1)您可以在循环后转换并将最后一个数字添加到矢量。最后一个数字仍然可以在tmp。

中找到

2)或者你可以在循环之前在字符串的末尾显式添加非数字字符。

答案 8 :(得分:0)

你省略了输入。更改您的代码以反映这一点:

   //this vector will store the integers
    vector<int> a;
    // this will store the user input
    string inp;
    getline(cin, inp);
    // this string will temporarily store the digits
    string tmp;
    //be sure that the reading part is okay
    cout << inp << endl;
     //until you meet something different than a digit, read char by char and add to string
     for(int i = 0; i < inp.length(); i++)
    {
        if(isdigit(inp[i]))
        {
            tmp =inp[i];
            int value = atoi(tmp.c_str());
            a.push_back(value);
        }
        else
        {
            tmp = "";
        }
    }
    // paste the entire vector of integers
    for(int i = 0; i < a.size(); i++)
    {
        cout << a[i] << endl;
    }
    return 0;

或循环替换:for(int i = 0; i <inp.length(); i++)

通过

for(int i = 0; i <= inp.length(); i++)