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

basic_istream::getline - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 20, средняя оценка - 4.80
moskitos80
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
23.07.2012, 01:36     basic_istream::getline #1
Всем здравствуйте. Изучаю С++ по книге Р. Лафоре в главе 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
Посмотрите здесь:

getline C++
getline C++
getline C++
Getline C++
std::basic_istream<_CharT, _Traits>::basic_istream() [with _CharT = char; _Traits = std::char_traits<char>]» is protected C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 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
 Аватар для xADMIRALx
66 / 60 / 1
Регистрация: 09.06.2012
Сообщений: 291
23.07.2012, 06:16     basic_istream::getline #3
по мне так луче gets();
Avazart
 Аватар для Avazart
6900 / 5140 / 252
Регистрация: 10.12.2010
Сообщений: 22,588
Записей в блоге: 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
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
23.07.2012, 10:18  [ТС]     basic_istream::getline #5
alsav22 - благодарю за подробное пояснение.. По поводу 17 строки вы конечно правы, правда, в данном случае это не существенно, но всё же спасибо и за внимательность.
Avazart - спасибо за ссылки, я даже не знал про такой ресурс - очень пригодится!
xADMIRALx - учту на будущее
Jupiter
23.07.2012, 10:32
  #6

Не по теме:

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

alsav22
5282 / 4801 / 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
 Аватар для Avazart
6900 / 5140 / 252
Регистрация: 10.12.2010
Сообщений: 22,588
Записей в блоге: 17
23.07.2012, 21:28     basic_istream::getline #8
Ну я не знаю как стандартная ф-ция может быть не переносимой, а на ignore() я ссылку тоже кинул.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
24.07.2012, 05:17     basic_istream::getline #9
Цитата Сообщение от Avazart Посмотреть сообщение
Ну я не знаю как стандартная ф-ция может быть не переносимой, а на ignore() я ссылку тоже кинул.
Вот ссылка на ту же тему, третий пост: Интересное поведение cin.getline(); Пишут, что
sync() можно, но это не сработает в linux
Avazart
 Аватар для Avazart
6900 / 5140 / 252
Регистрация: 10.12.2010
Сообщений: 22,588
Записей в блоге: 17
24.07.2012, 09:45     basic_istream::getline #10
Да проврерил (в Ubuntu,g++) действительно не работает sinc(), а ignore() работает что странно по тому как назначение ф-ций, как я понимаю, тоже.
moskitos80
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
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
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
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
Каратель
Эксперт C++
6542 / 3962 / 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
5282 / 4801 / 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++
error C2678: бинарный ">>": не найден оператор, принимающий левый операнд типа "std::basic_istream<_Elem,_Traits>" C++
Отличие getline() от cin.getline() C++

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

Или воспользуйтесь поиском по форуму:
moskitos80
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
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
Ответ Создать тему
Опции темы

Текущее время: 19:50. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru