Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.08.2014, 23:41   #1
GooderSteel
Пользователь
 
Регистрация: 09.10.2011
Сообщений: 11
По умолчанию Некорректно работает функция getline()

Здравствуйте, у меня возник вот такой вопрос. Сижу решаю задания по книге Лафоре "Объектно-ориентированное программирование на С++" и наткнулся на одну непонятность. в качестве решения 2 задачи в главе 7 соорудил данную программку:
Код:
#include <iostream>
#include <string>		//для использования функций работы со строками
using namespace std;
////////////////////////////////////////////////////////////////////////////////

class employee
{
public:
	void getdata();
	void putdata()const;
private:
	string name;
	long number;
};

int main()
{
	setlocale(LC_CTYPE, "rus");
	
	const int MAX = 100;
	employee s[MAX];
	int j = 0;		//переменная используемая для подсчета количества введенных данных пользователем
	char answer;	//символьная переменная, содержащая ответ пользователя
	
	for (int i=0; i < MAX; i++)
	{
		s[i].getdata();
		cout << "Вы хотите продолжить?(y/n): ";
	Request:cin >> answer;
		j++;
		if ((answer != 'y') && (answer != 'n'))
		{
			cout << "Был введен неверный символ. Пожалуйста введите символ заново." << endl;
			goto Request;
		}
		else if (answer == 'n')
		{
			break;	//выход из внутреннего цикла
		}
	}

	for (int i=0; i < j; i++)
	{
		s[i].putdata();
	}

	std::system("pause");
	return 0;
}

void employee::getdata()
{
	cout << "Введите имя сотрудника: ";
	getline(cin, name);
	cout << "Введите его номер: ";
	cin >> number;
}

void employee::putdata()const
{
	cout << "Имя сотрудника: " << name << endl;
	cout << "Номер сотрудника: " << number << endl;
}
И все вроде бы хорошо, если бы не одно но! Для первого ввода имени все работает замечательно, однако когда программа доходит до ввода имени второго сотрудника, то она просто перескакивает функцию getline и переходит сразу же к вводу номера. Вопрос - почему?

Последний раз редактировалось GooderSteel; 27.08.2014 в 23:53.
GooderSteel вне форума Ответить с цитированием
Старый 28.08.2014, 08:10   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

А почему не cin>>name? Почему getline() используешь?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 28.08.2014, 08:54   #3
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Потому что getline считывает строку. Строка заканчивается символом \n или \0, наверное.

Если первый символ в буфере клавиатуры \n, то getline считает пустую строку. Вот так она у тебя и работает. Это правильное поведение.

Request:cin >> answer;

Оператор >> считывает до тех пор, пока не встретит символ-разделитель. При этом сам разделитель (в том числе \n) остается в буфере. И тут ты вызываешь getline, который его считывает.

Короче ты делаешь что-то не так.

Код:
А почему не cin>>name? Почему getline() используешь?
Видимо потому, что >> считывает слово если права от оператора стоит строковый тип. Может быть ТС хочет считать что-то типа "Ivanov Ivan Ivanich", т.е. с пробелами, для этого таки надо вызывать getline.

Последний раз редактировалось Stilet; 28.08.2014 в 09:50.
rrrFer вне форума Ответить с цитированием
Старый 28.08.2014, 09:51   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
т.е. с пробелами
Черт. Все забываю о неудачной реализации cin.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 28.08.2014, 10:46   #5
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
Черт. Все забываю о неудачной реализации cin.
хз, мне кажется удачно все.
cin тут не при чем вроде бы, этож просто поток. Если винить, то оператор >>, но я думаю что он так и должен работать - удобно например строку на слова разделять... Ну если уж очень хочется - имхо можно перегрузить свой оператор и реализовать как угодно....
rrrFer вне форума Ответить с цитированием
Старый 28.08.2014, 11:51   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
удобно например строку на слова разделять...
Ну мне было бы удобнее считать всю строку, а потом применить какойнить split()
Или еще лучше для cin настроить некое свойство - конец строки. Вот типа setprecios() (или как оно там правильно называется) для cout сделали бы, чтоб можно было разделитель строки задавать, было бы замечтательно. А може и есть такое, токма я не знаю о сем.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 28.08.2014, 20:08   #7
GooderSteel
Пользователь
 
Регистрация: 09.10.2011
Сообщений: 11
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
Потому что getline считывает строку. Строка заканчивается символом \n или \0, наверное.

Если первый символ в буфере клавиатуры \n, то getline считает пустую строку. Вот так она у тебя и работает. Это правильное поведение.

Request:cin >> answer;

Оператор >> считывает до тех пор, пока не встретит символ-разделитель. При этом сам разделитель (в том числе \n) остается в буфере. И тут ты вызываешь getline, который его считывает.

Короче ты делаешь что-то не так.

Код:
А почему не cin>>name? Почему getline() используешь?
Видимо потому, что >> считывает слово если права от оператора стоит строковый тип. Может быть ТС хочет считать что-то типа "Ivanov Ivan Ivanich", т.е. с пробелами, для этого таки надо вызывать getline.
Да, именно так, в книге поставлена задача считать имя, которое может содержать пробелы..а в конце книги почему-то приведен неверный ответ)
GooderSteel вне форума Ответить с цитированием
Старый 28.08.2014, 20:10   #8
GooderSteel
Пользователь
 
Регистрация: 09.10.2011
Сообщений: 11
По умолчанию

На работе, знакомый программист мне сказал, что нужно как-то обнулять функцию после каждого использования, однако, я пока так и не понял каким именно образом..)
GooderSteel вне форума Ответить с цитированием
Старый 28.08.2014, 20:13   #9
GooderSteel
Пользователь
 
Регистрация: 09.10.2011
Сообщений: 11
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
А почему не cin>>name? Почему getline() используешь?
Просто в условии задачи сказано, что имя может содержать пробелы.. а cin >>, насколько мне известно не может вводить строки с пробелами..как-то так..
GooderSteel вне форума Ответить с цитированием
Старый 28.08.2014, 20:16   #10
GooderSteel
Пользователь
 
Регистрация: 09.10.2011
Сообщений: 11
По умолчанию

Не судите строго только) я в С++ только начинаю писать.. на работе использую другие языки программирования, такие как С и System Verilog, VHDL.. а С++ занялся скорее ради хобби.. хочу попытаться сделать маленькую игру)
GooderSteel вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
функция счётесли работает некорректно Pavelasd Microsoft Office Excel 2 04.05.2014 02:05
Функция ВПР работает некорректно Витальян Microsoft Office Excel 4 06.12.2013 00:20
Не работает с первого раза getline AxenicX Помощь студентам 2 28.11.2009 23:43
Функция С++ getline() Golovastik Общие вопросы C/C++ 8 30.07.2009 00:20