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

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

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

basic_istream::getline - C++

23.07.2012, 01:36. Просмотров 2586. Ответов 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
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.07.2012, 01:36
Здравствуйте! Я подобрал для вас темы с ответами на вопрос basic_istream::getline (C++):

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() от cin.getline() - C++
Чем отличается getline() от cin.getline() ?

Объясните разницу между "cin.getline" и "std::getline" - C++
string a; cin.getline(a); getline(cin, a);в чем разница между &quot;cin.getline(a);&quot; и &quot;getline(cin, a);&quot;

error C2678: бинарный ">>": не найден оператор, принимающий левый операнд типа "std::basic_istream<_Elem,_Traits>" - C++
Нужно из файла скачать информацию в объект. Почему у меня не получается? #include &lt;vector&gt; #include &lt;string&gt; #include &lt;iostream&gt; ...

Getline си++ - C++
Подскажите пожалуйста, в чем причина неправильной работы кода? while(file.getline(name_file, 4, '=')) { ...

Getline - C++
Проблема такая: getline не хочет работать так как надо, после строки &quot;Enter the manufacturer: &quot; программа не дает ввести имя и сразу...

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

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

Добавлено через 36 минут
И ещё, в 17 строке, наверное нужно cin >> numbers[i];?
5
xADMIRALx
67 / 61 / 1
Регистрация: 09.06.2012
Сообщений: 291
23.07.2012, 06:16 #3
по мне так луче gets();
0
Avazart
Эксперт С++
7213 / 5385 / 286
Регистрация: 10.12.2010
Сообщений: 23,792
Записей в блоге: 17
23.07.2012, 09:26 #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/
1
moskitos80
61 / 61 / 10
Регистрация: 04.10.2011
Сообщений: 217
Завершенные тесты: 1
23.07.2012, 10:18  [ТС] #5
alsav22 - благодарю за подробное пояснение.. По поводу 17 строки вы конечно правы, правда, в данном случае это не существенно, но всё же спасибо и за внимательность.
Avazart - спасибо за ссылки, я даже не знал про такой ресурс - очень пригодится!
xADMIRALx - учту на будущее
0
Jupiter
23.07.2012, 10:32
  #6

Не по теме:

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

0
alsav22
5421 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
23.07.2012, 21:19 #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/
0
Avazart
Эксперт С++
7213 / 5385 / 286
Регистрация: 10.12.2010
Сообщений: 23,792
Записей в блоге: 17
23.07.2012, 21:28 #8
Ну я не знаю как стандартная ф-ция может быть не переносимой, а на ignore() я ссылку тоже кинул.
0
alsav22
5421 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
24.07.2012, 05:17 #9
Цитата Сообщение от Avazart Посмотреть сообщение
Ну я не знаю как стандартная ф-ция может быть не переносимой, а на ignore() я ссылку тоже кинул.
Вот ссылка на ту же тему, третий пост: Интересное поведение cin.getline(); Пишут, что
sync() можно, но это не сработает в linux
0
Avazart
Эксперт С++
7213 / 5385 / 286
Регистрация: 10.12.2010
Сообщений: 23,792
Записей в блоге: 17
24.07.2012, 09:45 #10
Да проврерил (в Ubuntu,g++) действительно не работает sinc(), а ignore() работает что странно по тому как назначение ф-ций, как я понимаю, тоже.
0
moskitos80
61 / 61 / 10
Регистрация: 04.10.2011
Сообщений: 217
Завершенные тесты: 1
24.07.2012, 10:59  [ТС] #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()
Но это лишь потому, что до этого я пока ещё наверно не дочитал. А так спасибо ребята за разъяснения. Правда у меня ещё куча вопросов, но это уже другие темы
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
24.07.2012, 11:26 #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++?
0
Jupiter
Каратель
Эксперт С++
6556 / 3977 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
24.07.2012, 11:45 #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 не знаю
0
alsav22
5421 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
24.07.2012, 20:46 #14
Цитата Сообщение от moskitos80 Посмотреть сообщение
Единственное, для меня пока загадка - смысл этой строки
Цитата Сообщение от moskitos80 Посмотреть сообщение
numeric_limits<streamsize>::max()
Шаблонный класс numeric_limits. В данном случае, статический метод max(), выдаёт предельный размер для встроенного типа streamsize (размер потока), для данной платформы. Можно здесь почитать подробнее: http://www.cplusplus.com/reference/s...umeric_limits/ В каких-то компиляторах, требуется: #include <limits>.

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

Getline - C++
Доброго времени суток. В чём ошибка? Пишет, что пространство имён &quot;std&quot; не содержит члена &quot;getline&quot;. while (!std::getline(file,...

getline() - C++
#include &lt;string&gt; #include &lt;iostream&gt; using namespace std ; int main() { string s; cout &lt;&lt; &quot;Vvedite frazu: &quot;; ...

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

getline - C++
подскажите, в чем проблема, не работает getline, если пишу такой же код в другой программке работает, а тут нет #include&lt;iostream&gt; ...


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

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
24.07.2012, 23:31
Ответ Создать тему
Опции темы

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