C++ --- getline 和 cin ignore () . 删除输出字符串中的第一个字符

Posted

技术标签:

【中文标题】C++ --- getline 和 cin ignore () . 删除输出字符串中的第一个字符【英文标题】:C++ --- getline, and cin ignore () .deleting first characters in strings on output 【发布时间】:2019-03-20 21:20:41 【问题描述】:
#include <iostream>
#include <string>
using namespace std;


struct UserInfo

    string userPhoneNumber;
    string userName ;
    string userAddress ;

;


int main ()

    cout << "How many Entries do you want to enter?";
    int userAmountSelection;
    cin >> userAmountSelection;

    UserInfo userOne [userAmountSelection];

    for (int i = 0; i < userAmountSelection; i++)
        cout << "Please enter your first and last name: ";
        cin.ignore(); // possible problem in code 
        getline (cin, userOne[i].userName, '\n');
        cout << "Please Enter your address, " << userOne[i].userName << ":";
        cin.ignore(); // possible problem in code 
        getline (cin, userOne[i].userAddress, '\n');
        cout << "Please enter your phone#: ";
        cin.ignore (); // possible problem in code 
        getline (cin, userOne[i].userPhoneNumber);
    
    for (int i = 0; i < userAmountSelection; i++)
        cout << userOne[i].userName << "        " << 
                userOne[i].userAddress << "         " << 
                userOne[i].userPhoneNumber << endl;
    

    return 0;

正如您所见,它是用于学习结构和实验的简单代码。我遇到的问题似乎来自 cin.ignore () 代码。它在输出时忽略输入字符串的第一个字符。代码确实可以编译,但是输入和输出有偏差。

比如我输入一个Terry的名字,就会输出erry。

我尝试删除cin.ignore (),但是当我这样做时,输出会跳过用户需要输入数据的部分并将区域留空。 我搜索了论坛并找到了一些建议,例如向cin.ignore(std::numeric_limits&lt;std::streamsize&gt;::max(), '\n'); 添加参数。例如,但这并不能解决问题,只会添加到我遇到的错误列表中。

【问题讨论】:

ignores 放置在将不需要的内容留在流中的操作之后。如果您在操作之前ignore,您经常会发现自己丢失了您想要的数据,因为ignore 没有任何数据。 不要将提取器与getline 混合使用。他们打架。而不是cin &gt;&gt; userAmountSelection; 将输入读入带有getline 的字符串,并将字符串中的文本转换为int @pete becker --- 我明白你在说什么,我只是尝试实现它,如果我做得正确,它会给我使用 userAmountSelection 变量的错误。我不再能够在 UserInfo userOne [userAmountSelection] 中使用它;声明。 使用userAmountSelection 表示数组的大小是不合法的。一些编译器将其作为扩展提供。 【参考方案1】:

问题

问题在于ignores 的位置,以防止Why does std::getline() skip input after a formatted extraction? 中概述的错误ignores 已放置在getlines 之前,虽然这解决了getline 跳过问题,但它导致提问者遇到的问题。并不总是需要忽略某些东西。

例如

cin >> userAmountSelection;

如果用户输入金额然后按回车键,则会在流中留下一行结尾。

cout << "Please enter your first and last name: ";
cin.ignore(); // possible problem in code 
getline (cin, userOne[i].userName, '\n');

for 循环内如果不是ignore,将跳过此行结束。但是getline 不会在流中留下换行符,因此循环的第二次和后续迭代没有换行符可以忽略。部分所需数据改为ignored

之后

cin >> userAmountSelection;

而不是以前

getline (cin, userOne[i].userName, '\n');

将是放置ignore 的好地方,因此只有在将换行符留在流中后才会从流中删除它,但是...

解决方案

处理此问题的最佳方法是始终使用 getline 读取整行,然后将这些行 (see option 2 of this answer) 解析为您想要的部分。

std::string line;
std::getline(std::cin, line);
std::istringstream(line) >> userAmountSelection;

这总是有效的(注意:需要#include &lt;sstream&gt;),现在您只有一种阅读方式,而不是混搭游戏,您可能会忘记需要ignore

请立即停止阅读。

ignore 方法需要一些额外的聪明才智。除了人类记忆的易错性之外,它并不像看起来那么简单。您应该将ignores 放置在将不需要的内容留在流中的操作之后。如果您在操作之前ignore,您经常会发现自己丢失了您想要的数据,因为ignore 没有任何数据。

std::cin >> userAmountSelection; // read a number
std::cin.ignore(); // discard the next character

很多时候都有效,但是如果用户输入数量,然后输入一个空格,然后按回车键或输入他们需要输入的所有输入,因为他们很新,下一个提示是什么?你得有点狡猾。

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

这个ignore 会消灭所有东西,直到它到达行尾或流中的空间用完。 (注:需要#include &lt;limits&gt;

【讨论】:

#include 和 #include 对我来说非常新,今晚我将开始学习这些内容。非常感谢您深入研究,不仅回答了这个问题,而且很好地解释了它。你的时间对我来说很重要。 @Caedus sstream 是stringstream 的标头,基本上是cincout 读取或写入string 而不是控制台。 好点。我从用户的代码开始,将其排除在外。为了完整起见,不妨将其重新添加。【参考方案2】:

我遇到的问题似乎来自 cin.ignore () 代码。它在输出时忽略输入字符串的第一个字符。

看着istream::ignoredeclaration

istream& ignore (streamsize n = 1, int delim = EOF);

默认会丢弃第一个字符。


我已经尝试删除 cin.ignore(),但是当我这样做时, 输出跳过用户需要输入数据的部分和 将区域留空。

这是因为std::cin 的执行留下了剩余的换行符,然后被getline 消耗。您只需要在std::cingetline 调用之间使用ignore

std::cin >> userAmountSelection;
std::cin.ignore(); //---
...
for (int i = 0; i < userAmountSelection; i++) 
    ...
    getline (...);
    ...
    getline (...)


此外,在某些情况下,您可能不知道std::cin 是否会在getline 之前。在这种情况下,您可以在执行ignore 之前检查输入流是否包含新行:

    ...

    // some I/O operations happening here

    ...

    // ignore if there's white space
    if (std::iswspace(std::cin.peek())) std::cin.ignore();

    std::getline(std::cin, somestring);

【讨论】:

以上是关于C++ --- getline 和 cin ignore () . 删除输出字符串中的第一个字符的主要内容,如果未能解决你的问题,请参考以下文章

C++ --- getline 和 cin ignore () . 删除输出字符串中的第一个字符

C++ 中 cin.getline() 的意外返回

c++中 cincin.get()cin.getline()cin.getchar()的区别

c++ getline cin 问题

关于 getline(cin, string) 的 C++ 快速问题

cin.get() 和 cin.getline() 之间的区别