проверьте, что ввод командной строки является числовым - PullRequest
0 голосов
/ 12 февраля 2019

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

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <cs50.h>

int main(int argc, string argv[])
{
    if (argc == 2)
        {
            for (int i = 0, n = strlen(argv[1]); i < n; i++)
            {
                if isdigit(argv[1][i])
                {
                    printf("Success!\n");
                }
                else
                    {
                    printf("Error. Second argument can be numbers only\n");
                    return 1;
                    }    
            }
    else
        {
            printf("Error. Second argument can be numbers only\n");
            return 1;
        }
}

Хотя приведенный выше код не выдает ошибок, он не правильно проверяетвход, и я не могу понять, почему.Может ли кто-нибудь указать мне правильное направление?

Заранее большое спасибо и всего наилучшего

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Хотя вы можете полагаться на циклическое повторение символов, проверяя, является ли каждый isdigit(), если ваша цель - использовать числовое значение, которое представляет аргумент, вы также можете использовать strtol/strtoul для преобразования значения в значение signed/unsignedи полагаться на надежные отчеты об ошибках, чтобы точно сказать, что произошло во время преобразования и какая часть аргумента, если таковая имеется, состояла из нецифровых чисел.

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

Краткий пример объясняет:

#include <stdio.h>
#include <stdlib.h>     /* for strtol */
#include <errno.h>      /* errno - for strtol validation */

int main (int argc, char **argv) {

    char *endptr;   /* end pointer for strtol */
    long l;

    if (argc < 2) { /* validate at least one argument provided */
        fprintf (stderr, "error: insufficient arguments provided.\n"
                         "usage: %s number\n", argv[0]);
        return 1;
    }

    errno = 0;                          /* zero errno before call */
    l = strtol (argv[1], &endptr, 0);   /* attempt converstion to long */

    if (endptr == argv[1]) {    /* check if digits were converted */
        fprintf (stderr, "error: no digits converted in '%s'.\n", endptr);
        return 1;
    }
    else if (errno) {           /* check for error in conversion */
        perror ("strtol-argv[1]");
        return 1;
    }

    printf ("number provided: %ld\n", l);   /* output number */

    if (*endptr)    /* endptr not pointing to `'\0'`, chars remain */
        printf ("\nadditional characters following number: '%s'.\n", endptr);

    return 0;
}

Пример использования / Вывод

$ ./bin/strtolarg 123456
number provided: 123456

$ ./bin/strtolarg -123456
number provided: -123456

$ ./bin/strtolarg "val=123456"
error: no digits converted in 'val=123456'.

$ ./bin/strtolarg "123456=val"
number provided: 123456

additional characters following number: '=val'.

Посмотрите вещи и дайте мне знать, если у вас есть вопросы.

0 голосов
/ 12 февраля 2019
if (argc != 2)

должно быть

if (argc == 2)

Делая

if isdigit(argv[1][i])
{
  printf("Success!\n");
}

вы напечатаете «Успех» 4 раза, если число состоит из 4 цифр, лучше сделать что-то вроде:

for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
   if (!isdigit(argv[1][i])
   {
     printf("Error. Second argument can be numbers only\n");
     return 1;
   }    
 }
 printf("Success!\n");
 return 0;

Пример:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(int argc, char * argv[])
{
  if (argc == 2)
  {
    int i, n;

    for (i = 0, n = strlen(argv[1]); i < n; i++)
    {
      if (!isdigit(argv[1][i]))
      {
        printf("Error. Second argument can be numbers only\n");
        return 1;
      }
    }
    printf("Success!\n");
  }
  else {
    puts("argument is missing");
    return 1;
  }

  return 0;
}

Компиляция и выполнение:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out 
argument is missing
pi@raspberrypi:/tmp $ ./a.out az
Error. Second argument can be numbers only
pi@raspberrypi:/tmp $ ./a.out 12
Success!
pi@raspberrypi:/tmp $ ./a.out 12a
Error. Second argument can be numbers only
pi@raspberrypi:/tmp $ 

Выполнение в valgrind:

pi@raspberrypi:/tmp $ valgrind ./a.out 123
==2051== Memcheck, a memory error detector
==2051== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2051== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2051== Command: ./a.out 123
==2051== 
Success!
==2051== 
==2051== HEAP SUMMARY:
==2051==     in use at exit: 0 bytes in 0 blocks
==2051==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==2051== 
==2051== All heap blocks were freed -- no leaks are possible
==2051== 
==2051== For counts of detected and suppressed errors, rerun with: -v
==2051== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
...