【问题标题】:What are the rules of the std::cin object in C++?C++中std::cin对象的规则是什么?
【发布时间】:2010-10-22 18:26:03
【问题描述】:

我正在编写一个小程序供我个人使用来练习学习 C++ 及其功能,它是一个 MLA 引文生成器(我正在写一篇有数十次引文的大型论文)。

由于缺乏更好的方法(我不了解类或在您的 main 中使用其他 .cpp 文件,所以不要费心告诉我,我有更多时间时会处理),我正在为每种类型的引用编写一个函数。如果我有更多时间,我可能会将其分解为每个重用代码的函数。

我的问题是:std::cin 对象是如何工作的?我目前正在使用 std::cin >> 读取我希望是单个单词的字符串,并使用 getline(std::cin, string) 读取带有空格的字符串。不过,我没有得到正确的输出。我只想知道 std::cin 是如何工作的,以及为什么我总是意外地跳过一些输入(例如,它跳过了 webPage 而不是给我输入的机会)。

void webCit() {
    std::cout << "Leave any unknowns blank.\n";

    std::cout << "Author last name: ";
    std::string lastName;
    std::cin >> lastName;

    if (lastName.size() != 0) {
        lastName = lastName + ", ";
    }


    std::cout << "Author first name: ";
    std::string firstName;
    std::cin >> firstName;

    if (firstName.size() != 0) {
        firstName = firstName + ". ";
    }


    std::cout << "Article title: ";
    std::string articleTitle;
    getline(std::cin, articleTitle);

    if (articleTitle.size() != 0) {
        articleTitle = "\"" + articleTitle + ".\" ";
    }

    std::cout << "Title of web page: ";
    std::string pageTitle;
    std::cin >> pageTitle;

    if (pageTitle.size() != 0) {
        pageTitle = pageTitle + ". ";
    }

    std::cout << "Publication date: ";
    std::string publicationDate;
    getline(std::cin, publicationDate);

    if (publicationDate.size() != 0) {
        publicationDate = publicationDate + ". ";

    }

    std::cout << "Web address: ";
    std::string webAddress;
    getline(std::cin, webAddress);

    webAddress = "<" + webAddress + ">. ";

    std::cout << "Date accessed: ";
    std::string dateAccessed;
    getline(std::cin, dateAccessed);

    if (dateAccessed.size() != 0) {
        dateAccessed = dateAccessed + ". ";
    }

    std::string citation =
        lastName + firstName + articleTitle + pageTitle + publicationDate + webAddress + dateAccessed;

    std::cout << citation; //TEST; remove after
}

编辑:I/O

Leave any unknowns blank.
Author last name: Hooked
Author first name: Jerbear
Article title: Title of web page: title
Publication date: Web address: www.win.com
Date accessed: 4/29/09
Hooked, Jerbear. Title. <www.win.com>. 4/29/09. 

如您所见,出了点问题,因为我的输入被跳过了。

【问题讨论】:

  • 我没有看到你这样做的方式有任何明显的问题...你能复制和粘贴你与这个程序的交互,你有确切的输入和输出吗?另外,我建议将“使用命名空间标准;”在顶部(通常在所有#include 之后),这样你就可以只说“cin”和“cout”而不必一遍又一遍地写 std::。但你当然不必……不管怎样。
  • @MatrixFrog:我更喜欢using std::cin; using std::cout; ...,或者将using namespace std;放在使用它的函数中,而不是在全局级别。

标签: c++ iostream cin getline


【解决方案1】:

这里发生的情况是std::cin &gt;&gt; firstName; 最多只能读取 但不包括第一个空格字符,当您按 Enter 时,它包括换行符(或 '\n'),所以当它得到到getline(std::cin, articleTitle);'\n' 仍然是std::cin 中的下一个字符,getline() 立即返回。

// cin = "Bloggs\nJoe\nMan of Steel, Woman of Kleenex\n"
std::cin >> lastName;
std::cin >> firstName;
// firstName = "Joe", lastName = "Bloggs", cin = "\nMan of Steel, Woman of Kleenex\n"
getline(std::cin, articleTitle);
// articleTitle = "", cin = "Man of Steel, Woman of Kleenex\n"

在调用 getline() 之前添加“std::cin &gt;&gt; std::ws”(ws 意思是 whitespace)可以解决问题:

std::cin >> firstName >> std::ws;
getline(std::cin, articleTitle);

但如果你在论证中这样做,更容易看出你错过了什么:

std::cin >> firstName;
getline(std::cin >> std::ws, articleTitle);

【讨论】:

  • 我也正要加 ws :P
  • 不是多个cin >>s会发生什么!
  • @Jesse:哦,我明白你所说的“多个 cin >>s”是什么意思了。我猜它的行为是一样的。
【解决方案2】:

当您使用&gt;&gt; 运算符时,cin 会向上读取直到下一个空格字符,但它不会处理空格。所以当你有

std::cin >> str1;
std::getline(std::cin, str2);

第二次调用将只处理换行符,您将没有机会输入任何输入。

相反,如果您打算在operator &gt;&gt; 之后使用getline,则可以在调用getline 之前调用std::cin.ignore() 吃掉换行符。

编辑:当你这样做时,它会像你预期的那样工作

std::cin >> str1;
std::cin >> str2;

因为第二次调用将忽略所有前导空格。

【讨论】:

  • 另外,请注意 operator>> 和 getline 都返回一个布尔兼容值,当它成功读取输入值时为 true,如果有错误、文件结尾或格式化失败。
  • @Aaron:准确地说,它们返回 istream,它可转换为 void*,而 void* 可转换为 bool(哇!),即 !is.fail() 的值。这就是std::cin &gt;&gt; lastName &gt;&gt; firstName; 起作用的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-13
  • 2018-03-11
  • 2013-07-01
  • 2017-01-05
  • 2018-01-26
  • 2018-07-18
相关资源
最近更新 更多