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

Очистка потока ввода && строки - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 95, средняя оценка - 4.71
[WRG]
 Аватар для [WRG]
50 / 50 / 9
Регистрация: 20.11.2011
Сообщений: 243
Записей в блоге: 1
26.02.2013, 23:04     Очистка потока ввода && строки #1
как вобще грамотно очистить поток после ввода множества всяких вещей с клавиатуры?
если совсем не чистить то остаются нажатия клавиши enter, если применять такой код
C++
1
2
3
cin.clear();
while(cin.get() != '\n');
cin.get();
в конце каждой функции в программе, где происходит ввод, то в итоге пользователю приходится 4-5 лишних раз давить enter после ввода чего либо, т.е. эффект обратный. как реализовать очистку потока вывода грамотно?

и еще, есть функция
C++
1
2
3
4
5
6
7
8
void initialize_values(goods *db)
{
    for (int i = 0; i < base_size; i++) {
        strcpy(db[i].value, '\0');
        db[i].cost = 0;
        db[i].quantity = 0;
    }
}
инициализирует массив записей при старте программы. в дальнейшем предполагается использовать db[i].value как критерий существования записи: если строка нулевая, то запись пустая и её можно заполнить. но у меня почему то не получается использовать if(!db[i].value) { ...........}, он просто не срабатывет. причем если value инициализировано как strcpy(db[i].value, '\0') ,то программа выдает просто segmentation vault и не работает, а если strcpy(db[i].value, "\0"), то компилируется без ошибок, но опять же if(!db[i].value) { ...........} не работает. в чем ошибка?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.02.2013, 23:04     Очистка потока ввода && строки
Посмотрите здесь:

Очистка потока ввода C++
Ввод данных в string, очистка потока ввода C++
Цикл и строки, очистка потока ввода C++
Телефонный справочник. Очистка потока ввода C++
Очистка потока ввода C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
26.02.2013, 23:26     Очистка потока ввода && строки #2
Цитата Сообщение от [WRG
;4186036]если применять такой код:
cin.clear();
while(cin.get() != '\n');
cin.get();
в конце каждой функции в программе, где происходит ввод, то в итоге пользователю приходится 4-5 лишних раз давить enter после ввода чего либо, т.е. эффект обратный. как реализовать очистку потока вывода грамотно?
Код для очистки вполне годится, только зачем в конце cin.get(); ? Поток уже чист. Лишнее ожидание ввода. Ещё способы: http://cppstudy.wordpress.com/2009/0...in-get-and-co/
[WRG]
 Аватар для [WRG]
50 / 50 / 9
Регистрация: 20.11.2011
Сообщений: 243
Записей в блоге: 1
27.02.2013, 12:13  [ТС]     Очистка потока ввода && строки #3
поток то может и чист, но в том месте где программа должна читать строку она это место пропускает, не дожидаясь ввода и нажатия enter. для этого и нужен cin.get() но все же тогда требуются лишние нажатия enter, не могу понять почему
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
27.02.2013, 18:11     Очистка потока ввода && строки #4
Ещё раз. После этой конструкции:
C++
1
2
cin.clear();
while(cin.get() != '\n');
в потоке никакого '\n' уже нет (извлекается последним перед выходом из while()). Поток чист и готов к работе. Дополнительное нажатие Enter будет требоваться как раз тогда, когда после этой конструкции поставить ещё и cin.get(). А если что-то где-то пропускается, то покажите код.
vua72
410 / 410 / 83
Регистрация: 28.11.2010
Сообщений: 1,158
27.02.2013, 18:15     Очистка потока ввода && строки #5
не мешайте разные методы ввода, или все cin, или cin.getline, или getline. Тогда проблем н будет.
xtorne21st
интересующийся
300 / 271 / 19
Регистрация: 25.09.2010
Сообщений: 1,056
27.02.2013, 18:30     Очистка потока ввода && строки #6
C++
1
#define CIN_FLUSH if (std::cin.peek()) std::cin.ignore()
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
27.02.2013, 18:32     Очистка потока ввода && строки #7
Моё мнение, что дело не в этом. Мешать приходится, потому что эти методы для разного. Если бы они были полностью взаимозаменяемы, тогда да. Через getline() и cin.getline() не считать число или одиночный символ, через cin.getline() не считать объект string(или требуются дополнительные преобразования). Они специально сделаны разными, чтобы удобнее было использовать в разных случаях. Прсто нужно знать особенности каждого метода.
[WRG]
 Аватар для [WRG]
50 / 50 / 9
Регистрация: 20.11.2011
Сообщений: 243
Записей в блоге: 1
27.02.2013, 21:54  [ТС]     Очистка потока ввода && строки #8
вот код, очистку оформил в виде функции, чтобы использовать после каждого ввода
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
 
const int base_size = 100; //максимальный размер базы данных
 
struct goods {
    char value[30];
    float cost;
    unsigned int quantity;
};
 
char show_menu(); //готово вроде как
void initialize_values(goods *db);  //готово вроде как
int find_end_of_db(goods *db);  //должно возврашать -1 если база заполнена, вроде готово
void add_item(goods *db, int position);
void delete_item(goods *db, int position);
void show_item(goods *db, int position);
void flush_stdin();
 
 
//******************MAIN*******************
int main(int argc, char *argv[])
{
    goods base[base_size];
    char user_choice;
    
    initialize_values(base);
    
    do {
        user_choice = show_menu();
        switch(user_choice) {
            case 'a': {
                int *end = new int (find_end_of_db(base));
                if (*end == -1) {
                    cout << "База заполнена! Удалите ненужные записи" << endl;
                    //if(system("cls")) system ("clear");
                    continue;
                }
                add_item(base, *end);
                delete end;
                break;
            }
            case 'd': {
                int *choice = new int;
                do {
                    cout << "Введите номер удаляемой записи -> " << endl;
                    cin >> *choice;
                    if ((*choice < 0) || (*choice > base_size)) {
                        cout << "Недопустимое значение! Введите заново" << endl;    
                    }
                } while ((*choice < 0) || (*choice > base_size));
                delete_item(base, *choice);
                delete choice; 
                break;
            }
            case 's': {
                char *s = new char;
                char *pch = 0;
                bool found = false;
                cout << "Введите навание товара -> ";
                gets(s);
                for (int i = 0; i < base_size; i++) {
                    pch = strstr(base[i].value, s); 
                    if (pch) {
                        show_item(base, i);
                        found = true;
                    };
                }
                if (!found) cout << "Ни одной записи с таким именем не найдено!" << endl;
                break;
            }
        }
        
        flush_stdin();
    } while (user_choice != 'q');
    
    
    return 0;
}
 
//****************SHOW MENU****************
char show_menu()
{
    char choice;
    bool stop = false;
    
    do {
        cout << "Выберите нужный пункт меню" << endl;
        cout << "a - добавить запись в базу" << endl;
        cout << "d - удалить запись из базы" << endl;
        cout << "s - показать запись из базы" << endl;
        cout << "q - выход из программы" << endl;
        cout << "-> ";
        cin >> choice;
        if ((choice =='a') || (choice =='d') || (choice =='s') || (choice == 'q')) stop = true;
        else cout << "Ошибка ввода. Повторите ввод" << endl;
    } while (!stop);
    
    flush_stdin();
    
    return choice;
}
 
//******************INITIALIZE VALUES**********
void initialize_values(goods *db)
{
    for (int i = 0; i < base_size; i++) {
        strcpy(db[i].value, "\0");
        //db[i].value = '\0';
        db[i].cost = 0;
        db[i].quantity = 0;
    }
}
 
//*****************FIND END OF DB*****************
int find_end_of_db(goods *db)
{
    int i;
    for (i = 0; i < base_size; i++) {
        if (!db[i].cost) break;
    }
    if (i == base_size) return -1;
    return i;
}
 
//******************ADD ITEM******************
void add_item(goods *db, int position)
{
    cout << "Ввод записи №" << position << endl;
    cout << "Введите название товара: ";
    gets(db[position].value);
    cout << endl;
    cout << "Введите стоимость товара: ";
    cin >> db[position].cost;
    cout << endl;
    cout << "Введите количество товара на складе: ";
    cin >> db[position].quantity;
    cout << endl;
    
    flush_stdin();
}
 
 
//*****************DELETE ITEM*************
void delete_item(goods *db, int position)
{
    cout << "Удаление записи №" << position << endl;
    strstr(db[position].value, "\0");
    db[position] .cost = 0;
    db[position].quantity = 0;
    cout << "Запись №"<< position << "успешно удалена!" << endl;
    
    flush_stdin();
}
 
//*******************SHOW ITEMS**************
void show_item(goods *db, int position)
{
    cout << "Вывод записи №" << position << endl;
    cout << "Название товара: " << db[position].value << endl;
    cout << "Стоимость товара: " << db[position].cost << endl;
    cout << "Количество товара на складе: " << db[position].quantity << endl;
    cout << endl;
    
    flush_stdin();
}
 
void flush_stdin()
{
    cin.clear();
    while(cin.get() != '\n');
}
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
27.02.2013, 22:25     Очистка потока ввода && строки #9
И где лишний раз Enter приходится нажимать?
[WRG]
 Аватар для [WRG]
50 / 50 / 9
Регистрация: 20.11.2011
Сообщений: 243
Записей в блоге: 1
27.02.2013, 23:13  [ТС]     Очистка потока ввода && строки #10
да хоть где, например ввел запись, вывел ее на экран, и он ждет нескольких нажатий enter, или после всего этого если нажать q в меню то тоже несколько раз придется enter давить чтобы завершилась программа наконец
xtorne21st
интересующийся
300 / 271 / 19
Регистрация: 25.09.2010
Сообщений: 1,056
27.02.2013, 23:32     Очистка потока ввода && строки #11
Цитата Сообщение от [WRG
;4190257]while(cin.get() != '\n');
поробуйте вместо этого цикла воспользоваться макросом, который я описал выше
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
27.02.2013, 23:46     Очистка потока ввода && строки #12
Просто вы навставляли очистку потока где надо и где не надо. Нужно только после cin >> перед gets(), getline() и т.п. В частности, уберите flush_stdin(); в 77 строке и из тех функций, где нет ввода через cin >>.

Добавлено через 4 минуты
А вот что лучше не делать, так это использовать одновременно и функции ввода-вывода С и потоки С++. Лучше, наверное, что-то одно.
vua72
410 / 410 / 83
Регистрация: 28.11.2010
Сообщений: 1,158
28.02.2013, 00:13     Очистка потока ввода && строки #13
Прата так делает (пример 17.15, 2011 г.):
C++
1
inline void eatline() { while (std::cin.get() != '\n') continue; }
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
28.02.2013, 00:17     Очистка потока ввода && строки #14
C++
1
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.02.2013, 00:59     Очистка потока ввода && строки #15
Цитата Сообщение от vua72 Посмотреть сообщение
Прата так делает (пример 17.15, 2011 г.):
C++
1
inline void eatline() { while (std::cin.get() != '\n') continue; }
Не понимаю только, что это continue даёт?
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
28.02.2013, 01:24     Очистка потока ввода && строки #16
http://www.daniweb.com/software-deve...e-input-stream
В частности код:

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
39
40
41
42
43
44
#include <ios>
#include <istream>
#include <limits>
template <typename CharT>
std::streamsize ignore_line (
  std::basic_istream<CharT>& in, bool always_discard = false )
{
  std::streamsize nread = 0;
  if ( always_discard
    || ( in.rdbuf()->sungetc() != std::char_traits<CharT>::eof()
    && in.get() != in.widen ( '\n' ) ) )
  {
    // The stream is good, and we haven't
    // read a full line yet, so clear it out
    in.ignore ( std::numeric_limits<std::streamsize>::max(), in.widen ( '\n' ) );
    nread = in.gcount();
  }
  return nread;
}
class ignoreline {
  bool _always_discard;
  mutable std::streamsize _nread;
public:
  ignoreline ( bool always_discard = false )
    : _always_discard ( always_discard ), _nread ( 0 )
  {}
  std::streamsize gcount() const { return _nread; }
  template <typename CharT>
  friend std::basic_istream<CharT>& operator>> (
    std::basic_istream<CharT>& in, const ignoreline& manip )
  {
    manip._nread = ignore_line ( in, manip._always_discard );
    return in;
  }
};
 
int main()
{
  std::cout<<"First input: ";
  std::cin.get();
  std::cout<<"Clearing cin.\n";
  std::cin>> ignoreline();
  std::cout<<"All done.\n";
}
vua72
410 / 410 / 83
Регистрация: 28.11.2010
Сообщений: 1,158
28.02.2013, 01:31     Очистка потока ввода && строки #17
Цитата Сообщение от alsav22 Посмотреть сообщение
Не понимаю только, что это continue даёт?
отбрасывает остаток строки, если строка была прочитана не полностью.
Там пример такой
Кликните здесь для просмотра всего текста
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
// truncate.cpp -- using get() to truncate input line, if necessary
#include <iostream>
const int SLEN = 10;
inline void eatline() { while (std::cin.get() != '\n') continue; }
int main()
{
    using std::cin;
    using std::cout;
    using std::endl;
 
    char name[SLEN];
    char title[SLEN];
    cout << "Enter your name: ";
    cin.get(name,SLEN);
    if (cin.peek() != '\n')
        cout << "Sorry, we only have enough room for "
                << name << endl;
    eatline();
    cout << "Dear " << name << ", enter your title: \n";
    cin.get(title,SLEN);
    if (cin.peek() != '\n')
        cout << "We were forced to truncate your title.\n";
    eatline();
    cout << " Name: " << name
         << "\nTitle: " << title << endl;
    // cin.get();
    return 0; 
}
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
28.02.2013, 01:36     Очистка потока ввода && строки #18
vua72, этот continue там ни к чему, и написан, скорей всего, просто для читаемости.
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
28.02.2013, 01:38     Очистка потока ввода && строки #19
Цитата Сообщение от alsav22 Посмотреть сообщение
Не понимаю только, что это continue даёт?
Ничего. Возможно для ясности.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.02.2013, 01:44     Очистка потока ввода && строки
Еще ссылки по теме:

Выполнение цикла. Очистка потока ввода C++
C++ Класс Person. Очистка потока ввода
C++ Очистка потока

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

Или воспользуйтесь поиском по форуму:
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.02.2013, 01:44     Очистка потока ввода && строки #20
Цитата Сообщение от vua72 Посмотреть сообщение
отбрасывает остаток строки, если строка была прочитана не полностью.
Куда что там отбрасывать, если чтение по символу, пока не встретится '\n'? Что с continue, что без...
Yandex
Объявления
28.02.2013, 01:44     Очистка потока ввода && строки
Ответ Создать тему
Опции темы

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