Мы должны создать код, чтобы зашифровать шифр Цезаря. Один из шагов: вместо того, чтобы распечатать предоставленный аргумент командной строки, ваша программа вместо этого проверяет, является ли каждый символ этого аргумента командной строки десятичной цифрой (т. Е. 0
, 1
, 2
и т. Д.) И, если какой-либо из них нет, завершается после печати сообщения Usage: ./caesar key. Но если аргумент состоит исключительно из цифровых символов, вы должны преобразовать эту строку (напомним, что argv
- это массив строк, даже если эти строки выглядят как числа) в фактическое целое число и распечатать целое число, как через %i
с printf
. Код ниже - это то, что у меня есть, но он возвращает как Success, так и Error. Как я могу это исправить, чтобы программа проверяла, что каждый символ аргумента командной строки является цифрой? Код, который у меня есть
Как убедиться, что каждый символ аргумента команды является десятичной цифрой?
Ответы (3)
isdigit
применяется к int
, содержащему код символа, но выполняя isdigit(atoi(argv[1]))
, вы сначала пытаетесь преобразовать строку в целое число, поэтому это неверно. Если вы используете isdigit
, это повторяется по всей строке.
atoi
молча возвращает 0, если аргумент не является допустимым целым числом, не используйте его.
Это не потому, что строка содержит только цифры, которые можно получить с помощью int
, потому что число может быть слишком большим для int
. Если вы принимаете отрицательное число, первым символом может быть -
, который не является цифрой. Один из способов как преобразовать, так и проверить всю строку, представляющую действительное целое число, - использовать strtol
, возвращающий long
.
Из-за этого, когда argc
не равно 2, вы должны прекратить выполнение, а не продолжать, как вы это делаете.
Вот простой способ проверить, что все символы в строке находятся в заданном наборе:
#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 символ.
Вы можете сделать это эффективно:
#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
You can safely use atoi() after validating the arguments are correctly given
: нет, вы пропустили возможное переполнение
- person bruno; 29.05.2020
-
, действительным представлением целого числа
- person bruno; 29.05.2020
strlen
, а затем выполнить итерацию по строке, означает, что строка будет прочитана два раза, а для преобразования будет выполнено третье чтение, помните, вы сказали эффективный способ ^^
- person bruno; 29.05.2020
strlen
для чтения строки до 4 раз?
- person bruno; 29.05.2020