C++ 如何正确使用getline
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21500292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to use getline correctly
提问by DanielV
I wrote a program that uses getline()
function, but I don't know how should I use getline()
in the correct way. I've searched it on the Internet but I just found something about about using getchar()
with getline()
or cin.ignore()
. I tried and none of them worked and I don't know what is the problem and why getline()
function needs getchar()
or cin.ignore()
to work correctly?
我写了一个使用getline()
函数的程序,但我不知道我应该如何getline()
以正确的方式使用。我在互联网上搜索过它,但我刚刚找到了一些关于使用getchar()
withgetline()
或 的信息cin.ignore()
。我试过,但没有一个工作,我不知道是什么问题,为什么getline()
功能需要getchar()
或cin.ignore()
正常工作?
My Input
我的输入
2
Alderaan
1000.00 2000.00 3000.00
Dantooine
-1000.00 1000.00 1000.00
Circarpous Major
-500.00 500.00 -500.00
Y'Toub
-500.00 -500.00 500.00
here is my code:
这是我的代码:
#include <cmath>
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
long long int x, y, z, x1, y1, z1;
int n;
cin >> n;
string s, p;
while (n--)
{
getline(cin, s);
cin >> x;
cin >> y;
cin >> z;
cin.ignore();
getline(cin, p);
cin >> x1;
cin >> y1;
cin >> z1;
cin.ignore();
printf("%s to %s: %.2f\n", s.c_str(), p.c_str(), sqrt(pow(x - x1, 2) + pow(y - y1, 2) + pow(z - z1, 2)));
}
}
回答by Dietmar Kühl
The code mixes formatted input (i.e. using the >>
operator for input) with unformatted input (in this case using std::getline()
). Unformatted input does notskip leading whitespace while formatted input does skip leading whitespace. In both cases reading stops as soon as the input is the next character wouldn't fit the format.
该代码将格式化输入(即使用>>
运算符进行输入)与未格式化输入(在本例中使用std::getline()
)混合在一起。未格式化的输入并不会跳过前导空白,而格式化输入不跳过前导空白。在这两种情况下,只要输入的下一个字符不符合格式,就会停止读取。
For example, reading a double
when the input is 3000.00\n...
stops after reading the last 0
because the '\n
doesn't fit the double
s format. The next character in the stream is, thus, a \n
. The function std::getline()
reads until it finds the first \n
which is immediately: it extracts that one character and [successfully] produces an empty line. With your input the sequence Dantooine
is next but doesn't fit the format of a double
and the stream goes into fail state.
例如,在读取最后一个后停止double
输入时读取 a ,因为 '不适合s 格式。因此,流中的下一个字符是 a 。该函数一直读取,直到找到第一个立即出现的字符:它提取该字符并[成功] 生成一个空行。随着您的输入,序列是下一个,但不符合 a 的格式,并且流进入失败状态。3000.00\n...
0
\n
double
\n
std::getline()
\n
Dantooine
double
The simple fix is to always skip leading white space when switching from formatted input to unformatted input, e.g., using the std::ws
manipulator:
简单的解决方法是在从格式化输入切换到未格式化输入时始终跳过前导空格,例如,使用std::ws
操纵器:
std::getline(std::cin >> std::ws, s);
Whether this is suitable depends a bit on what you are trying to read. If the strings you want to read can start with a whitespace, you would need to be a bit more careful and, e.g., only extract whitespace up to the next newline:
这是否合适取决于您要阅读的内容。如果您要读取的字符串可以以空格开头,则需要更加小心,例如,只提取空格直到下一个换行符:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
(just ignoring one character may not work, e.g., if the input of the line ends in 3000.00 \n
).
(仅忽略一个字符可能不起作用,例如,如果该行的输入以 结尾3000.00 \n
)。
Reading 3000.00
as long
actually stops at the .
, i.e., the first change to your program is to correct the type of values read to be double
rather than long
. Note that you should also alwayscheck that your input was successful before processing it. That is, I would actually use something like this:
读取3000.00
aslong
实际上停在.
,即,对程序的第一个更改是将读取的值的类型更正为 ,double
而不是long
。请注意,在处理输入之前,您还应该始终检查输入是否成功。也就是说,我实际上会使用这样的东西:
double x0, y0, z0, x1, y1, z1;
std::string l0, l1;
while (0 < n--
&& std::getline(std::cin >> std::ws, l0)
&& std::cin >> x0 >> y0 >> z0
&& std::getline(std::cin >> std::ws, l1)
&& std::cin >> x1 >> y1 >> z1) {
// do something with the input
}
回答by timrau
cin >> z
does not consume the \n
character. Thus you need a cin.ignore()
to consume the newline character and make the next getline()
reading the line you want. The same issue also happens on cin >> z1
.
cin >> z
不消耗\n
角色。因此,您需要使用 acin.ignore()
来使用换行符并使下一次getline()
阅读您想要的行。同样的问题也发生在cin >> z1
.
回答by Kerrek SB
It's best not to mix token and line extraction. Just use string streams if you want to tokenize a line. I'd try this:
最好不要混合令牌和行提取。如果您想标记一行,只需使用字符串流。我会试试这个:
#include <string>
#include <sstream>
#include <iostream>
std::string n_str; // for the first number, parse it later
if (!std::getline(std::cin, n_str))
{
// error, die
}
for (std::string name, numbers;
std::getline(std::cin, name) && std::getline(std::cin, numbers); )
{
std::istringstream iss(numbers);
double x, y, z;
if (!(iss >> x >> y >> z >> std::ws) || iss.get() != EOF)
{
// parse error, die
}
// "name", "x", "y", "z" are usable now
}
回答by shajib0o
try it
尝试一下
#include <cmath>
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
long long int x, y, z, x1, y1, z1;
int n;
cin >> n;
string s, p;
while (n--)
{
cin.ignore();
cin.clear();
getline(cin, s);
cin >> x;
cin >> y;
cin >> z;
cin.ignore();
cin.clear();
getline(cin, p);
cin >> x1;
cin >> y1;
cin >> z1;
printf("%s to %s: %.2f\n", s.c_str(), p.c_str(), sqrt(pow(x - x1, 2) + pow(y - y1, 2) + pow(z - z1, 2)));
}
}
you have twice in the first time you enter the string.
第一次输入字符串时有两次。