Каковы правила объекта std :: cin в C ++? - PullRequest
0 голосов
/ 30 апреля 2009

Я пишу небольшую программу для личного использования для практики изучения C ++ и ее функциональности, генератор ссылок MLA (я пишу большую статью с десятками цитат).

Из-за отсутствия лучшего способа сделать это (я не понимаю классы или не использую другие файлы .cpp внутри вашей основной сети, поэтому не стесняйтесь говорить мне, я буду работать над этим, когда у меня будет больше времени) Я пишу функцию для каждого типа цитирования. Я мог бы разбить это на функцию для каждого повторно используемого кода, если у меня будет больше времени.

Мой вопрос: как работает объект std :: cin? В настоящее время я читаю с std :: cin >> для строк, которые я ожидаю, чтобы быть отдельными словами, и getline (std :: cin, string) для строк с пробелами. Я не получаю правильный вывод, хотя. Я просто хочу знать, как работает std :: cin и почему я неожиданно пропускаю некоторые входные данные (например, он пропускает веб-страницу вместо того, чтобы дать мне шанс войти в нее).

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. 

Как видите, что-то идет не так, потому что мой ввод пропускается.

Ответы [ 2 ]

7 голосов
/ 30 апреля 2009

То, что здесь происходит, это то, что std::cin >> firstName; читает только до , но не включает первый символ пробела, который включает символ новой строки (или '\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"

Добавление 'std::cin >> std::ws' (ws означает w hite s pace) до того, как ваши вызовы getline () решат проблему:

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

Но легче увидеть, где вы пропустили это, если вы сделаете это в аргументе:

std::cin >> firstName;
getline(std::cin >> std::ws, articleTitle);
3 голосов
/ 30 апреля 2009

Когда вы используете оператор >>, cin читает до следующего символа пробела, но не обрабатывает пробел. Итак, когда у вас есть

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

второй вызов просто обработает символ новой строки, и у вас не будет возможности набрать какой-либо ввод.

Вместо этого, если вы планируете использовать getline после operator >>, вы можете позвонить std::cin.ignore(), чтобы съесть новую строку, прежде чем позвонить getline.

Редактировать: работает, как вы ожидаете, когда вы делаете

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

, так как второй вызов будет игнорировать все начальные пробелы.

...