我在练习用户输入处理。我的目标是让用户输入由空格(“”)分隔的整数行,将它们作为整数读取,存储它们并在以后处理它们。我偶然发现了一个有趣的问题(我的意见中的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;
}
答案 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++)