Выявление ошибки ввода целого числа

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

Ответить
_Gleb_
Сообщения: 467
ОС: Kubuntu 12.04 LTS

Выявление ошибки ввода целого числа

Сообщение _Gleb_ »

Скажите пожалуйста, как сделать проверку результата strtol. Нужно, чтобы не проходили слишком большие числа, дробные числа или абракадабра вроде "bhtrh/+^$". Проверку на длину я сделал: n1 == LONG_MAX, а вот как сделать проверку двух других условий -- не понял. Пробовал разные значения errno, но разобраться не смог. Помогите, пожалуйста!
P.S. Не по теме, но, может быть, кому-то не трудно ответить: как переместить курсор по экрану на 1 строку вверх?
Изображение
Спасибо сказали:
Аватара пользователя
dey
Сообщения: 335
ОС: OpenSuse 11.1

Re: Выявление ошибки ввода целого числа

Сообщение dey »

Может стоит попробовать регулярные выражения ?
В сознательных действиях должен присутствовать существенный неалгоритмический компонент.
Roger Penrose,The Emperor's New Mind
Спасибо сказали:
_Gleb_
Сообщения: 467
ОС: Kubuntu 12.04 LTS

Re: Выявление ошибки ввода целого числа

Сообщение _Gleb_ »

А это как?
Изображение
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Выявление ошибки ввода целого числа

Сообщение drBatty »

_Gleb_ писал(а):
23.12.2007 22:05
А это как?

из пушки по воробьям.
Вот так проще:

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

char *p = str;
while(*p >= '0' && *p <='9')  p++;
if(*p)
 //не число, или не целое число, в целом только цифры и ничего более
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
pryga
Сообщения: 12
ОС: Debian

Re: Выявление ошибки ввода целого числа

Сообщение pryga »

dey писал(а):
23.12.2007 22:02
Может стоит попробовать регулярные выражения ?

Не стоит. Самому довольно сложно написать, а использовать стороннюю библиотеку ради такой крошечной проверки не стоит.

drBatty писал(а):
23.12.2007 22:16
Вот так проще:

Нету проверки на переполнение, и почему знаки +- не учитываем?

_Gleb_, взгляни тут.

_Gleb_ писал(а):
23.12.2007 19:05
P.S. Не по теме, но, может быть, кому-то не трудно ответить: как переместить курсор по экрану на 1 строку вверх?

Я это только для винды помню :)
Спасибо сказали:
_Gleb_
Сообщения: 467
ОС: Kubuntu 12.04 LTS

Re: Выявление ошибки ввода целого числа

Сообщение _Gleb_ »

pryga писал(а):
23.12.2007 23:17
_Gleb_, взгляни тут.

Не нашёл, наверное, придётся небольшую логическую функцию написать.
Изображение
Спасибо сказали:
Аватара пользователя
dey
Сообщения: 335
ОС: OpenSuse 11.1

Re: Выявление ошибки ввода целого числа

Сообщение dey »

pryga писал(а):
23.12.2007 23:17
Не стоит. Самому довольно сложно написать, а использовать стороннюю библиотеку ради такой крошечной проверки не стоит.

Не так уж и сложно

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

#include <stdio.h>
#include <pcreposix.h>

int main(int argc, char** argv)
{
    char *str="1234568"; /* строка, в которой будет производится поиск */
    char *pattern="(^\\d{,7}$)"; /* шаблон, по которому будет производится поиск */
//в фигурных скобках шаблона  максимальное число  символов в строке  ,символы м.б. только цифрами
regmatch_t p[20]; /* массив, в который будут заноситься результаты поиска */
    regex_t f; /* переменная, для хранения преобразованного шаблона */
    int i,j;

    if(regcomp(&f,pattern,0)) /* если возвращаемое значение не 0 - ошибка */
    {
    printf("Ошибка в шаблоне! %i\n",i);
        exit(1);
    }
    if(regexec(&f,str,7,p,0)) /* если возвращаемое значение не 0 - значит ничего не найдено */
    {
        printf("Не найдено!\n");
        exit(1);
    }
    printf("Найдено:\n");

    return 0;
}


Код взят из примера, только шаблон изменил. Решение, которое предложил drBatty наверно самое подходящее
В сознательных действиях должен присутствовать существенный неалгоритмический компонент.
Roger Penrose,The Emperor's New Mind
Спасибо сказали:
_Gleb_
Сообщения: 467
ОС: Kubuntu 12.04 LTS

Re: Выявление ошибки ввода целого числа

Сообщение _Gleb_ »

drBatty писал(а):
23.12.2007 22:16
Вот так проще:

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

char *p = str;
while(*p >= '0' && *p <='9')  p++;
if(*p)
 //не число, или не целое число, в целом только цифры и ничего более

А что означает "if(*p)"?
Изображение
Спасибо сказали:
Аватара пользователя
pryga
Сообщения: 12
ОС: Debian

Re: Выявление ошибки ввода целого числа

Сообщение pryga »

dey писал(а):
24.12.2007 00:45
Не так уж и сложно

Так лишнюю библиотеку подключаем же все равно. Без нее вполне можно обойтись.

_Gleb_ писал(а):
23.12.2007 23:39
Не нашёл

Не нашел, потому что там на английском? Попросил бы перевести. Вот перевод:

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

#define ERANGE 34
/* ... */
   char str[] = "4233 ddsada";
   char *end;
   long int l = strtol(str, &end, 10);
   if (*end != '\' || errno == ERANGE || *str == '\')
       printf("Error!");
   else
       printf("%ld", l);


_Gleb_ писал(а):
24.12.2007 01:31
А что означает "if(*p)"?

Поэтому я и пишу *p != '\' :)
Каждая строка завершается символом с кодом 0. Во время прохода строки мы перемещали указатель.
В конце концов мы либо обнаружили недопустимый символ, либо дошли до конца строки.
В этом условии мы именно это и проверяем, если мы не дошли до конца строки, то после разыменовывания получим
не 0, условие истинно, идем в if.

ЗЫ после \ съедается 0.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Выявление ошибки ввода целого числа

Сообщение drBatty »

_Gleb_ писал(а):
24.12.2007 01:31
А что означает "if(*p)"?
К этому надо привыкнуть, многие так пишут. Значит "если *p символ", считая что последний 0 - не символ. Часто встречается if(p) читается "если p валидный указатель"

pryga писал(а):
23.12.2007 23:17
Нету проверки на переполнение, и почему знаки +- не учитываем?

проверка вроде уже сделана. Про знаки:

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

unsigned char *p = str;
но для этого есть isdigit()
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
pryga
Сообщения: 12
ОС: Debian

Re: Выявление ошибки ввода целого числа

Сообщение pryga »

_Gleb_ писал(а):
23.12.2007 19:05
Нужно, чтобы не проходили слишком большие числа


drBatty писал(а):
24.12.2007 12:52
проверка вроде уже сделана


Вот не вижу я проверки на очень большие числа. Мы определили, является ли строка числом, это да.
Но еще нужно узнать, влезает ли это число в указанный тип.

drBatty писал(а):
24.12.2007 12:52
Часто встречается if(p)

Имхо, это не есть гуд. Код становится менее читабелен. Непонятно, что это - логическая переменная, число или указатель?
Но это уже дело вкуса.
Спасибо сказали:
Аватара пользователя
Liksys
Сообщения: 2910

Re: Выявление ошибки ввода целого числа

Сообщение Liksys »

pryga :)

Код:

/******************************************************************************** * * * strnlowcpy_filter_wc() - filtruet <count> simvolov stroki <str>, * * konvertiruya v rasshirennuyu stroku i pomeshyaet v <str_wc>. * * * ********************************************************************************/ wchar_t *strnlowcpy_filter_wc(wchar_t *str_wc, const char *str, size_t count) { ////////////////////////////////////////// wchar_t *ptr_str_wc = str_wc; // Ukazatel na rasshirennuyu stroku size_t str_offset = 0; // Smeshenie ukazatelya mbstate_t mbstate; // Status sdviga ////////////////////////////////////////// memset(&mbstate, 0, sizeof(mbstate)); for (; ((str_offset = mbrtowc(ptr_str_wc, str, sizeof(wchar_t), &mbstate)) > 0) && count; ++ptr_str_wc, str += str_offset, --count) { (*ptr_str_wc) = towlower(*ptr_str_wc); if ( ptr_str_wc == str_wc ) continue; if ( ((*(ptr_str_wc -1)) == L' ') && (*(ptr_str_wc) == L' ') ) { (*(ptr_str_wc -1)) = L'\'; return str_wc; } } str_wc[0] = L'\'; return NULL; } /******************************************************************************** * * * strcmp_all_wc() - sravnenie dvuh rasshirennyh strok. * * * ********************************************************************************/ int strcmp_all_wc(const wchar_t *str1_wc, const wchar_t *str2_wc) { for (; (*str1_wc) && (*str2_wc); str1_wc++, str2_wc++) if ( (*str1_wc) != (*str2_wc) ) return 1; if ( !(*str1_wc) && !(*str2_wc) ) return 0; return 1; }
И вот из таких хаков критичные участки кода у меня только и состоят - на всю программу всего пара счетчиков, все остальные операции над указателями :) Это кусочек из моего поисковика.
Препод в универе, когда увидел вот такое в решении какой-то задачи изрек "б*я пи*дец" :)
Спасибо сказали:
Аватара пользователя
pryga
Сообщения: 12
ОС: Debian

Re: Выявление ошибки ввода целого числа

Сообщение pryga »

Liksys писал(а):
24.12.2007 14:00
на всю программу всего пара счетчиков, все остальные операции над указателями

У меня тоже такое бывало. Особенно код смотрелся, когда там **, *** :)
Но преподы код не смотрели, к счастью :) И никаких указателей "я" на тип "б" не определяли :)

Но все-таки if (p != NULL) printf("ok"); смотрится лучше, чем if (p) printf("ok"),
при этом генерируется один ассемблерный код.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Выявление ошибки ввода целого числа

Сообщение drBatty »

pryga писал(а):
24.12.2007 13:45
Вот не вижу я проверки на очень большие числа. Мы определили, является ли строка числом, это да.
Но еще нужно узнать, влезает ли это число в указанный тип.

Вот тут я не знаю. Это довольно сложно сделать переносимым способом, разве что задействовать что-то из стандартной библиотеки. Не думаю, что это нужно. Если вам необходим конкретный диапазон - пожалуйста, проверяем на цифры, если ничего другого нет, то отрезаем ведущие нули, проверяем размер, и сравниваем.

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

while(*p++ == '0');
if(strlen(--p) == 3 && strcmp(p, "342") > 0 || strlen(p) > 3)
//не число
else
//число
можно совместить с преобразованием в число.

pryga писал(а):
24.12.2007 14:42
Но все-таки if (p != NULL) printf("ok"); смотрится лучше, чем if (p) printf("ok"),
при этом генерируется один ассемблерный код.

Вы не правы. Попробуйте переписать код Liksys, будет менее понятнее. И насчёт одного кода вы так же не правы(в общем случае).
Liksys писал(а):
24.12.2007 14:00
И вот из таких хаков критичные участки кода у меня только и состоят - на всю программу всего пара счетчиков, все остальные операции над указателями :)
Не вижу здесь хаков. Только отступы побились по дороге...

pryga писал(а):
24.12.2007 13:45
Имхо, это не есть гуд. Код становится менее читабелен. Непонятно, что это - логическая переменная, число или указатель?
Какая разница? р или не р, вот в чём вопрос. Когда я вижу такой код я знаю что это, если я напишу
if(eto_moj_ukazatel_ja_ego_sravnivaju_s_NULL)
мне не станет понятнее.
А если я пишу if(f = fopen("xx","w")), то я понимаю, что это проверка, есть файл или нет. Читается "Если файл открылся, то...", а не по вашему:
"Если я открываю файл и его поток не равен NULL, то..."
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
pryga
Сообщения: 12
ОС: Debian

Re: Выявление ошибки ввода целого числа

Сообщение pryga »

drBatty писал(а):
24.12.2007 15:07
Вот тут я не знаю. Это довольно сложно сделать переносимым способом, разве что задействовать что-то из стандартной библиотеки. Не думаю, что это нужно. Если вам необходим конкретный диапазон - пожалуйста, проверяем на цифры, если ничего другого нет, то отрезаем ведущие нули, проверяем размер, и сравниваем.

А чем не нравится способ, предложенный мною выше?

drBatty писал(а):
24.12.2007 15:07
И насчёт одного кода вы так же не правы(в общем случае).

Ну это да, я же не могу это проверить во всех случаях на всех компиляторах :)

drBatty писал(а):
24.12.2007 15:07
А если я пишу if(f = fopen("xx","w")), то я понимаю, что это проверка, есть файл или нет. Читается "Если файл открылся, то...", а не по вашему:
"Если я открываю файл и его поток не равен NULL, то..."

drBatty писал(а):
24.12.2007 15:07
Вы не правы. Попробуйте переписать код Liksys, будет менее понятнее.

Все это субъективно. Так же как и то, где ставить { - на новой или на той же строке :)
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Выявление ошибки ввода целого числа

Сообщение drBatty »

pryga писал(а):
24.12.2007 15:40
drBatty писал(а):
24.12.2007 15:07

разве что задействовать что-то из стандартной библиотеки.

А чем не нравится способ, предложенный мною выше?

Вы про stltol()? Нравится.
drBatty писал(а):
24.12.2007 15:07
И насчёт одного кода вы так же не правы(в общем случае).

Ну это да, я же не могу это проверить во всех случаях на всех компиляторах :)

я не про то, я про несколько разные операторы.
if(p) преобразует p в int или в void*, а == к самому старшему типу(к примеру если есть char и long, char преобразуется в long)
Все это субъективно. Так же как и то, где ставить { - на новой или на той же строке :)

Да, я в некоторых случаях пишу if(p == NULL), если есть хоть малая вероятность, что я или компилятор поймёт не правильно. А насчёт скобок - главное выбрать стиль и затем его придерживаться. Вопрос религиозный, спорить не буду.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Ответить