Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 20, средняя оценка - 4.80
moskitos80
61 / 61 / 10
Регистрация: 04.10.2011
Сообщений: 217
Завершенные тесты: 1
#1

basic_istream::getline - C++

23.07.2012, 01:36. Просмотров 2546. Ответов 14
Метки нет (Все метки)

Всем здравствуйте. Изучаю С++ по книге Р. Лафоре в главе 7 массивы и строки есть задание которое предполагает получение строки, содержащей пробелы в переменную типа string и тут при выполнении задания я столкнулся с непонятным поведением функции basic_istream::getline вот пример кода который показывает проблему:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>
 
using namespace std;
 
const int SIZE = 100;
 
int main() {
    
    char ans;
    int numbers[SIZE];
    string empl[SIZE];
    
    for (int i = 0; i < SIZE; i++) {
        cout << "\nEnter number";
        cin >> empl[i];
        
        cout << "\nEnter name";
        getline(cin, empl[i]); // Вот этот момент программа как будто пропускает...
        
        cout << "\nEnter more data? y/n ";
        cin >> ans;
        
        if (ans == 'n') {
              break;
        }
    }
    
    cout << endl;      
    system("PAUSE");    
    
    return EXIT_SUCCESS;    
}
При выполнении программы происходит следующее:
прога пишет

Enter number - ввожу номер нажимаю enter

Далее прога выдает:

Enter name
Enter more data? y/n

Т.е. она не ждёт ввода после Enter name! Получается что getline(cin, empl[i]); как-то пропускается
Объясните пожалуйста чайнику с чем связано такое поведение? Использую Dev C++ 4.9.9.2
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.07.2012, 01:36     basic_istream::getline
Посмотрите здесь:

