如何正确使用getline

时间:2014-02-01 16:02:30

标签: c++ getline

我编写了一个使用getline()函数的程序,但我不知道如何以正确的方式使用getline()。我在互联网上搜索了它,但我发现了一些关于将getchar()getline()cin.ignore()一起使用的问题。我尝试过,但没有一个工作,我不知道问题是什么,为什么getline()函数需要getchar()cin.ignore()才能正常工作?

我的输入

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    

这是我的代码:

#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)));
    }
}

4 个答案:

答案 0 :(得分:5)

代码将格式化输入(即使用>>运算符输入)与未格式化输入(在本例中使用std::getline())混合。无格式输入跳过前导空格,而格式化输入确实跳过前导空格。在这两种情况下,只要输入是下一个字符,读取就会停止。

例如,在阅读上一个double后,当输入为3000.00\n...时停止阅读0,因为“\n不适合double格式。因此,流中的下一个字符是\n。函数std::getline()读取,直到找到第一个\n为止:它提取一个字符并[成功]产生一个空行。根据您的输入,序列Dantooine是下一个但不符合double的格式,并且流将进入失败状态。

简单的解决方法是在从格式化输入切换到无格式输入时始终跳过前导空格,例如,使用std::ws操纵器:

std::getline(std::cin >> std::ws, s);

这是否合适取决于你想要阅读的内容。如果您想要读取的字符串可以以空格开头,则需要更加小心,例如,只提取空格直到下一个换行符:

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

(只是忽略一个字符可能不起作用,例如,如果该行的输入以3000.00 \n结尾)。

3000.00视为long实际上停在.,即对您的计划的第一次更改是更正读取的值的类型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
}

答案 1 :(得分:2)

cin >> z不会消耗\n个字符。因此,您需要cin.ignore()来使用换行符,并使下一个getline()读取您想要的行。同样的问题也发生在cin >> z1

答案 2 :(得分:0)

最好不要混合令牌和线条提取。如果要对行进行标记,只需使用字符串流。我试试这个:

#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
}

答案 3 :(得分:0)

试试吧

#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)));
    }
}

你第一次输入字符串时有两次。