Как сделать проверку на число в си
Перейти к содержимому

Как сделать проверку на число в си

  • автор:

Как сделать проверку на число в си

Здравствуйте. У меня вопрос. Как можно организовать в языке Си проверку на ввод числа т.е. если мы введем букву или иные символы вместо числа то должно выдать ошибку.
Заранее спасибо.

Snifer1994
Посмотреть профиль
Найти ещё сообщения от Snifer1994

Белик Виталий 🙂
Регистрация: 23.07.2007
Сообщений: 57,792

Переведи строку в число. Если функция перевода вернет ошибку значит нужно уведомить пользователя. Функций перевода в число множество — выбирай какая по вкусу из хелпа своего компилятора..

I’m learning to live.
Регистрация: 14.08.2012
Сообщений: 3

Не знаю по поводу перевода строки в число. А нету способа полегче?
Вот нашел на просторах интернета этот способ но не могу понять как он работает?
Сможет кто нибудь объяснить принцип его работы.

void main()
Snifer1994
Посмотреть профиль
Найти ещё сообщения от Snifer1994

Белик Виталий 🙂
Регистрация: 23.07.2007
Сообщений: 57,792

Эта функция умеет возвращать в качестве результата код ошибки, если введенное нельзя сравнить с шаблоном формата. Короче если введенное не является числом по формату %d (т.е. не целое) то выдать ошибку.
Можно и так, если scanf-ом не брезгуешь.

I’m learning to live.

Как сделать проверку на число в си

Я только начинающий программер. Потому не надо писать типа «. вот ламо. rtfm. » Я лишь прошу консультации.

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

Прошу помочь!! Буду премного благодарен!

Re: Проверка данных при вводе. Нужна помощь!

От: dotidot
Дата: 24.12.06 14:45
Оценка:

Здравствуйте, maksqwe, Вы писали:
Вот вам костыль из моей далекой молодости
Вообще — он ужасен, но работает(сделан специально под виндовый cmd)
см. коментарии.

#ifndef _1251_to_866_H #define _1251_to_866_H #include #include #include // cp1251(в ней обычно MSVC исходник сохраняет)->cp866(виндовая консолька) std::string _r(const char* str) < int i = 0; int y = 0; char z; std::string tmp; while (*(str + i) != '\0') < y = z = *(str + i); if ((y = -64)) z = 192 + y; if ((y = -16)) z = 240 + y; tmp+=z; i++; > return tmp; > struct __resurrect_cin < __resurrect_cin()<>static void resurrect() < if(!std::cin) < std::cin.clear(); std::cin.ignore(4096,'\n'); throw(std::runtime_error(_r("Ошибка ввода. Повторите.\n"))); > > >; const __resurrect_cin resurrect_cin; std::istream& operator>>(std::istream& in, const __resurrect_cin&) < __resurrect_cin::resurrect(); return in; > #endif

пример использования кривого костыля:

#include "1251_to_866.h" #include #include using namespace std; double zad51(double x,double y) < if(y<=0.0) if((-1<=x)&&(1<=x)) return exp(x+3)/(1+fabs(x)); return x*x*y; > int main() < double d1,d2; while(true) < cout<<_r("Задание 51.\n Введите значения переменных:\n"); try < cin>>d1>>d2>>resurrect_cin; cout<<_r("\nРезультат: ")"\n"; system("Pause"); return 0; > catch(runtime_error& a) < cout> return 0; >

Re: Проверка данных при вводе. Нужна помощь!

От: LaptevVV
Дата: 24.12.06 14:46
Оценка:

Здравствуйте, maksqwe, Вы писали:

M>Я только начинающий программер. Потому не надо писать типа «. вот ламо. rtfm. » Я лишь прошу консультации.

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

M>Прошу помочь!! Буду премного благодарен!
Для этого нужно написать собственную функцию посимвольного ввода с проверкой на легальность символов.

Хочешь быть счастливым — будь им!
Без булдырабыз.
Re: Проверка данных при вводе. Нужна помощь!

От: igna
Дата: 24.12.06 15:55
Оценка: 1 (1)

Здравствуйте, maksqwe, Вы писали:

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

В некоторых случаях можно так:

#include using namespace std; int main() < int i; if (cin >> i) cout "i error\n"; >

Re: Проверка данных при вводе. Нужна помощь!

От: Roman Odaisky
Дата: 24.12.06 19:54
Оценка:

Здравствуйте, maksqwe, Вы писали:

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

Лучше всего проверять не посимвольно, а положиться на стандартные языковые средства работы со строками и распознавания в них чисел. Наверное, самый «правильный» способ такой:

std::string s; . . . // как-то получили строку в s. Например, std::cin >> s. . . . int value = boost::lexical_castint>(s); // can throw boost::bad_lexical_cast . . . // если вводим из потока (stream >> s), то можно и сразу проверять - см. совет г-на Лаптева выше.

Здесь в случае «лишних» символов в строке будут вылетать исключения. Следовательно, программа унаследует все преимущества и недостатки последних. Если, как я понимаю, строки должны являться числами (а иначе вылетаем с ошибками), то исключения — то, что надо.

2 All: я понимаю, что Boost — то еще развлечение для начинающего, но надо начинать с лучшего, верно?

P. S. Это всё из предположения, что язык — C++.

До последнего не верил в пирамиду Лебедева.
Re[2]: Проверка данных при вводе. Нужна помощь!

От: Roman Odaisky
Дата: 24.12.06 19:56
Оценка:

RO>// если вводим из потока (stream >> s), то можно и сразу проверять — см. совет г-на Лаптева выше.

Автор: igna
Дата: 24.12.06
До последнего не верил в пирамиду Лебедева.
Re[2]: Проверка данных при вводе. Нужна помощь!

От: maksqwe
Дата: 24.12.06 22:46
Оценка:

I>В некоторых случаях можно так:

I>

I>#include I>using namespace std; I>int main() I> < I>int i; I> if (cin >> i) I> cout "i error\n"; I>> I>

После чего бесконечно повторяется следующая функция. Как сделать что бы этого не происходило.

Re[3]: Проверка данных при вводе. Нужна помощь!

От: LaptevVV
Дата: 25.12.06 07:03
Оценка:

Здравствуйте, maksqwe, Вы писали:

I>>В некоторых случаях можно так:

I>>

I>>#include I>>using namespace std; I>>int main() I>>< I>> int i; I>> if (cin >> i) I>> cout "i error\n"; I>>> I>>

M>После чего бесконечно повторяется следующая функция. Как сделать что бы этого не происходило.
вот так — читай сюда:

Состояния потока
Каждый поток (и стандартные в том числе) в каждый момент времени находится в некотором состоянии. Эти состояния имеют названия good, bad, fail и eof (end-of-file). Сами состояния определены в классе ios_base как целые статические константы. Эти константы называют флагами состояния потока [1-27.4.2.1.3].

typedef int iostate; goodbit = 0x00 badbit = 0x01 eofbit = 0x02 failbit = 0x04

Значения флагов зависят от реализации (показанные значения флагам присвоены в системе C++ Builder 6), однако имена определены в стандарте, поэтому именно так флаги состояния называются во всех без исключения системах. В программе имена флагов состояния нужно записывать с префиксом, например

std::ios_base::eofbit

С таким же успехом можно использовать класс, производный от ios_base. В частности, в текстах программ стандартной библиотеки часто встречается более короткий префикс

std::ios::eofbit

В базовом классе ios_base определено поле

iostate _M_iostate; // библиотека STLport

ПРИМЕЧАНИЕ
Такое имя поле имеет в системе Borland C++ Builder 6. В другой реализации имя поля может быть другим.
В этом поле сохраняются флаги состояния во время работы программы. Это поле мы можем прочитать методом