std::basic_istream<_CharT, _Traits>::basic_istream() [with _CharT = char; _Traits = std::char_traits<char>]» is protected - C++
Есть класс: class Expression { public: Expression(string expr, ErrorCallback errcb=0); Expression(const Expression&amp; orig); ...

getline - C++
Я считываю число из входного потока, но дальше из входного потока уже не могу считать строку. Его надо очищать что ли? #include...

не работает getline - C++
Есть код (писал не я), но не могу понять, почему getline() игнорируется в строке 72. Сначала не работало в функции класса, потом решил...

Помогите с getline - C++
Добрый день! Помогите, пожалуйста, разобраться с механизмом работы функции getline класса ifstream. Есть кусок кода: int buffLen =...

getline() в рекурсивной ф-и - C++
почему в рекурсивной ф-и гетлайн учитывается только однажды? к примеру: int get_answer() { string str; string question; ...

Проскакивает getline - C++
Программа игнорирует первый ввод. Client obj; cout &lt;&lt; &quot;Name: &quot;; getline(cin, obj.Name); cout &lt;&lt; '\n'; cout &lt;&lt; &quot;Last...

Замена getline() - C++
Подскажите замену getline() #include &lt;string&gt; #include &lt;iostream&gt; #include &lt;fstream&gt; #include &lt;conio.h&gt; using namespace std; ...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
23.07.2012, 02:46     basic_istream::getline #2
Сообщение было отмечено автором темы, экспертом или модератором как ответ
После cin >> empl[i]; поставьте cin.get().

Добавлено через 8 минут
cin >> оставляет во входном потоке символ новой строки '\n'. Он становится первым считываемым символом для getline(). Для неё это пустая строка. Обрабатывает она её так: если пустая строка, то чтение останавливается, символ '\n' извлекается из очереди, но не сохраняется, в строку ввода помещается '\0'. Если после cin >> поставить cin.get(),то символ '\n' будет извлечён этим методом из потока, и дальше всё будет нормально.

Добавлено через 36 минут
И ещё, в 17 строке, наверное нужно cin >> numbers[i];?
xADMIRALx
67 / 61 / 1
Регистрация: 09.06.2012
Сообщений: 291
23.07.2012, 06:16     basic_istream::getline #3
по мне так луче gets();
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,398
Записей в блоге: 17
23.07.2012, 09:26     basic_istream::getline #4
C++
1
2
3
4
5
6
cout << "\nEnter name";
 
cin.sinc();   // !!!
getline(cin, empl[i]);     
 
cout << "\nEnter more data? y/n ";
http://www.cplusplus.com/reference/i.../istream/sync/
http://www.cplusplus.com/reference/i...stream/ignore/
moskitos80
61 / 61 / 10
Регистрация: 04.10.2011
Сообщений: 217
Завершенные тесты: 1
23.07.2012, 10:18  [ТС]     basic_istream::getline #5
alsav22 - благодарю за подробное пояснение.. По поводу 17 строки вы конечно правы, правда, в данном случае это не существенно, но всё же спасибо и за внимательность.
Avazart - спасибо за ссылки, я даже не знал про такой ресурс - очень пригодится!
xADMIRALx - учту на будущее
Jupiter
23.07.2012, 10:32
  #6

Не по теме:

Цитата Сообщение от xADMIRALx Посмотреть сообщение
по мне так луче gets();
вы документацию к этой функции читали? видимо нет
и вообще каким боком Си-шная функция в С++!?

alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
23.07.2012, 21:19     basic_istream::getline #7
Цитата Сообщение от Avazart Посмотреть сообщение
C++
1
2
3
4
5
6
cout << "\nEnter name";
 
cin.sinc();   // !!!
getline(cin, empl[i]);     
 
cout << "\nEnter more data? y/n ";
http://www.cplusplus.com/reference/i.../istream/sync/
http://www.cplusplus.com/reference/i...stream/ignore/
Несколько раз мне попадались рекомендации не использовать sinc(). Кажется, из-за непереносимости. Не знаю, насколько это обоснованно. Советуют ignore(). Вот ссылка, как это правильно делать: http://cppstudy.wordpress.com/2009/0...in-get-and-co/
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,398
Записей в блоге: 17
23.07.2012, 21:28     basic_istream::getline #8
Ну я не знаю как стандартная ф-ция может быть не переносимой, а на ignore() я ссылку тоже кинул.
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
24.07.2012, 05:17     basic_istream::getline #9
Цитата Сообщение от Avazart Посмотреть сообщение
Ну я не знаю как стандартная ф-ция может быть не переносимой, а на ignore() я ссылку тоже кинул.
Вот ссылка на ту же тему, третий пост: Интересное поведение cin.getline(); Пишут, что
sync() можно, но это не сработает в linux
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,398
Записей в блоге: 17
24.07.2012, 09:45     basic_istream::getline #10
Да проврерил (в Ubuntu,g++) действительно не работает sinc(), а ignore() работает что странно по тому как назначение ф-ций, как я понимаю, тоже.
moskitos80
61 / 61 / 10
Регистрация: 04.10.2011
Сообщений: 217
Завершенные тесты: 1
24.07.2012, 10:59  [ТС]     basic_istream::getline #11
Цитата Сообщение от Avazart Посмотреть сообщение
Да проврерил (в Ubuntu,g++) действительно не работает sinc(), а ignore() работает что странно по тому как назначение ф-ций, как я понимаю, тоже.
- Полезная инфа - спасибо.

alsav22 а этому товарищу: cppstudy.wordpress.com вообще зачёт!

Итог: принял для себя такое решение для подобных случаев - после чтения из буфера будем подчищать его таким макаром:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
 
using namespace std;
 
int main() {
    
    string name;
    int age;
    
    cout << "Enter age "; cin >> age;
 
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
        
    cout << "\nEnter name "; getline(cin, name);
    
    cout << "\nWas entered age " << age 
         << " name " << name << endl;
       
    system("PAUSE");    
    return EXIT_SUCCESS;    
}
Потому как такой способ (Dev 4.9.9.2 на Win 7x32) у меня не заработал:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
 
using namespace std;
 
int main() {
    
    string name;
    int age;
    
    cout << "Enter age "; cin >> age;
    
    cin.ignore(cin.rdbuf()->in_avail(), '\n');
        
    cout << "\nEnter name "; getline(cin, name);
    
    cout << "\nWas entered age " << age 
         << " name " << name << endl;
       
    system("PAUSE");    
    return EXIT_SUCCESS;    
}
Единственное, для меня пока загадка - смысл этой строки (наверно здесь мы получаем какое то верхнее пороговое значение размера буфера, но вот способ получения... ) :

C++
1
numeric_limits<streamsize>::max()
Но это лишь потому, что до этого я пока ещё наверно не дочитал. А так спасибо ребята за разъяснения. Правда у меня ещё куча вопросов, но это уже другие темы
kravam
быдлокодер
1693 / 880 / 44
Регистрация: 04.06.2008
Сообщений: 5,438
24.07.2012, 11:26     basic_istream::getline #12
Итог: принял для себя такое решение для подобных случаев - после чтения из буфера будем подчищать его таким макаром:
...
C++
1
cin.ignore(numeric_limits<streamsize>::max(), '\n');


++++++++++++++++++++++++++++++++++++++++++++=

Определили для себя, что в буфере остался один символ (в нашем случае '\n'):
C++
1
2
3
        cout << "\nEnter name";
        getchar ();
        getline(cin, empl[i]);

Если необходимо очистить буфер консоли полностью и наверное, то так:
C++
1
2
3
        cout << "\nEnter name";
        fflush (stdin);
        getline(cin, empl[i]);
Всё!

++++++++++++++++++++++++++++++++++++++++++++=

Это Сишные функции, но кто нам запрещает использовать их в С++, имея ввиду, что С это подмножество C++?
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
24.07.2012, 11:45     basic_istream::getline #13
kravam, по поводу fflush(stdin)
If it was open for reading and the last operation was an input operation, the behavior depends on the specific library implementation. In some implementations this causes the input buffer to be cleared, but this is not standard behavior.
ожидаемый эффект есть только под виндой в VS, про mingw не знаю
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
24.07.2012, 20:46     basic_istream::getline #14
Цитата Сообщение от moskitos80 Посмотреть сообщение
Единственное, для меня пока загадка - смысл этой строки
Цитата Сообщение от moskitos80 Посмотреть сообщение
numeric_limits<streamsize>::max()
Шаблонный класс numeric_limits. В данном случае, статический метод max(), выдаёт предельный размер для встроенного типа streamsize (размер потока), для данной платформы. Можно здесь почитать подробнее: http://www.cplusplus.com/reference/s...umeric_limits/ В каких-то компиляторах, требуется: #include <limits>.

Добавлено через 9 минут
Цитата Сообщение от Jupiter Посмотреть сообщение
про mingw не знаю
Работает.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.07.2012, 23:31     basic_istream::getline
Еще ссылки по теме:

Пропускает getline - C++
Доброго времени суток. Проблема с getline в строке 33 - компилятор его просто не видит. Думал, что в потоке оставался \n, но ни cin.get(),...

Работа с getline - C++
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;string&gt; using namespace std; int main() { string str, name, breed,...

Getline, getchar - C++
Подскажите пожалуйста, как я поняла getline это шаблон функции, который построчно извлекает строки из выходного потока, но что делается...

не работает getline - C++
Подскажите, пожалуйста, почему не работает getline? Нужно ввести порядковый номер служащего и его имя с фамилией, но getline пропускает...

Не работает getline - C++
Есть прога, которая считает предложения и выводит самое длинное.Есть главный кейс с меню. В первом пункте кейса есть гетлайн, но при выборе...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
moskitos80
61 / 61 / 10
Регистрация: 04.10.2011
Сообщений: 217
Завершенные тесты: 1
24.07.2012, 23:31  [ТС]     basic_istream::getline #15
Цитата Сообщение от alsav22 Посмотреть сообщение
Шаблонный класс numeric_limits. В данном случае, статический метод max(), выдаёт предельный размер для встроенного типа streamsize (размер потока), для данной платформы. Можно здесь почитать подробнее: http://www.cplusplus.com/reference/s...umeric_limits/ В каких-то компиляторах, требуется: #include <limits>.
- Уф... до этого я ещё не дошёл, я дошёл пока только до перегрузки операторов и приведения пользовательских типов Тяжело конечно с PHP да Javascript переходить на языки с контролем типов да и вообще по сравнению с С++ они кажутся какими то игрушечными.
Yandex
Объявления
24.07.2012, 23:31     basic_istream::getline
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru