Как убедиться, что каждый символ аргумента команды является десятичной цифрой?

Мы должны создать код, чтобы зашифровать шифр Цезаря. Один из шагов: вместо того, чтобы распечатать предоставленный аргумент командной строки, ваша программа вместо этого проверяет, является ли каждый символ этого аргумента командной строки десятичной цифрой (т. Е. 0, 1, 2 и т. Д.) И, если какой-либо из них нет, завершается после печати сообщения Usage: ./caesar key. Но если аргумент состоит исключительно из цифровых символов, вы должны преобразовать эту строку (напомним, что argv - это массив строк, даже если эти строки выглядят как числа) в фактическое целое число и распечатать целое число, как через %i с printf. Код ниже - это то, что у меня есть, но он возвращает как Success, так и Error. Как я могу это исправить, чтобы программа проверяла, что каждый символ аргумента командной строки является цифрой? Код, который у меня есть


person Anu Suppiah    schedule 29.05.2020    source источник
comment
Привет, добро пожаловать в SO. Найдите минутку, чтобы прочитать как задать вопрос и как создать минимальный воспроизводимый пример   -  person skrrrt    schedule 29.05.2020
comment
Привет. В заголовке вашего вопроса написано C ++. В ваших тегах написано C. Это разные языки. Пожалуйста, выберите один.   -  person Mike Kinghan    schedule 29.05.2020
comment
Скопируйте свой код в свой вопрос, используя синтаксис Markdown для примеров кода (строка с тремя `` '' до и после кода.) Изображения (1) трудно читать на мобильных устройствах (и людям, использующим программы чтения с экрана, и т. д.), и (2) еще сложнее скопировать в ответ.   -  person rici    schedule 29.05.2020


Ответы (3)


isdigit применяется к int, содержащему код символа, но выполняя isdigit(atoi(argv[1])), вы сначала пытаетесь преобразовать строку в целое число, поэтому это неверно. Если вы используете isdigit, это повторяется по всей строке.

atoi молча возвращает 0, если аргумент не является допустимым целым числом, не используйте его.

Это не потому, что строка содержит только цифры, которые можно получить с помощью int, потому что число может быть слишком большим для int. Если вы принимаете отрицательное число, первым символом может быть -, который не является цифрой. Один из способов как преобразовать, так и проверить всю строку, представляющую действительное целое число, - использовать strtol, возвращающий long.

Из-за этого, когда argc не равно 2, вы должны прекратить выполнение, а не продолжать, как вы это делаете.

person bruno    schedule 29.05.2020

Вот простой способ проверить, что все символы в строке находятся в заданном наборе:

#include <string.h>

int main(int argc, char *argv[]) {
    if (argc > 1) {
        if (strspn(argv[1], "0123456789") == strlen(argv[1]))
            printf("OK\n");
        else
            printf("Invalid characters\n");
    }
    return 0;
}

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

person chqrlie    schedule 29.05.2020

Вы можете сделать это эффективно:

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

bool isNumber(char number[])
{
    int i = 0;

    if (strlen(number) == 0) // checks for empty string
        return false;

    if (strlen(number) == 1 && number[0] == '-') // checks for invalid str with negation sign
        return false;

    if (number[0] == '-') // verifies negation sign
        i = 1;

    for (; number[i] != 0; i++)
        if (!isdigit(number[i]))
            return false; // if not a number

    return true; // if number
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("Usage: ./caesar key\n");
        return -1;
    }

    if (isNumber(argv[1]))
        printf("%d\n", atoi(argv[1])); // ... statements
    else
        printf("Usage: ./caesar key\n");

    return 0;
}

Вы можете безопасно использовать atoi() после проверки правильности аргументов. Рассмотреть возможность:

if (isNumber(argv[1]))
    printf("Go on\n");
else
    printf("Usage: ./caesar key\n");

Пример вывода

$ ./caesar
Usage: ./caesar key
$ ./caesar s
Usage: ./caesar key
$ ./caesar 123 // --- right one
123
$ ./caesar s 3 f
Usage: ./caesar key
person Rohan Bari    schedule 29.05.2020
comment
You can safely use atoi() after validating the arguments are correctly given: нет, вы пропустили возможное переполнение - person bruno; 29.05.2020
comment
@bruno. Если аргументу дано целое число, которое выходит за границу, очевидно, что он выдаст неверный результат. - person Rohan Bari; 29.05.2020
comment
ни больше ни меньше, чем без проверки строка представляет собой целое число ^^ - person bruno; 29.05.2020
comment
обратите внимание, что вы считаете пустую строку или строку, содержащую только -, действительным представлением целого числа - person bruno; 29.05.2020
comment
вы пропустили регистр пустой строки. И чтобы вызвать strlen, а затем выполнить итерацию по строке, означает, что строка будет прочитана два раза, а для преобразования будет выполнено третье чтение, помните, вы сказали эффективный способ ^^ - person bruno; 29.05.2020
comment
@bruno теперь код работает нормально эффективным способом. - person Rohan Bari; 29.05.2020
comment
эффективно, когда вы добавили другие вызовы к strlen для чтения строки до 4 раз? - person bruno; 29.05.2020