C++ Getline 不断获得换行符。我怎样才能避免这种情况?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18725522/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:09:49  来源:igfitidea点击:

Getline keeps on getting newline character. How can I avoid this?

c++stringgetline

提问by rishiag

Basically I first takes an integer as input and then test case follows. My each test case is an string. I am suppose to print the string back if the starting patten of string matches "HI A" and it is case-insensitive. I wrote the code below to accomplish to this. My problem is that when I press enter after each input, getline takes newline character as new input. I have tried to tackle this by using extra getline after each input but the issue is still there. Program gets stuck in the loop even though I have put a break condition. What am I doing wrong?

基本上我首先将一个整数作为输入,然后是测试用例。我的每个测试用例都是一个字符串。如果字符串的起始模式与“HI A”匹配并且不区分大小写,我想将字符串打印回来。我写了下面的代码来完成这个。我的问题是,当我在每次输入后按 Enter 时,getline 将换行符作为新输入。我试图通过在每次输入后使用额外的 getline 来解决这个问题,但问题仍然存在。即使我设置了中断条件,程序也会卡在循环中。我究竟做错了什么?

#include <iostream>
#include <string>
using namespace std;
int main(){
    int N;
    cin >>N;
    string nl;
    getline(cin,nl);
    for (int i=0;i<N;i++){
        string s;
        getline(cin,s);
        //cout <<"string"<<s<<endl;
        int flag=0;
        if ((s.at(0)=='h'||s.at(0)=='H')&&(s.at(1)=='i'||s.at(1)=='I')&&(s.at(2)==' ')&&(s.at(3)=='a'||s.at(3)=='A')) flag=1;

        if (flag==1) cout << s;
        //cout << "not " <<s;
        string ne;
        cout << "i="<< i<<endl;
        if (i==N-1) {break;}
        getline(cin,ne);

    }
}

Here is sample input:

这是示例输入:

5
Hi Alex how are you doing
hI dave how are you doing
Good by Alex
hidden agenda
Alex greeted Martha by saying Hi Martha

Output should be:

输出应该是:

Hi Alex how are you doing

采纳答案by Mark Ransom

Your cin >>Nstops at the first non-numeric character, which is the newline. This you have a getlineto read past it, that's good.

cin >>N停在第一个非数字字符处,即换行符。这个你有一个getline阅读过去它,那很好。

Each additional getlineafter that reads the entire line, including the newline at the end. By putting in a second getlineyou're skipping half your input.

之后的每个额外内容getline都会读取整行,包括末尾的换行符。通过getline输入一秒钟,您将跳过一半的输入。

回答by Dignesh P R

ignore() function does the trick. By default, it discards all the input suquences till new line character.

ignore() 函数可以解决问题。默认情况下,它会丢弃所有输入序列直到换行符。

Other dilimiters and char limit can be specified as well.

也可以指定其他分隔符和字符限制。

http://www.cplusplus.com/reference/istream/istream/ignore/

http://www.cplusplus.com/reference/istream/istream/ignore/

In your case it goes like this.

在你的情况下,它是这样的。

    cin >> N;
    cin.ignore();

回答by Mats Petersson

So, your real problem isn't that getlineeats newlines, but that your second getline(cin, ne)is eating a line...

所以,你真正的问题不是getline吃换行符,而是你的第二个getline(cin, ne)是吃线......

And that is because you mistakenly think that you need two getlineoperations to read one line - or something like that. Mixing "linebased" and "itembased" input does have confusing ways to deal with newlines, so you do need something to "skip" the newline left behind frin cin >> N;, but once you have got rid of that, you only need ONE getlineto read up and including the newline at the end of a line.

那是因为你错误地认为你需要两个getline操作来读取一行——或者类似的东西。混合使用“linebased”和“itembased”输入确实会产生令人困惑的处理换行符的方法,所以你确实需要一些东西来“跳过”留下 frin 的换行符cin >> N;,但是一旦你摆脱了它,你只需要一个getline来阅读和包括行尾的换行符。

回答by macsyz

you just need to accept the fact that getline will give you '\n' at the end. One solution is remove '\n' after getting it. Another solution is do not write the additional 'endl'. for example, for your problem, you can use this code

你只需要接受 getline 最后会给你 '\n' 的事实。一种解决方案是在获取后删除 '\n'。另一个解决方案是不要写额外的“endl”。例如,对于您的问题,您可以使用此代码

int N;
cin >> N;
string line;
getline(cin, line); // skip the first new line after N.
for (int i = 0; i < N; i++) {
  string line;
  getline(cin, line);
  string first4 = line.substr(0, 4);
  // convert to upper case.
  std::transform(first4.begin(), first4.end(), first4.begin(), std::ptr_fun<int, int>(std::toupper)); // see http://en.cppreference.com/w/cpp/algorithm/transform
  if (first4 == "HI A") {
    cout << line;  // do not include "<< endl"
  }
}

回答by user3458845

cin.ignore()worked for me.

cin.ignore()为我工作。

void House::provideRoomName()
{
    int noOfRooms;

    cout<<"Enter the number of Rooms::";
    cin>>noOfRooms;
    cout<<endl;

    cout<<"Enter name of the Rooms::"<<endl;
    cin.ignore();
    for(int i=1; i<=noOfRooms; i++)
    {
        std::string l_roomName;
        cout<<"Room"<<"["<<i<<"] Name::";
        std::getline(std::cin, l_roomName);
    }
}

回答by FernandoZ

I am writing this answer with the hopes that it may help someone else out there that wants a very simple solution to this problem.

我写这个答案是希望它可以帮助其他想要一个非常简单的解决方案来解决这个问题的人。

In my case the problem was due to some files having different line endings such as '\r' vs. '\n'. Everything worked fine in windows but then it failed in Linux.

在我的情况下,问题是由于某些文件具有不同的行尾,例如“\r”与“\n”。在 Windows 中一切正常,但在 Linux 中却失败了。

The answer was actually simple. I created a function removeNewLineChar after each line was read in. That way the char was removed. The removeNewLineChar takes in the line that was read in and copies it over character by character into a new string but it avoids copying either of the newline characters.

答案其实很简单。在读入每一行后,我创建了一个函数 removeNewLineChar。这样就删除了字符。removeNewLineChar 接收读入的行并将其逐个字符复制到新字符串中,但它避免复制任何换行符。

Here is a full explanation of how that works.

这是有关其工作原理的完整说明。

C++ getline reads in the newline character and how to avoid it

C++ getline 读入换行符以及如何避免它