iostate rdstate();

Установить любой флаг можно методом

void setstate(iostate flag);

Для установки нескольких флагов, естественно, нужно воспользоваться битовыми операциями, например

setstate(std::ios::eofbit | std::ios::failbit);

Система ввода/вывода С++ предоставляет несколько методов, с помощью которых мы всегда можем узнать состояние потока:

bool good() const; // следующая операция может выполняться bool eof() const; // виден конец ввода bool fail() const; // следующая операция не выполняется bool bad() const; // поток испорчен

Если после выполнения некоторой операции поток находится в состоянии good, то это хорошая ситуация: во время предыдущей операции не произошло никаких непредвиденных событий и может быть выполнена следующая операции ввода/вывода. В остальных случаях следующая операция выполнена не будет.
Состояние fail и состояние bad являются состояниями ошибки потока. Если поток находится в одном из этих состояний, то операции обмена не выполняются. Состояние bad включает в себя состояние fail: когда поток находится в состоянии bad, он находится и в состоянии fail; обратное неверно.
Если поток находится в состоянии fail, то операция ввода/вывода завершилась неудачно, однако поток не испорчен и никакие символы не потеряны. Обычно это состояние устанавливается при ошибках форматирования в процессе чтения — например, программа пытается прочитать целое число, а первый же символ является недопустимым (буква или знак операции). Поток из состояния fail мы можем вернуть в нормальное состояние с помощью метода clear(), например

if (stream.fail()) stream.clear();

После этого можно выполнять операции обмена — опять до очередной ошибки. Метод clear() перегружен и позволяет не только сбросить, но и затем установить нужные флаги состояния. Прототип этого метода

void clear(iostate flag);

Состояние bad – это более тяжелое состояние. Флаг badbit указывает на неработоспособность потока данных или потерю данных. Когда поток в состоянии bad, ни в чем нельзя быть уверенным, поэтому в таких случаях лучше завершать выполнение программы.
Состояние eof может возникнуть только при операции чтения. Для стандартного потока ввода это состояние возникает при вводе комбинации клавиш + . Для файлов это состояние устанавливается при первой попытке чтения после последнего байта файла. При этом поток тоже переводится в состояние fail.
Состояние потока и логические условия
Состояние потока можно проверять непосредственно в условиях if и while. Например, ввод массива целых значений можно выполнять в цикле таким образом

int aa[10] = ; i = 0; while(cin >> aa[i++]);

Цикл завершается по одной из двух причин:
1. Создалась ситуация «end-of-file»; для входного потока это эквивалентно нажатию комбинации клавиш + ;
2. В потоке встретился символ, не соответствующий типу вводимой переменной; в этом случае поток переводится в состояние fail;
Например, мы набрали на клавиатуре следующую последовательность символов
12345e6
Тогда элементы массива а будут иметь следующие значения:

aa[0] = 1; aa[1] = 2; aa[2] = 3; aa[3] = 4; aa[4] = 5; aa[5] = 0; aa[6] = 0; aa[7] = 0; aa[8] = 0; aa[9] = 0;

Символ ‘e’после цифры 5 не является допустимым для целого числа, поэтому ограничивает ввод.
В условиях можно задавать и явный вызов методов. Например, мы хотим посчитать количество символов ‘\n’, которым оканчиваются вводимые строки. Это можно сделать, используя метод get():

int nl = 0; while(cin.get(ch)) // читать все символы, в том числе пробельные < if(ch=='\n') nl++; cout.put(ch); >

Так как «неправильных» символов не существует, цикл можно завершить только вводом комбинации + . Можно использовать и другую форму метода get():

int nl = 0; while(ch = cin.get() && ch != EOF) // читать все символы < if(ch=='\n') nl++; cout.put(ch); >

Константа EOF помещается в ch при нажатии комбинации + .
В библиотеке реализована логическая операция operator!, с помощью которой можно проверить аварийное состояние потока, например

if (!(cin >> x)) < // ввод завершился неудачей . . . >

Обратите внимание, выражение ввода заключено в скобки. Это делать необходимо, так как в соответствии с приоритетом операций выражение без скобок интерпретируется как

(!cin) >> x

Естественно, ввод и проверку состояния потока можно разделить, например

cin >> x; if(!cin) < // ввод завершился неудачей . . . >

Во всех приведенных примерах, на месте cin может стоять любой поток.
При разделении ввода и проверки можно использовать явный вызов соответствующего метода. Например, таким способом мы можем проверять наступление ситуации «end-of-file» для потока, связанного с файлом.

while (!from.eof()) // явная проверка на конец файла < getline(from, s); // чтение строки из потока from cout

Однако тут возможны сюрпризы. По умолчанию ограничителем строки является символ ‘\n’, который записан в конце каждой строки. В данном случае при считывании последней строки ситуации конца файла не возникает — она возникает только при попытке ввода за концом файла. Поэтому цикл выполнится лишний раз и на экране дважды появится последняя строка.
Правильная последовательность операторов может быть такой

getline(from, s); // чтение строки из потока from while (!from.eof()) // явная проверка на конец файла < cout // чтение строки из потока from >

Другой вариант — бесконечный цикл с проверкой «end-of-file» внутри цикла

while (true) < getline(from, s); // чтение строки из потока from if(from.eof()) break; // явная проверка на конец файла cout

Хочешь быть счастливым — будь им!
Без булдырабыз.
Re[2]: Проверка данных при вводе. Нужна помощь!

От: LaptevVV
Дата: 25.12.06 07:11
Оценка:

Здравствуйте, Roman Odaisky, Вы писали:

RO>Лучше всего проверять не посимвольно, а положиться на стандартные языковые средства работы со строками и распознавания в них чисел. Наверное, самый «правильный» способ такой:
RO>

RO>std::string s; RO>. . . RO>// как-то получили строку в s. Например, std::cin >> s. RO>. . . RO>int value = boost::lexical_castint>(s); // can throw boost::bad_lexical_cast RO>

RO>Здесь в случае «лишних» символов в строке будут вылетать исключения. Следовательно, программа унаследует все преимущества и недостатки последних. Если, как я понимаю, строки должны являться числами (а иначе вылетаем с ошибками), то исключения — то, что надо.
RO>Boost: www.boost.org
RO>2 All: я понимаю, что Boost — то еще развлечение для начинающего, но надо начинать с лучшего, верно?
Тогда уж лучше использовать стандартные строковые потоки:

Строковые потоки
В отличие от строковых потоков, реализованных в библиотеке , которые могут быть только входными или только выходными, строковые потоки объектно-ориентированной библиотеки [1-27.7] могут быть еще и двунаправленными. Кроме того, нам нет необходимости резервировать память для строки при работе с ними. И наконец, со строковыми потоками можно использовать все средства форматирования или собственные написанные манипуляторы.
Чтобы использовать строковые потоки, мы должны прописать в программе оператор
#include
После этого в программе можно объявлять объекты-строковые потоки трех видов:
 входной istringstream [1-27.7.2];
 выходной ostringstream [1-27.7.3];
 двунаправленный stringstream [1-27.7.4];
Чтобы продемонстрировать возможности строковых потоков, перепишем примеры 10.4 и 10.6. Первый пример (листинг 10.32) — аналог примера 10.4 — демонстрирует возможности выходных строковых потоков.

Листинг 10.32. Выходной строковый поток #include #include using namespace std; int main() < char s[] = "computer", c = 'L'; int i = 35; float fp = 1.7320534f; ostringstream os; /* Форматирование и вывод данных */ os "String: " << s "; " "Character: " << c "; " "Integer: " << i "; " "Real: " << fp"; " << endl; cout "Output:" '\n' << os.str() << endl; cout "character count Peter", "Mike", "Shea", "Jerry">; string temp[4]; string name; int age; long salary; stringstream strm; // двунаправленный поток srand( (unsigned)time(NULL)); // инициализация датчика случайных чисел /* создание данных name, age и salary */ for (int loop=0; loop < 4; ++loop) strm' '' '/* вывод шапки */ cout << setw(4) "#" " | " << left << setw(20) "Name" " | " << right << setw(5) "Age" " | " << right << setw(15) "Salary" << endl; cout " --------------------------------------------------\n"; strm.seekg(0); // перевод головки чтения/записи в начало потока for (loop=0; loop < 4; ++loop) < strm >> name >> age >> salary; // ввод name, age и salary cout << right << setw(4) << (loop + 1) " | " << left << setw(20) << name " | " << right << setw(5) << age " | " >

Эта программа сначала пишет в поток strm. Потом из того же потока выполняется считывание и вывод на экран.
Перед считыванием устанавливается позиция чтения методом seekg() [1-27.6.1.3]. В отличие от библиотеки в объектно-ориентированной библиотеке позиционирование можно выполнять и для строковых, и для файловых потоков. Это нельзя делать только для стандартных потоков. Набор методов, связанных с позиционированием, значительно расширен и намного удобнее, чем функции библиотеки . Мы рассмотрим методы позиционирования далее.
Входной строковый поток можно использовать, чтоб реализовать считывание чисел из поля фиксированной длины. Не будем писать манипулятор с аргументами, а напишем простой шаблон функции (листинг 10.34).

Листинг 10.34. Ввод из поля фиксированной длины template class T> void fixedread(istream &in, T &t) < if (in.width() > 0) // ширина поля установлена < string field; in >> field; // ввод по ширине или до пробела istringstream strm(field); // входной строковый поток if (!(strm >> t) // ввод их строкового потока in.setstate(ios::failbit); // ошибки ввода > else // ширина поля по умолчанию in >> t; // ввод в переменную >

Если ширина поля ввода установлена (то есть, не равна нулю), то объявляется строка для ввода и ввод выполняется в нее. Затем этой строкой инициализируется строковый поток. Обратите внимание на то, что ввод из строкового потока проверяется на корректность и в случае ошибки устанавливается флаг failbit для входного потока-параметра.
Использовать эту функцию можно так:

int k = 0; cin.width(3); fixedread(cin, k);

Если мы наберем на клавиатуре 1234, то в переменную k попадет число 123. При наборе строки «56 4567» в переменную k попадает число 56.

И кстати об исключениях:

Потоки и исключения
По умолчанию при ошибках ввода/вывода исключения не генерируются. Однако можно указать, при установке каких флагов состояния должно генерироваться исключение. В состав класса basic_ios [1-27.4.4] входит метод exceptions(), который и позволяет это сделать. Прототип метода следующий

void exceptions(iostate flags);

Задать генерацию исключения при установке флага ios::badbit можно так:

stream.exceptions(ios::badbit);

Флаги, как обычно, можно комбинировать, например

stream.exceptions(ios::badbit|ios::failbit);

Исключения будут генерироваться не только во время операций ввода/вывода, но и при установке флагов методами clear() и setstate().
Если аргумент равен 0 или ios::goodbit, исключения генерироваться не будут.
Вызов без аргумента возвращает текущие флаги, при установке которых генерируется исключение, например

ios_base::iostate flags = stream.exceptions();

Если возвращается goodbit, исключения не генерируются.
Генерируемые исключения являются объектами класса ios_base::failure [1 27.4.2.1.1], который является наследником класса exception (см. главу 4). Класс ios_base::failure имеет следующую структуру:

class ios_base::failure : public exception < public: explicit failure(const string& msg); virtual ˜failure(); virtual const char* what() const throw(); >;

Как видите, сложного ничего нет.

Хочешь быть счастливым — будь им!
Без булдырабыз.
Re: Проверка данных при вводе. Нужна помощь!

От: Megabyte
Дата: 25.12.06 15:26
Оценка: +1

On Sun, 24 Dec 2006 16:42:35 +0500, maksqwe <62114@users.rsdn.ru>wrote:

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

string s;
cin >> s;
int i;
int err = sscanf(s, «%d», &i);


Using Opera’s revolutionary e-mail client: http://www.opera.com/mail/

Posted via RSDN NNTP Server 2.0
Re: Проверка данных при вводе. Нужна помощь!

От: greenya
Дата: 25.12.06 15:40
Оценка:

Здравствуйте, maksqwe, Вы писали:

M>Я только начинающий программер. Потому не надо писать типа «. вот ламо. rtfm. » Я лишь прошу консультации.

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

M>Прошу помочь!! Буду премного благодарен!

для этого нужно просто считывать не в числовую переменную а в строковую. после — конвертировать ее в числовое значение — ошибки не будет. если человек введёт «вася», то оно просто конвертирует его безошибочно в значение 0.

более сложный вариант: — читать посимвольно и пропускать только символы от «0» до «9».

Re[2]: Проверка данных при вводе. Нужна помощь!

От: igna
Дата: 25.12.06 16:44
Оценка:

Здравствуйте, Megabyte, Вы писали:

M>sscanf(s, «%d», &i);

Или istringstream(s) >> i.

Re: Проверка данных при вводе. Нужна помощь!

От: Edge
Дата: 26.12.06 09:26
Оценка:

Здравствуйте, maksqwe, Вы писали:

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

isalpha и ей подобные

Как сделать проверку целого числа на языке Си?

— — — —
Нужно проверить число при вводе на то, чтобы оно было положительным и целым.
Вот как у меня получилась первая часть, а как проверить его целое оно или нет, я незнаю:
if((x>0&&. ))
Подскажите пожалуйста, принимается любая помощь. Заранее спасибо!

Лучший ответ
if (x > 0 && !floor(x))
<
// Код
>
Остальные ответы

При вводе обычно набирают символы. Поэтому строку надо проверить на наличие ненулевых цифр после десятичной точки.
Проверку, с переводом в бинарный формат, можно иногда обмануть, так целые десятичные числа не всегда круглые для двоичных!

Похожие вопросы
Ваш браузер устарел

Мы постоянно добавляем новый функционал в основной интерфейс проекта. К сожалению, старые браузеры не в состоянии качественно работать с современными программными продуктами. Для корректной работы используйте последние версии браузеров Chrome, Mozilla Firefox, Opera, Microsoft Edge или установите браузер Atom.

Как проверить на int?

pro100chel

Никак. Если у вас в коде вводится int , то ничего, кроме int прост не введется. То есть в таком коде «проверка на int» бессмысленна.

У вас переменная задана как int, кроме int ничего и не будет. Не вижу смысла в вопросе

SHA_bash

SHA_bash @SHA_bash Автор вопроса
Если пользователь ввёл строку или вещественное число!
Пишу же – как проверить ввод на равенство int

SHA_bash, если пользователь ввел строку, то int в принципе ничего с ней не сделает, а если будет вещ. число, то оно станет int с обрезанной частью после запятой. Если вам нужно проверить ввод на int/не int, тогда и тип вводимого значения следует поменять

SHA_bash

SHA_bash @SHA_bash Автор вопроса

Антон Муравьев, в общем, лучше напишу условие.
Мне надо было, чтобы пользователь ввёл строго целое число, а не
что-нибудь другое. Я не знаю, что произойдёт если он введёт не int,
т.к. только начал изучать «плюсы».
В общем, не хочу чтобы всё посыпалось, если на ввод попадет – строка,
так с этой переменной (в которую записывается ввод) связаны дальнейшие
арифметические операции.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *