Проверка ввода C++ (Почему-то не хочет работать)

Модератор: Модераторы разделов

Kondrat
Сообщения: 223
ОС: И снова Федора

Проверка ввода C++

Сообщение Kondrat »

Написал программу для вывода простых чисел от 0 до заданного пользователем. Споткнулся на проверке введенных символов. Вот текст программы:

Код:

#include <iostream> #include <cmath> #include <cctype> using namespace std; int main() { int i, n, ent; bool sost; cout << "Введите число от 0 до" << pow(16, sizeof(int)) << ": "; cin >>ent; --> Закомментированное ниже работает без вопросов /* if (!isdigit(ent)) { cout << "Ошибка: это не число"; return 1; } */ while (ent < 0 || ent > pow(16, sizeof(int)) || (!isdigit(ent)))<-- Последнее условие не работает { cout << "Ошибка: введите правильное число\nПопробуйте снова :"; cin >> ent; } for (i = 2; i <= ent; i++) { for (n = 2; n <= sqrt(i); n++) if (!(i % n)) sost = 1; if (!(sost)) cout << i << "\n"; sost = 0; } return 0; }


Проблема в том, что отдельно проверка вводимого выполняется, но при этом завершается работа программы. Мне же надо, чтобы выводилось сообщение об ошибке и можно было бы повторить ввод. В случае добавления данного условия к оператору while просто циклически выводится сообщение без возможности ввести что-либо. Что я сделал не так?
Ёж - птица гордая: пока не пнёшь, не полетит.
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: Проверка ввода C++

Сообщение ZyX »

1) Оператор бинарного сдвига в C++ разве отсутствует (я про то, что 2 в степени
n можно записать как 1<<n, не привлекая абсолютно ненужную и к тому же
неточную pow).

2) Вы читали man isdigit? Эта функция проверяет, является ли символ
цифрой. isdigit(ent)=1 ⇔ '0'≤ent≤'9' || 'a'≤ent≤'f' || 'A'≤ent≤'F'.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Проверка ввода C++

Сообщение NickLion »

// оптимизируем :) Для этой задачи лучше использовать решето Эратосфена. Ну и там же ссылка на улучшенный алгоритм (но онне такой простой).
Спасибо сказали:
Kondrat
Сообщения: 223
ОС: И снова Федора

Re: Проверка ввода C++

Сообщение Kondrat »

[b}ZyX[b], 1)с побитовым сдвигом пока не разобрался, так что использовал то, что знаю.
2) То о чем вы написали, является функцией isxdigit, и она действительно проверяет 16-ричные числа. Но у меня осуществлялась проверка десятичных чисел, поэтому использовал isdigit.

NickLion, спасибо за ссылку, попробую реализовать.

Но главный вопрос остается в силе: как сделать, чтобы после проверки вводимого на корректность символов программа не завершалась, а повторно запрашивала число?
Ёж - птица гордая: пока не пнёшь, не полетит.
Спасибо сказали:
Аватара пользователя
Cra3y
Сообщения: 80
ОС: Debian

Re: Проверка ввода C++

Сообщение Cra3y »

Можно, например, так:

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

long enternum() {
 long result;
 char* str = NULL;
 size_t len = 0;

 do {
  errno = 0;
  if (str) {
   free(str);
   str = NULL;
  }
  fputs("Enter number > ");
  getline(&str, &len, stdin);
  result = strtol(str, NULL, 10);
 }
 while((errno == EINVAL)||(errno == ERANGE));
 if (str) {
  free(str);
  str = NULL;
 }
 return result;
}

int main (int argc, char ** argv) {
 long num;
 do {
  puts("Number from 0 to .....");
  num = enternum();
 }
 while ((num < 0)||(num > 16));
 return 0;
}

Описания используемых функций есть в манах
HP G62 (AMD Phenom II x3 1.8GHz 4GB DDR3 Ram) / Debian 8 amd64
Спасибо сказали:
Аватара пользователя
Crazy
Сообщения: 862
Статус: Адепт Дзен.
ОС: Mint, Win7.

Re: Проверка ввода C++

Сообщение Crazy »

Код: Выделить всё

#include <iostream>
#include <cmath>

bool Valid(int val);

int main()
{
    while(true)
    {
        std::cout << "Введите число от 0 до" << pow(16, sizeof(int)) << ": ";
        int ent;
        std::cin.unsetf(std::ios::skipws);
        std::cin >>ent;
        if(!Valid(ent))
        {
            std::cout << "Chislo dolzno bit [0.."<<pow(16, sizeof(int))<<"]"<<std::endl;
            std::cin.clear(std::ios::failbit);
        }
        if(std::cin.good())
        {
            std::cin.ignore(10, '\n');
            break;
        }
        std::cin.clear();
        std::cin.ignore(10, '\n');
        std::cout<<"Nepravilniy vvod\n";
    }
}

bool Valid(int val)
{
    if( (val>=0) && (val<=pow(16, sizeof(int)))) return true;
    return false;
}

Desipere in loco
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: Проверка ввода C++

Сообщение ZyX »

Kondrat писал(а):
07.10.2009 23:59
[b}ZyX[b], 1)с побитовым сдвигом пока не разобрался, так что использовал то, что знаю.
2) То о чем вы написали, является функцией isxdigit, и она действительно проверяет 16-ричные числа. Но у меня осуществлялась проверка десятичных чисел, поэтому использовал isdigit.

NickLion, спасибо за ссылку, попробую реализовать.

Но главный вопрос остается в силе: как сделать, чтобы после проверки вводимого на корректность символов программа не завершалась, а повторно запрашивала число?

Да, перепутал (в man isdigit куча других функций, а isxdigit самая выделяющаяся
из-за строчки из жирных зелёных чисел). Но суть осталась: '0'≤ent≤'9'.
А cin<<ent запишет в ent число, полученно из стандартного ввода: если
в стандартном вводе "0", то cin запишет в ent 0, а 0<'0'. Что isdigit, что
isxdigit предназначены для символов.
Спасибо сказали:
Аватара пользователя
Crazy
Сообщения: 862
Статус: Адепт Дзен.
ОС: Mint, Win7.

Re: Проверка ввода C++

Сообщение Crazy »

ZyX писал(а):
08.10.2009 02:02
Kondrat писал(а):
07.10.2009 23:59
[b}ZyX[b], 1)с побитовым сдвигом пока не разобрался, так что использовал то, что знаю.
2) То о чем вы написали, является функцией isxdigit, и она действительно проверяет 16-ричные числа. Но у меня осуществлялась проверка десятичных чисел, поэтому использовал isdigit.

NickLion, спасибо за ссылку, попробую реализовать.

Но главный вопрос остается в силе: как сделать, чтобы после проверки вводимого на корректность символов программа не завершалась, а повторно запрашивала число?

Да, перепутал (в man isdigit куча других функций, а isxdigit самая выделяющаяся
из-за строчки из жирных зелёных чисел). Но суть осталась: '0'≤ent≤'9'.
А cin<<ent запишет в ent число, полученно из стандартного ввода: если
в стандартном вводе "0", то cin запишет в ent 0, а 0<'0'. Что isdigit, что
isxdigit предназначены для символов.

Зачем проверять символы, когда нужно проверять число?

Desipere in loco
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: Проверка ввода C++

Сообщение ZyX »

Crazy писал(а):
08.10.2009 17:01
Зачем проверять символы, когда нужно проверять число?

Я про то и говорю.
Спасибо сказали:
Kondrat
Сообщения: 223
ОС: И снова Федора

Re: Проверка ввода C++

Сообщение Kondrat »

Прогнал программу в дебаггере, и заметил следующее: в участке кода

Код:

while (ent < 0 || ent > pow(16, sizeof(int)) || (!isdigit(ent))) { cout << "Ошибка: введите правильное число\nПопробуйте снова :"; cin >> ent; }


почему-то не отрабатывает функция cin, т.е бесконечно выводится сообщение, хотя кусок

Код:

if (!isdigit(ent)) { cout << "Ошибка: это не число"; return 1; }

отрабатывает на ура. Пробовал вводить разные сочетания букв и цифр, сбоев не обнаружил. Почему не срабатывает cin, понять не могу, программа его просто проскакивает.
Ёж - птица гордая: пока не пнёшь, не полетит.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Проверка ввода C++

Сообщение NickLion »

Kondrat писал(а):
09.10.2009 15:21
почему-то не отрабатывает функция cin, т.е бесконечно выводится сообщение

У Crazy ведь было:

Код: Выделить всё

std::cin.clear(std::ios::failbit);

Надо пропустить неверные данные и только потом читать
Спасибо сказали: