CodeInside
@CodeInside

Почему происходит пропуск функции считывания строки gets_s?

Для пользователя выводится интерфейс выбора некой функции (в данном случае оставил только функцию addFilm(), ибо она меня и интересует. При вызове функции addFilm() в операторе switch - выводится запрос на считывание данных (название фильма, режиссер и т.д.). Почему-то если вызывать функцию в switch, то выводится "Name-> Director->". То есть пропускается процесс считывания строки name и считывается только строка director. Если вызывать setFilm() или addFilm() в области видимости функции main (не в switch), то всё отлично. Изменяя gets_s на cin - нормально считывает первую строку (name), НО она же считывается без пробелов и при этом же в таком случае при вызове gets_s() для director - пропускается уже строка director. Кто-то может объяснить что за магия и как с ней бороться?
#include <iostream>
#include <conio.h>
#define MAX_CHAR 100
using namespace std;

//жанр
enum Genre
{
	anime, biographical, action, western, military, detective, baby, documentary,
	drama, historical, kinokomiks, comedy, concert, short_film, crime, melodrama,
	mystic, music, cartoon, musical, _scientific, adventure, reality_show, family,
	sport, talk_show, thriller, horror, fantastic, film_noir, fantasy
};

struct Film
{
	char * name;//название фильма
	char * director;//режиссер
	Genre genre;//жанр
	double rating;//рейтинг
	double price;//цена
};
// инициализирует/перезаписывает получаемый объект
void setFilm(Film & film)
{
	cout << "Name-> ";
	char name[MAX_CHAR];
	gets_s(name ,MAX_CHAR);
	//film.name = name;
	film.name = new char[strlen(name) + 1];
	strcpy_s(film.name, strlen(name) + 1, name);

	cout << "Director-> ";
	char director[MAX_CHAR];
	gets_s(director, MAX_CHAR);
	//film.director = director;
	film.director = new char[strlen(director) + 1];
	strcpy_s(film.director, strlen(director) + 1, director);

	//считывание жанра
	showGenres();
	unsigned short genreId;
	do
	{
		cout << "\nGenre id-> ";
		cin >> genreId;
	} while (!setGenre(film, genreId));//выход только если жанр удачно установлен

	cout << "Rating-> ";
	cin >> film.rating;

	cout << "Price-> ";
	cin >> film.price;
}
//выводит всю информацию о фильме
void showFullFilmInfo(Film film)
{
	cout << "\nName-> " << film.name;
	cout << "\nDirector-> " << film.director;
	cout << "\nGenre-> ";
	cout << "genre";// вместо "showGenreOfFilm(film);". Не хочу засорять код ненужными для данного вопроса функциями
	cout << "\nRating-> " << film.rating;
	cout << "\nPrice-> " << film.price << endl;
}
//добавляет объект в конец массива
Film * addFilm(Film * films, int & size)
{
	system("cls");
	Film * nfilms = new Film[size + 1];
	Film obj;
	setFilm(obj);

	for (int i = 0; i < size; i++)
		nfilms[i] = films[i];
	nfilms[size++] = obj;

	return nfilms;
}

void main()
{
	int size = 5;
	Film * films = new Film[size];
	films[0] = { "Interstellar", "Christopher Nolan", fantastic, 8.607, 10.55};
	films[1] = { "The Silence of the Lambs", "Jonathan Demme", horror, 8.349, 4.52 };
	films[2] = { "Cartel Land", "Matt Heineman", documentary, 6.789, 8.99 };
	films[3] = { "Citizenfour", "Laura Poitras", documentary, 7.203, 11.5 };
	films[4] = { "In the Mouth of Madness", "John Carpenter", horror, 6.994, 4.52 };


	//первый тестовый фрагмент кода
	/*setFilm(films[0]);
	showFullFilmInfo(films[0]);
	_getch();*/

	//второй фрагмент кода
	int func_id;
	do
	{
		cout << "1-show films list\n"
			<< "2-add film in list\n"
			<< "3-show full film information\n"
			<< "4-search by name\n"
			<< "5-search by director\n"
			<< "6-search by genre\n"
			<< "7-show most popular film with genre\n"
			<< "8-exit\n\n";
		cout << "Function number-> ";
		cin >> func_id;

		switch (func_id)
		{
		case 1:
			showFilms(films, size);
			break;
		case 2:
			cout << "films = addFilm(films, size)";
			break;
		case 3://show full film information
			//get number(id) of film
			/*int id;
			for (int i = 0; i < size; i++)
				cout << i << '-' << films[i].name << endl;
			cout << "id-> ";
			cin >> id;
			system("cls");*/
			cout << "showFullFilmInfo(films[id])";
			break;
		case 4:
			cout << "searchByName(films, size)";
			break;
		case 5:
			cout << "searchByDirector(films, size)";
			break;
		case 6:
			cout << "searchByGenre(films, size)";
			break;
		case 7:
			cout << "showMostPopularFilmWithGenre(films, size)";
			break;
		case 8:
			exit(1);
		}
	} while (true);
}
  • Вопрос задан
  • 2174 просмотра
Решения вопроса 1
@abcd0x00
Вызов gets_s() проскакивает потому, что при вводе по cin ты нажимаешь Enter в конце. Когда нажимаешь Enter, в поток посылается символ перевода строки и остаётся там. А потом gets_s() видит его и считает введённой строкой. Поэтому ты должен после cin выполнить cin.get()

Пример
#include <iostream>

using namespace std;

int main()
{
    int n;
    char c;

    cin >> n;
    cin.get(c);

    cout << n << " " << int(c) << endl;
    return 0;
}


Вывод
[guest@localhost cpp]$ .iso++ t.cpp -o t
[guest@localhost cpp]$ ./t
123
123 10
[guest@localhost cpp]$


Вот это число 10 - это код символа \n (символа перевода строки).
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@MiiNiPaa
Главная проблема — смешивание форматированного и неформатированного ввода: stackoverflow.com/a/21567292/3410396

И да, не мешайте С и С++. Используйте getline вместо gets_s
Ответ написан
AtomKrieg
@AtomKrieg
Давай я поищу в Google за тебя
Не мешайте С++ и c. Пишите cout - пишите и cin. Нужен gets, используйте printf. Или буфер очищайте. Проблема известная, в интернете полно инфы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы