Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
45 / 0 / 0
Регистрация: 10.04.2016
Сообщений: 114
1

Почему с cin отображается корректно, а с gets() нет?

15.11.2018, 11:51. Показов 3412. Ответов 20

Author24 — интернет-сервис помощи студентам
Всем доброго времени! Сразу к делу. Такая задача стоит. Я ее решил, но остался вопрос:п почему с cin программа все выводит адекватно, а с gets() нет.
Задача: Определить класс Children, который содержит такие поля (члены класса): закрытые – имя ребенка, фамилию и возраст , публичные – методы ввода данных и отображения их на экран. Объявить два объекта класса, внести данные и показать их.

Мое решение:
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
34
35
36
#include <iostream>
#include <cstring>
using namespace std;
 
class children{
        char name[80];
        char surname[80];
        int age;
    public:
        children(){name[80] = 0; surname[80] = 0; age = 0;}
        void put_data(char s[80], char g[80], int i){strcpy(name,s); strcpy(surname, g), age = i;}
        void getData();
};
 
void children::getData()
{
    cout << name << ' ' << surname << ' ' << age << '\n';
}
int main()
{
    children ob[2];
    int i, x;
    char s[80];
    char g[80];
    for(i=0; i<2; i++){
        gets(s);
        gets(g);
        cin >> x; 
        ob[i].put_data(s, g, x);
    }
    cout << "Name" << ' ' << "Surname" << ' ' << "Age" << '\n';
    for(i=0; i<2; i++){
        ob[i].getData();
    }
    return 0;
}
В чем загвоздка? Заранее благодарю за ответы!
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.11.2018, 11:51
Ответы с готовыми решениями:

Почему разметка не отображается корректно во фрагменте?
Есть простейшая разметка: &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;...

Почему при загрузке отображается вариант ВИНДЫ, которой уже нет на диске?
Помогите пожалуйста! Когда-то ВиндовсИксПи стоял на диске D, сейчас переустановил на C, почему при...

Почему в офисе 97 прога заполнения шаблона ворда из файла екселя работает корректно, а в офисе 2000 нет?
люди подскажите почему в офисе 97 прога заполнения шаблона ворда из файла екселя работает...

Считывание чаров из cin происходит не корректно
Доброго времени суток! В процедуре void Enter(char* massive) считываю чары в массив. Если в строке...

20
474 / 426 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
15.11.2018, 11:57 2
Цитата Сообщение от Руслан92 Посмотреть сообщение
а с gets() нет.
Потому что это устаревшая и небезопасная функция.
Используй gets_s(), с входными параметрами строковой переменной и количества символов.
1
45 / 0 / 0
Регистрация: 10.04.2016
Сообщений: 114
15.11.2018, 12:04  [ТС] 3
Это не ответ. gets() тоже существует и до этого момента работал адекватно. То, что она устаревшая и небезопасная не делает ее неадекватной в плане ее функционала.
Высылаю скрины:
1) с gets().
2) с cin.
Миниатюры
Почему с cin отображается корректно, а с gets() нет?   Почему с cin отображается корректно, а с gets() нет?  
0
474 / 426 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
15.11.2018, 13:45 4
Цитата Сообщение от Руслан92 Посмотреть сообщение
делает ее неадекватной в плане ее функционала.
Делает, на то она и "устаревшая и небезопасная".

А еще после считывания возраста, у тебя в потоке остается завершающий нуль-символ '\0'

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
34
35
36
37
38
#include <iostream>
#include <cstring>
 
using namespace std;
 
class children {
    char name[80];
    char surname[80];
    int age;
public:
    children() { name[80] = 0; surname[80] = 0; age = 0; }
    void put_data(char s[80], char g[80], int i) { strcpy_s(name, 79, s); strcpy_s(surname, 79, g), age = i; }
    void getData();
};
 
void children::getData()
{
    cout << name << ' ' << surname << ' ' << age << '\n';
}
int main()
{
    children ob[2];
    int i, x;
    char s[80];
    char g[80];
    for (i = 0; i<2; i++) {
        gets_s(s, 79);
        gets_s(g, 79);
        cin >> x;
        cin.ignore();
        ob[i].put_data(s, g, x);
    }
    cout << "Name" << ' ' << "Surname" << ' ' << "Age" << '\n';
    for (i = 0; i<2; i++) {
        ob[i].getData();
    }
    return 0;
}
1
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
15.11.2018, 13:48 5
SuperKir, она небезопасная в плане переполнения буфера, а не никоим боком не "неадекватная"?
0
474 / 426 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
15.11.2018, 13:49 6
Kuzia domovenok, Именно в этом плане и неадекватная
0
45 / 0 / 0
Регистрация: 10.04.2016
Сообщений: 114
15.11.2018, 14:22  [ТС] 7
То есть gets() у себя в буфере сохраняет все значения и поэтому она с ошибкой выдает мне результат?
А '\0' символ присутствует здесь
C++
1
cout << "Name" << ' ' << "Surname" << ' ' << "Age" << '\n';
? Или где? И на что может повлиять его присутствие?

Добавлено через 2 минуты
Все, увидел где '\0'.
Про gets() ответьте, пожалуйста
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
15.11.2018, 14:23 8
Руслан92, успокойся, этот перфекционист придирается к случаям, когда ты вводишь строку длиною в 80 букв.
Тогда да, очевидно gets провалится. Но мы-то понимаем, что конкретно сейчас проблема не в этом и не время гундеть про "безопасность буфера"
1
45 / 0 / 0
Регистрация: 10.04.2016
Сообщений: 114
15.11.2018, 14:28  [ТС] 9
Хорошо. Тогда ответьте, почему gets() не работает при вводе второй фамилии?...

Добавлено через 26 секунд
И как вы делаете конкретное обращение в чате?)
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
15.11.2018, 14:35 10
Руслан92, gets это функция для чтения строки в широком смысле. - от начала до нажатия Enter
То есть в твоём примере name это "Ruslan Ranzan 26"
surname следующая строка
а не то что ты подумал
1
45 / 0 / 0
Регистрация: 10.04.2016
Сообщений: 114
15.11.2018, 14:48  [ТС] 11
Я Enter после каждого ввода данных нажимаю. И если уж на то пошло, то в "Ruslan Ranzan 26 Dmitry 0" далеко не 80 символов, однако он почему-то завершает строку. Короче муть какая-то...(
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
15.11.2018, 14:54 12
Цитата Сообщение от Руслан92 Посмотреть сообщение
И если уж на то пошло, то в "Ruslan Ranzan 26 Dmitry 0" далеко не 80 символов, однако он почему-то завершает строку.
Я о том и говорю, что рано для SuperKir говорить о переполнении и способах избегать его с помощью gets_s - это просто не тот случай.
Цитата Сообщение от Руслан92 Посмотреть сообщение
Я Enter после каждого ввода данных нажимаю.
я смотрю на скриншот - там "Руслан Рязань 26" всё в одну строчку, плюс, ты изначально спросил о различиях getline и cin.
Ну вот оно - различие! Getline считывает в строковую переменную всю строку с экрана, а cin лишь до пробела
0
474 / 426 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
15.11.2018, 15:25 13
Kuzia domovenok, Про getline речи вообще не шло, ни сначала, ни в конце.
Про ввод - исходил из скринов, на нем видно, что автор понимает, что вводить нужно до enter (наверное).

Здесь не тот случай, но избегать его все же надо.
А проблему я озвучил выше - символ переноса после ввода целочисленной переменной чистить надо.
0
45 / 0 / 0
Регистрация: 10.04.2016
Сообщений: 114
15.11.2018, 15:26  [ТС] 14
Вы на код посмотрите внимательнее. Там в функции-члене класса прописано выводить все в одну строчку через пробел.
И насчет этого различия я прекрасно понимаю, что cin обрезает строки при наличии в них пробела. Но речь не об этом. Повторяю еще раз, дорогие мои помощники, в функции-члене класса прописано выводить все в одну строчку через пробел. Почему gets(s) во второй итерации работает, а gets(g) не работает, а выдает шляпу какую-то.
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
15.11.2018, 15:27 15
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
я смотрю на скриншот - там "Руслан Рязань 26" всё в одну строчку, плюс, ты изначально спросил о различиях getline и cin.
Ну вот оно - различие! Getline считывает в строковую переменную всю строку с экрана, а cin лишь до пробела
я смотрю на скриншот - там "Руслан Рязань 26" всё в одну строчку, плюс, ты изначально спросил о различиях gets и cin.
Ну вот оно - различие! Gets считывает в строковую переменную всю строку с экрана, а cin лишь до пробела

Не по теме:

ты прав, поправил

0
474 / 426 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
15.11.2018, 15:29 16
Руслан92, Потому что после первого ввода символ enter перешел во второй элемент массива в поле ИМЯ, ты вводишь имя для следующего, оно переходит в поле ФАМИЛИЯ, а когда вводишь фамилию, происходит "обнуление", т.к. вводимые данные не являются числом. Вот тебе и вывод "Пусто ИМЯ 0"
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
15.11.2018, 15:31 17
Цитата Сообщение от Руслан92 Посмотреть сообщение
Но речь не об этом. Повторяю еще раз, дорогие мои помощники, в функции-члене класса прописано выводить все в одну строчку через пробел.
а ввод-то тут при чём? cin и cout и gets вообще-то разные вещи. Да , ты можешь вывести несколько строк через << в линию, а вот дать тебе их ввести тебе в gets никто не обещал.
1
474 / 426 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
15.11.2018, 15:33 18
Kuzia domovenok, попробую перевести)
Он говорит, что ты обращаешь внимание на вывод, который у него в одну строку, а его интересует ввод через gets, который он производил через enter
1
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
15.11.2018, 15:35 19
SuperKir, на вывод я вообще не смотрел, наоборот, увидев его ответ, долго думал, что у него там есть в одну строку в программе в функции-члене класса прописано выводить все в одну строчку через пробел
и лишь не сразу понял, что это вывод. При чём тут вывод?
1
474 / 426 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
15.11.2018, 15:36 20
Лучший ответ Сообщение было отмечено Руслан92 как решение

Решение

Руслан92, Еще раз говорю, проблема вся в том, что в потоке, после ввода числа (количества лет), остается символ переноса строки \n (выше я немного не так написал, не \0). Т.к. ты его не чистишь, то получается это:

Цитата Сообщение от SuperKir Посмотреть сообщение
Руслан92, Потому что после первого ввода символ enter перешел во второй элемент массива в поле ИМЯ, ты вводишь имя для следующего, оно переходит в поле ФАМИЛИЯ, а когда вводишь фамилию, происходит "обнуление", т.к. вводимые данные не являются числом. Вот тебе и вывод "Пусто ИМЯ 0"
Сделай очистку потока (как например я привел в коде выше через cin.ignore()) и проблема пропадет.

На этом откланиваюсь, работа зовет)
1
15.11.2018, 15:36
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.11.2018, 15:36
Помогаю со студенческими работами здесь

Как работает cin.peek, cin,get, cin.ignore, cin.clear?
Здравствуйте, товарищи и не товарищи!:) Я только начал изучать C++, а уже использую вещи, которые...

Не корректно отображается в ie
Есть сайт ts21.ru во всех браузерах отображается корректно, а вот в ie никак не хочет нормально...

Защита от дурака при вводе текста с помощью: cin.get cin.clear cin.sync
Доброго времени суток. На С++ учусь с недавних пор. Имеется стандартная &quot;защита от дурака&quot; на ввод....

Объясните пожалуйста как работают cin.good(), cin.sync(), cin.clear()
Такая проблема: сдаю в вуза лабораторные по программированию, писал все сам, до этого c++ не...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru