Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
Программист
33 / 33 / 8
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1

Универсальная функция получения числа через cin

30.10.2013, 00:51. Показов 3296. Ответов 31
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Пытался написать универсальную функцию для гарантированного получения числа нужного типа, примерно так:

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
// Функция для безопасного получения числа указанного типа,
// оставляет поток cin в корректном состояние, вроде бы гарантированно
template <class T = double>
T getNum(const T &min = numeric_limits<T>::lowest(),
         const T &max = numeric_limits<T>::max())
{
    if (max < min)
        throw string("Ошибка в аргументах getNum, минимум больше максимума");
 
    // Для очистки потока от некорректного состояния
    auto clear = []()
    {
        cin.clear();
        cin.ignore(numeric_limits<std::streamsize>::max(), '\n');
        //cin.sync();
        //cin.clear();
    };
 
    T num(0);
 
    do
    {
        cout << "Число должно быть больше или равно " << min
             << " и меньше или равно "                << max
             << endl;
 
        cin >> num;
 
        if (cin.fail() || cin.bad() || cin.eof())
        {
            clear();
            continue;
        }
 
    }
    while((static_cast<T>(num) < min) || (static_cast<T>(num) > max));
 
    clear();
 
    return static_cast<T>(num);
}
но что-то она не очень работает, точнее не обрабатывает как должна ввод текста вместо числа.
В частности при вызове с аргументом шаблона T = long double и рандовном набивание символов
num присваивается 0, а clear то ли не отрабатывает как надо, то ли еще что... в общем все работает не так.
Светлые умы, помогите довести до ума кто знает как

Добавлено через 18 минут
Кстати также некорректно обрабатывает ввод типа 2,,3, при нем двойка считывается как корректное значение, но поток не очищается от мусора, как я понимаю(а было бы не плохо все это непотребство отбраковывать и требовать повторный ввод).
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.10.2013, 00:51
Ответы с готовыми решениями:

Заполнить массив цифрами числа, считанного через cin
Здрасти, как ввести в массив int mMass число 12345 с помощью cin&gt;&gt;? Нужно чтобы в mMass записалась 1, в mMass записалась 2 .... и...

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

Универсальная функция
1.Определим функцию K(n), которая определяет количество цифр в заданном натуральном числе n. 2. Вычисление квадрата целого числа m,...

31
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2013, 03:13
Студворк — интернет-сервис помощи студентам
Вот этот будет работать, mingw почему-то не нравится cin.ignore(cin.rdbuf()->in_avail()) :
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
#include <iostream>
#include <limits>
#include <cstdlib>
#include <windows.h>
using namespace std;
 
// Функция для безопасного получения числа указанного типа,
// оставляет поток cin в корректном состояние, вроде бы гарантированно
template <class T>
T getNum(const T &min = numeric_limits<T>::lowest(),
         const T &max = numeric_limits<T>::max())
{
    if (max < min)
        throw string("Ошибка в аргументах getNum, минимум больше максимума");
 
    T num(0);
    
    do
    {
        cout << "Число должно быть больше или равно " << min
                 << " и меньше или равно "            << max
                 << endl;
 
        while (!(cin >> num) || (cin.peek() != '\n'))
        {
            cin.clear();
            while (cin.get() != '\n');
            cout << "Ошибка ввода!" << endl;
        }
 
    } while (num < min || num > max);
 
    return num;
}
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
    getNum(2, 6);
 
    system("pause");
    return 0;
}
Добавлено через 2 минуты
Потом нужно будет разобраться, что ему не нравится.

Добавлено через 1 минуту
MrGluck, в Linux, кстати, sync() не работает. По-моему, у вас, один из вариантов, использует.
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
30.10.2013, 03:18
C++
1
2
3
4
5
6
while (!(cin >> num) || (cin.peek() != '\n'))
{
    cin.clear();
    cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
    cout << "Ошибка ввода!" << endl;
}
cin.rdbuf()->in_avail(); возвращала 0

Добавлено через 3 минуты
in_avail() returns the number of chars it can see in the internal buffer, if any. Otherwise it calls showmanyc() to try to detect if chars are known to be available elsewhere, so a buffer fill request is guaranteed to succeed.

In turn, showmanyc() will return the number of chars it knows about, if any, or -1 if it knows that a read will fail, or 0 if it doesn't have a clue.
1
Программист
33 / 33 / 8
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
30.10.2013, 03:22  [ТС]
Так, подтверждаю работоспособность последнего выложенного кода на своей машине, большое спасибо.
Никогда не дружил с "заскоками" iostream'ов, завтра на свежую голову поизучаю повнимательнее, что где было не так.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2013, 03:29
Вот ещё, добавил предварительнное восстановление потока, если ломается до вызова функции:
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
#include <iostream>
#include <limits>
#include <cstdlib>
#include <windows.h>
using namespace std;
 
// Функция для безопасного получения числа указанного типа,
// оставляет поток cin в корректном состояние, вроде бы гарантированно
template <class T>
T getNum(const T &min = numeric_limits<T>::lowest(),
         const T &max = numeric_limits<T>::max())
{
    if (max < min)
        throw string("Ошибка в аргументах getNum, минимум больше максимума");
 
    T num(0);
 
     if (!cin)
     {
         cin.clear();
         cin.ignore(numeric_limits<streamsize>::max(), '\n');
     }
 
     do
    {
        cout << "Число должно быть больше или равно " << min
                 << " и меньше или равно "            << max
                 << endl;
 
        while (!(cin >> num) || (cin.peek() != '\n'))
        {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "Ошибка ввода!" << endl;
        }
 
    } while (num < min || num > max);
 
    return num;
}
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
    getNum(2, 6);
 
    system("pause");
    return 0;
}
Добавлено через 2 минуты
Цитата Сообщение от MrGluck Посмотреть сообщение
cin.rdbuf()->in_avail(); возвращала 0
MrGluck, если по-русски, почему?
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
30.10.2013, 03:30
Whiteha, однако на бубунте работает. Пруф:
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
30.10.2013, 03:31
del
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2013, 03:50
Цитата Сообщение от MrGluck Посмотреть сообщение
cin.rdbuf()->in_avail(); возвращала 0
Добавлено через 3 минуты
in_avail() returns the number of chars it can see in the internal buffer, if any. Otherwise it calls showmanyc() to try to detect if chars are known to be available elsewhere, so a buffer fill request is guaranteed to succeed.
In turn, showmanyc() will return the number of chars it knows about, if any, or -1 if it knows that a read will fail, or 0 if it doesn't have a clue.
Если по-русски, почему?
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
30.10.2013, 03:59
Цитата Сообщение от alsav22 Посмотреть сообщение
MrGluck, если по-русски, почему?
Оно кидает исключение
В описании http://www.cplusplus.com/refer... /in_avail/
Basic guarantee: if an exception is thrown, the stream buffer is in a valid state (this also applies to standard derived classes).
Видимо в старых компиляторах это не реализовано.
Исключение выдает basic_ios::clear.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2013, 04:07
Цитата Сообщение от MrGluck Посмотреть сообщение
Видимо в старых компиляторах это не реализовано.
Не реализовано что?
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
30.10.2013, 04:14
Цитата Сообщение от alsav22 Посмотреть сообщение
Не реализовано что?
В новых компиляторах кидает исключение, из-за чего поток остается в "рабочем состоянии". В старых это не делает.

Добавлено через 5 минут
Это лишь предположение.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.10.2013, 04:17
Цитата Сообщение от MrGluck Посмотреть сообщение
В новых компиляторах кидает исключение, из-за чего поток остается в "рабочем состоянии". В старых это не делает.
По какому поводу исключение? mingw 4.8.0 разве старый?
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
30.10.2013, 04:28
Цитата Сообщение от alsav22 Посмотреть сообщение
По какому поводу исключение? mingw 4.8.0 разве старый?
Исключение при перехвате выдает basic_ios::clear.
Нашел решение:
нужно добавить строку
C++
1
ios_base::sync_with_stdio(0);
и использовать
C++
1
2
cin.clear();
cin.ignore(cin.rdbuf()->in_avail(), '\n');
Добавлено через 3 минуты
А MS судя по всему с борландом синхронизируют любой поток и функция ios_base::sync_with_stdio() у них вообще не реализована толком.

Добавлено через 1 минуту
Цитата Сообщение от alsav22 Посмотреть сообщение
mingw 4.8.0 разве старый?
у меня именно этот мингв исключение кидал.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
30.10.2013, 04:28

Универсальная функция
Напишите пожалуйста прогу.Написать универсальную функцию для вычислениия заданных выражений.В main() обеспечить вызов этой функции и...

Универсальная функция
Здравствуйте! Прошу помощи. Можно сделать какую-нибудь универсальную функцию, которой можно было бы передавать массив заголовков столбцов и...

Универсальная функция Ajax
Хочу сделать универсальную функцию Ajax, но не получаеться получить ответ сразу, функция выполняется, а потом приходит ответ... Как...

Универсальная функция вывода
Господа, пытаюсь сделать функцию, которая напечатает массив, и будет универсальна для всех типов и одной структуры. Вот пока все мои...

Универсальная функция запросов в базу
Здравствуйте. Есть несколько мест в коде где идет 6-8 запросов в базу, запросы различные (select,insert,update,вызов процедур) запихать...


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

Или воспользуйтесь поиском по форуму:
32
Ответ Создать тему
Новые блоги и статьи
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru