Почему getline не работает после cin c
Перейти к содержимому

Почему getline не работает после cin c

  • автор:

Ввод в языке C++ через cin

Для считывания данных со стандартного ввода используется объект cin , также определенных в заголовочном файле iostream . Его использование похоже на использование объекта cout для вывода. Например, для считывания двух переменных a и b нужно дать команду:

Также как и в случае с cout , нет нужды беспокоиться о типах данных — можно считывать целые и действительные числа, символы и строки.

Особенности считывания символов

Пусть дано время в формате HH:MM. Считать его можно следующим образом:

int h, m;
char c;
cin >> h >> c >> m;

То есть сначала считывается число, затем — символ, затем — число.

При этом при считывании символа пропускаются пробельные символы (пробелы и концы строк) и считывается следующий непробельный символ. Например, если при запуске приведенного выше кода ввести «12 34», то переменная h станет равна 12, переменная с — ‘3’, а переменная m — 4.

Если установить манипулятор noskipws :

то при считывании символов пробельные символы не будут пропускаться. Для восстановления режима пропуска пробельных символов используется манипулятор skipws :

Особенности считывания строк

Считывание строк при помощи cin >> s , где s — объект класса string или C-строка приведет к считыванию строки из непробельных символов, при этом пробельные символы пропускаются.Использовать манипулятор noskipws при чтении строк не следует.

Строку целиком до конца строки, вместе с пробельными символами можно считать следующим образом:

Отметим следующую особенность такого считывания. Пусть входные данные заданы так — сначала число строк n, затем — n строк, возможно, содержащие пробелы. Требуется считать данные строки и сохранить их в массиве строк.

Правильное решение будет таким:

int n;
string s, A[100];
cin >> n;
getline(cin, s);
for (int i = 0; i < n; ++i)
getline(cin, A[i]);

Здесь нужно обратить внимание на «лишний» вызов getline после считывания числа n. Дело в том, что cin >> n не считывает конец строки из потока, поэтому последующий вызов getline вернет пустую строку (но зато считает конец строки), поэтому нужно сделать один «холостой» вызов getline перед считыванием всех остальных строк.

Значение, возвращаемое при считывании

Для проверки успешности считывания можно преобразовать значение, возвращаемое операцией считывания к типу bool . Например, следующим образом:

bool is_correct;
int a;
is_correct = (cin >> a);

Если значение переменной is_correct будет true , то считывание было успешно, иначе — нет.

Вместо записи результата в логическую переменную, можно непосредственно использовать его, например, в условной инструкции. Вот так, например, можно проверять, что на вход программе подано два числа через двоеточие:

int h, m;
char c;
if (cin >> noskipws >> h >> c >> m)
if (c == ‘:’) .
>

Похожее использование — чтение текста «по словам», с обработкой каждого слова:

string word;
while (cin >> word)
// Обработать слово в переменной word
>

Или считывание текста по строкам:

string line;
while (getline(cin, s))
// Обработать строку в переменной line
>

Не работает cin.getline

Author24 — интернет-сервис помощи студентам

Не работает cin.getline(name2, 3). Компилятор его тупо пропускает.

Добавлено через 4 минуты
первый cin.getline(name,3); работает нормально

