Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/54: Рейтинг темы: голосов - 54, средняя оценка - 4.67
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517

Не очищается поток после cin.clear()

11.07.2011, 07:55. Показов 11225. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Собственно есть программа записывающая данные в файл и считывающая их оттудова со всеми сопутствующими функциями (новая запись, обновление записей между файлами, печать). Проблема в том что в функции по добавлении записи

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
void newRecord (fstream& file)
{
    int ID; // номер
    string Name;string SName; //имя и фамилия
    double balance; //баланс
 
    try
    {
        cout<<"\nEnter information about client\n(ID, Name, Second Name, balance):\n? ";
        cin>>ID>>Name>>SName>>balance;
 
        if (!cin.good())
         throw exception();
 
        file<<ID<<' '<<Name<<' '<<SName<<' '<<balance<<endl;
 
    }
 
    catch(exception)
    {
        cerr<<"\nError, wrong information";
        cin.clear();
        return;
    }
 
    return;
}
Если пойти по пути выброшенного исключения то программа напишет что есть ошибка и вернётся в главное меню, но при этом вводить ничего больше не получиться, хотя курсор будет мигать. Почему так? На всякий случай вся программа:
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#include <iostream>
#include <iomanip>
#include <cstring>
#include <fstream>
using namespace std;
 
int menu();
void newRecord (fstream&);
void update(fstream&);
void print(fstream&);
 
int main()
{
    fstream trans("trans.dat",ios::in|ios::app);
    fstream oldmast;
    if(!trans)
     cerr<<"\nCritical Error! Can not open file \"trans.dat\"\n";
    int choice=menu();
    while(choice)
    {
        switch (choice)
        {
            case 1:
            newRecord(trans);
            break;
 
            case 2:
            update(trans);
            break;
 
            case 3:
            print(trans);
            break;
 
            case 4:
            oldmast.open("oldmast.dat",ios::in);
            if(!oldmast)
             cerr<<"\nCritical Error! Can not open file \"oldmast.dat\"\n";
            print(oldmast);
            break;
 
            default:
            cerr<<"\nSomething wrong...\n";
        }
        cout<<"\n\n\n";
        if (oldmast)
         oldmast.close();
        choice=menu();
    }
 
 
}
 
int menu()
{
    cout<<"\t\t\tMAIN MENU"<<endl
    <<"1 - new record in DB"<<endl
    <<"2 - update all records"<<endl
    <<"3 - print \"trans.dat\""<<endl
    <<"4 - print \"oldmast.dat\""<<endl
    <<"0 - exit"<<endl
    <<"Enter your choice:\n? ";
    int choice;
    do
     cin>>choice;
    while(choice<0 || choice>4);
 
    return choice;
}
 
void newRecord (fstream& file)
{
    int ID; // номер
    string Name;string SName; //имя и фамилия
    double balance; //баланс
 
    try
    {
        cout<<"\nEnter information about client\n(ID, Name, Second Name, balance):\n? ";
        cin>>ID>>Name>>SName>>balance;
 
        if (!cin.good())
         throw exception();
 
        file<<ID<<' '<<Name<<' '<<SName<<' '<<balance<<endl;
 
    }
 
    catch(exception)
    {
        cerr<<"\nError, wrong information";
        cin.clear();
        return;
    }
 
    return;
}
 
void update(fstream& file)
{
    fstream oldmast("oldmast.dat",ios::out|ios::in);
    ofstream newmast("newmast.dat",ios::out);
    if(!newmast)
     perror("newmast.dat");
    if(!oldmast)
     perror("oldmast.dat");
 
    //установить курсор в начала файлов
    file.seekp(0);
    oldmast.seekp(0);
    newmast.seekp(0);
 
    int ID1,ID2;
    string Name1,Name2;
    string SName1,SName2;
    double balance1,balance2;
    oldmast>>ID1>>Name1>>SName1>>balance1;
 
    //пока есть записи в oldmast которые нужно перенести в newmast
    while(!oldmast.eof())
    {
        //ищем совпадения по ID в нашем файле
        file>>ID2>>Name2>>SName2>>balance2;
        while(!file.eof())
        {
            //если совпадение есть то изменить баланс считанный с oldmast
            if (ID1==ID2)
             balance1+=balance2;
 
            file>>ID2>>Name2>>SName2>>balance2;
        }
        file.clear(); //убрать метку конца файла для возможности последующего считывания
        file.seekp(0); //установить курсор в начало файла
        newmast<<ID1<<' '<<Name1<<' '<<SName1<<' '<<balance1<<endl; //записать данные в newmast
        oldmast>>ID1>>Name1>>SName1>>balance1; // считать новые данные из oldmast
    }
 
    oldmast.clear(); //убрать метку конца файла у oldmast
    file.clear(); //убрать метку конца файла у файла
    file.seekp(0); //установить курсор в начало файла
    oldmast.seekp(0); //установить курсор в начало oldmast.dat
 
 
    // проверить какие записи есть в файле и нет в oldmast
    // и выдать для них предупреждения так как они не будут перенесены
    // в основной файл
    file>>ID2>>Name2>>SName2>>balance2;
    while(!file.eof())
    {
        int flag=0;
 
        oldmast>>ID1>>Name1>>SName1>>balance1;
        while(!oldmast.eof())
        {
            //если номера совпадают то они были перенесены в файл newmast
            if (ID1==ID2)
            {
 
                flag=1;
                break;
            }
 
            oldmast>>ID1>>Name1>>SName1>>balance1;
        }
        oldmast.clear();//убрать метку конца файла у oldmast
        oldmast.seekp(0); //установить курсор на начало файла
 
        // если в oldmast нет записей с таким номером то выдать предупреждение
        if (flag==0)
         cerr<<"\nUnmatched transaction record for account number "<<ID2<<endl;
        file>>ID2>>Name2>>SName2>>balance2;
    }
 
    file.clear();
    //закрыть файлы
    oldmast.close();
    newmast.close();
 
    //удалить oldmast.dat
    if(remove("oldmast.dat"))
     perror("oldmast.dat");
 
    //переименовать newmast.dat в oldmast.dat для последующих операций обновления файлов
    if(rename("newmast.dat","oldmast.dat"))
     perror("newmast.dat");
}
 
void print(fstream& file)
{
    cout<<"\n\n";
    file.seekp(0,ios::end); //перевести курсор в конец файла
    //если при этом курсор будет в начале файла значит файл пуст
    if (!file.tellp())
    {
        cerr<<"\nFile is empty\n\n";
        return;
    }
 
    //иначе установить курсор в начало файла
    file.seekp(0);
    file.clear();
    int ID;
    string Name,SName;
    double balance;
 
    //считать первую строку данных
    file>>ID>>Name>>SName>>balance;
 
    //вывести подписи к данным
    cout<<setw(5)<<left<<"ID"<<setw(7)<<left<<"NAME"
    <<setw(10)<<left<<"Second Name"<<setw(8)<<right<<"BALANCE"<<endl;
 
    //пока есть записи которые можно вывести напечатать их
    while (!file.eof() && file.good())
    {
        cout<<setw(5)<<left<<ID<<setw(7)<<left<<Name
        <<setw(10)<<left<<SName<<setw(8)<<right<<balance<<endl;
 
        file>>ID>>Name>>SName>>balance;
    }
    file.clear();
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.07.2011, 07:55
Ответы с готовыми решениями:

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

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

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

4
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
11.07.2011, 10:36
Попробуй после cin.clear(); добавить cin.sync();
3
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
11.07.2011, 10:48
Цитата Сообщение от Gepar Посмотреть сообщение
C++
1
2
if(!trans) 
  cerr<<"\nCritical Error! Can not open file \"trans.dat\"\n";
Ну сказали пользователю, что есть проблема с открытием файла, и хватит с него, продолжаем выполнять программу... Может всё-таки на этом месте её и завершить, пока пользователь с файлами не разберётся?

Цитата Сообщение от Gepar Посмотреть сообщение
oldmast.open("oldmast.dat",ios::in);
Та же история...

Не факт, что на этом все ошибки кончатся, но так в любом случае не нужно делать...
0
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
11.07.2011, 12:13  [ТС]
easybudda, да, и хватит с него, мне этого достаточно, а пишу это я для себя. Если честно то просто люблю более короткие записи, а когда добавляешь ещё и выход то надо скобки ещё доцеплять же {}, было бы в c++ что-то типа cerr<<... & exit() тогда хорошо Ну а так конечно же Вы правы, это плохая привычка.

Вообще могу прикрепить файлики с тестовыми данными ... нет, не надо, cin.sync() помогло, но как?

У меня изначально при неправильном вводе шла попытка записать символ в переменную int, если это случалось я прерывал выполнение новой записи и ничего не делал и всё возвращалось в main. Но собственно ведь попытка писать символ шла же, те: символ должен был убраться с потока и не застревать там, а он получается застревал ... хотя если бы он застревал то программа же должна была бы зациклиться в меню хотя бы (вывод менюшки-> ловля символа->опять вывод менюшки, такое у меня получалось часто в программах на с++ когда не верные данные вводишь), а оно получалось как-будто клавиатура отваливалась от входящего потока. Так что же происходило подскажите же? Может я до конца не понимаю что же делает cin.sync(). Тут более важно понять чего так, а не радоваться что заработало

Добавлено через 1 минуту
Кстати одного cin.sync() без cin.clear() у меня в программе не достаточно, ровно как и второго без первого (ну это я методом тыка чтобы посмотреть что же делает эта cin.sync() )
0
Freelance
Эксперт С++
 Аватар для asics
2891 / 1826 / 356
Регистрация: 09.09.2010
Сообщений: 3,841
11.07.2011, 13:18
Лучший ответ Сообщение было отмечено как решение

Решение

Gepar, cin.clear() - сброс битов ошибок входного стандартного потока
cin.sync() - очищение буфера стандартного ввода
7
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.07.2011, 13:18
Помогаю со студенческими работами здесь

Проблема с cin.ignore() и cin.clear()
Есть проблема. Добавлено через 11 минут // ConsoleApplication6.cpp: определяет точку входа для консольного приложения. // ...

Cin.clear cin.ignore
Как использовать cin.clear и cin.ignore?

Cin.clear() не работает?
Почему cin.clear() не работает как надо? ( не очищает поток ). Если мы вводим например 3 значения (123) то цикл срабатывает 3 раза. while...

cin.get() и cin.clear()
В общем, занимаюсь по видео-урокам на ютубе, дошли до темы &quot;массивы&quot;. Суть программы - вывести наибольший и наименьший элемент (его...

Сброс состояния буфера cin.clear
Всем привет. Пытаюсь контролировать ввод пользователя. Вопрос в следующем: почему очерёдность операций принципиальна : #include...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru