Вам не нужны два цикла for для этой задачи. Любой цикл будет работать сам по себе, и разница будет в состоянии остановки. Я собираюсь использовать цикл for
в этом примере, но аналогичная реализация, использующая цикл while
, просто проверит следующий символ, являющийся нулевым терминатором.
enum bool_t {
FALSE,
TRUE
};
int main(int argc, char *argv[])
{
if (argc == 1) {
fprintf(stderr, "No input(s).\n");
return EXIT_FAILURE;
}
while (*++argv) {
int found_invalid_character = FALSE;
for (size_t i = 0; i < strlen(*argv); ++i) {
if (!isdigit((*argv)[i])) {
found_invalid_character = TRUE;
break;
}
}
if (found_invalid_character) {
printf("%s is not a valid integer.\n", *argv);
continue;
}
int n = atoi(*argv);
printf("%d is a valid integer.\n", n);
}
return EXIT_SUCCESS;
}
Выход:
x20 is not a valid integer.
20x is not a valid integer.
20 is a valid integer.
Помните, что argv
- это массив указателей на массивы символов с нулевым символом в конце, поэтому вы всегда сможете выполнить итерацию по «строке», проверив, нажали ли вы нулевой терминатор. Вы можете переопределить функции в string.h
с нуля, если хотите, используя это практически для всего. Вот, например, функция strlen
.
size_t my_strlen(const char* s) {
size_t len = 0;
while (*s++)
++len;
return len;
}
Каждый раз, когда оценивается условие while
, указатель s
увеличивается и разыменовывается. Каждое значение *s
будет некоторым значением ASCII и, следовательно, ненулевым, пока не будет найден терминатор nul, в этот момент оператор ++len
не будет выполнен. Вот почему strlen
условно возвращает длину строки минус нулевой терминатор .
Таким образом, в основном цикл for
, который я использовал в своем примере для вашей программы, который зависел от длины строки ввода, косвенно зависел от нахождения нулевого терминатора входной строки. Вот почему вы также можете использовать цикл while
при проверке нулевого терминатора.
<ч />
Кроме того, я заметил, что вы возвращаете 1 в конце как ваших успешных, так и неудачных веток, которыми я был немного озадачен. Возвращение 1 условно означает ошибку, и фактически stdlib.h
определяет макрос EXIT_FAILURE
как 1. Я сам использую эти макросы, хотя, если вы заметите, я определил TRUE
и FALSE
, используя перечисление, что делает их лексически видимые для программы как «FALSE» и «TRUE», а также 0 и 1, которые являются их соответствующими значениями, а не просто заменяются текстом на 0 и 1 препроцессором.
Кроме того, вы не включили свои заголовки или предыдущие определения, но я предполагаю, что вы работаете в Windows, потому что false
не является допустимым значением в C без определения вручную, тогда как Visual Studio, будучи Компилятор C ++, это позволяет. Я поднимаю это, потому что меня смутила строка string s = argv[1]
. Это может означать, что вы работаете с компилятором C ++ и используете печально известный using namespace std;
, или вы напечатали def'd: typedef const char* string
. Мне не нравится ни один из вариантов лично, но каждому свой.
В любом случае, надеюсь, это поможет, удачи.