Лучшие ответы ( 3 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

cin.getline как работает?
Здравствуйте, в моей программе я столкнулся с некоторой проблемой. В переменную place я хочу.

Не работает cin.getline(buf, 20);
Товарищи подскажите почему не работает cin.getline(buf, 20);? Проблема в том что я хочу ограничить.

Не работает. cin.getline(string,200);
Я создаю проект. Все работает кроме одного cin.getline(string,200), почему? Когда запускаю этот.

167 / 107 / 22
Регистрация: 02.01.2012
Сообщений: 596

Лучший ответ

Сообщение было отмечено FGlomgold как решение

Решение

ЦитатаСообщение от FGlomgold Посмотреть сообщение

Компилятор его тупо пропускает.

Нет. Просто после первого getline в буфере ввода остаётся символ конца строки, поэтому второй сразу завершается.
Попробуйте, например, ввести сразу 6 символов — и Вы увидете, что оба оператора отработали.

Странно работает cin.get

Он почему-то не работает после того, как я делаю «cin >> чтототам», без этого все работает, а как только сделаю «cin >> чтототам», cin.get просто не работает 🙁 что делать ?

anonymous
05.05.01 12:46:38 MSD

а можно подробности узнать, как именно не работает? желательно куском кода 🙂

anonymous
( 06.05.01 04:31:58 MSD )

Куском кода давать проблематично т.к. я не умею делать переход на новую строку в этом форуме(пытался писать
— не получилось). Я пытаюсь делать примерно так : int age; char name[20]; Потом делаю cin >> age; Это работает и работает так как надо, а потом я делаю cin.get(name, 20); — вот это уже не работает, просто не делается приглашения ввести что-то. Похоже cin >> age; забирает все до пробела, а cin.get — подбирает все, что после него, а мне надо чтобы cin.get забирал свою, независимую от cin >> строку. Получилось сделать так, между cin >> и cin.get вставить char garbage; garbage = cin.get(); — так все нормально, но мне кажется как то неправильно это.

anonymous
( 06.05.01 17:24:21 MSD )

не понял как не работает. у меня все работает:

int main(void) <
int age;
char name[20];
string str;

или я не понял чего именно ты хочешь?
заглотить целую строчку? тогда пользуй
istream& istream::getline(char* ptr, int len, char delim = ‘\n’);
соответственно cin.getline(name,20);

в общем пиши, разберемся 🙂

PS. а по поводу переносов, есть такой listbox под окошком,
ставишь там User line breaks 🙂

anonymous
( 07.05.01 00:42:53 MSD )

Проверка
переноса
проверка

anonymous
( 07.05.01 00:54:54 MSD )

Перенос работает — большое спасибо. Код не работает вот так:
#include
#include

age — он забирает, а вот fio — нет 🙁

anonymous
( 07.05.01 01:01:19 MSD )

в общем мораль простая, cin >> age оставляет конец строки
в потоке, в результате по getline тебе прилетает пустая строчка
пока чтоб работало можешь сделать что-нить вроде:
#include
#include

void main(void) <
int age;
char fio[20],tmp;
cin >> age;
cin >> tmp;
cin.putback(tmp);
cin.getline(fio,20);
cout >

это работает, потому как все пробельные символы пропускаются пока
не найдется не-пробел, он кладется в tmp и потом запихивается
обратно в поток.
ну или если пустая строчка то перечитывай пока непустая не придет 🙂

хотя по-моему был какой-то прямой способ сказать
istream чтоб пропустил пробелы перед началом считывания.

утро вечера мудренее, завтра поковыряюсь — напишу

PS. подумай про случай, когда тебе введут `21 Joe Farmer’ 🙂
PPS. почему предпочитаешь char* использовать, когда есть string ?

anonymous
( 07.05.01 03:41:58 MSD )

Спасибо, я в общем то так и делал, только чуть-чуть по другому:
char garbage;
garbage = cin.get();

cin.get без параметров возвращает единичный символ, похоже то что мне надо, тот самый разделитель, я потому и написал, что думал про другой способ, более правильный. Про тот случай когда вводятся данные целиком подумал, спасибо. String не использую потому, что сейчас пытаюсь разобраться с поизвольным доступом к файлу, записываю туда структуру целиком, и мне нужно чтобы были четкие размеры, а string я не вообще не особо понимаю — какие у него размеры 🙂 В общем большое спасибо, если найдешь другой способ — напиши пожалуйста.

anonymous
( 07.05.01 19:23:14 MSD )

Структуру лучше записывать методом write, а считывать методом read. Пропускать пробелы — если я правильно помню — cin >> skipws.

justme ★
( 08.05.01 02:48:46 MSD )

про структуры и бинарные файлы согласен с justme

про skipws все почти так, skipws в установленном сстоянии
обеспечивает пропуск пробельных символов при вводе(сам он их не извлекает)
перед данными при операциях вроде
cin >> age;
getline, get не пропускает пробелы перед вводом данных. отличаются
они тем, что getline забирает конец строчки из потока, а get — нет.

char garbage=cin.get();
работает только если после age не осталось пробелов до конца строки.
я-бы не стал на это надеяться, особенно если учесть возможность
перенаправления ввода из файла.

char tmp;
cin >> tmp;
cin.putback(tmp);
работает потому, что по-умолчанию в потоке стоит флажок skipws и все
пробелы пробелы пропускаются, в tmp кладется первый не пробел из следующей
строчки(fio), он запихивается обратно в поток и первый символ — начало
строчки. все работает, если устраивает игнорирование пробелов вначале fio.

и использовать примерно так:
char fio[20];
int age;
cin >> age;
skipwhite(cin);
cin.readline(fio,20);

или при большом желании можно сделать из нее манипулятор,
как писать пока не буду, надо будет — напишу 🙂
char fio[20];
int age;
cin >> age >> skipwhite;
cin.readline(fio,20);

надеюсь на этот раз ровно то, что хотелось 🙂
ds.

PS. DOS’овские CR/LF это, как обычно, дополнительные грабли, но имхо
лучше с ними не связаваться, а конвертить предварительно файлы.

PPS. все равно не пойму, чем тебе больше нравится
char fio[20];
cin.getline(fio,20);
чем
string fio;
cin.getline(fio);
по-моему ничем не хуже 🙂 а лучше,
а если структуры/бинарные данные вводить, то правильней использовать
read и write, они хоть char(0) в конец не добавляют, и читают
указанные 20 символов, а не 19, как get и getline 🙂

getline() не работает, если используется после некоторых входов

getline() не работает, если я использую его после некоторых входов, т.е.

#include using namespace std; main() < string date,time; char journal[23]; cout>date; cout>time; cout

где, как если бы я использовал getline() поверх входов, он работает, т.е.

cout>date; cout>time; 

В чем может быть причина?

Поделиться Источник 02 октября 2012 в 13:33

3 ответа

Символы извлекаются до тех пор, пока не будут извлечены либо (n — 1) символы, либо не будет найден разделительный символ (что является разделителем, если указан этот параметр, либо ‘\n’ в противном случае). Извлечение также прекращается, если конец файла достигнут в последовательности ввода или если возникает ошибка во время операции ввода.

Когда cin.getline() читается из ввода, в потоке ввода остается символ новой строки, поэтому он не читает вашу строку c. Используйте cin.ignore() перед вызовом getline() .

cout 

Поделиться 02 октября 2012 в 13:44

Добавляя к тому, что сказал @DavidHammen:

Операции извлечения оставляют последующий символ '\n' в потоке. С другой стороны, istream::getline() отбрасывает его. Поэтому, когда вы вызываете getline после оператора извлечения, '\n' является первым символом, который встречается, и он перестает читать прямо там.

Поместите это после вызова getline извлечения:

Более надежный способ получения ввода будет выглядеть так:

while (true) < cout>time) < cin.ignore(); // discard the trailing '\n' break; >else < // ignore everything or to the first '\n', whichever comes first cin.ignore(numeric_limits::max(), '\n'); cin.clear(); // clear the error flags cout > 

Поделиться 02 октября 2012 в 13:45

Вы не проверяете состояние потока. Оператор извлечения потока std::cin ( operator>> ) может завершиться сбоем. Когда он завершится, поток помечается как "плохой" ( failbit , badbit или eofbit установлены). После "плохого" завершения все последующие извлечения потока в этом потоке завершатся сбоем, если вы не очистите состояние.

Учитесь быть параноидальным программистом. Всегда проверяйте состояние этих отформатированных операций ввода. Вы можете, например, выбросить исключение или напечатать сообщение об ошибке и выйти. Единственное, что вам не следует делать, это просто предположить, что это сработало.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *