Я написал некоторый код, чтобы убедиться, что серийный номер является буквенно-цифровым в C, используя isalnum
, Я написал код в предположении isalnum
вход char
, Все работало Тем не менее, после рассмотрения isalnum
позже я вижу, что он хочет, чтобы вклад как int
, Мой код в порядке, как я должен изменить его?
Если мне нужно измениться, что будет правильным способом? Должен ли я просто объявить int и установить его на char и передать его isalnum
? Это считается плохой практикой программирования?
Заранее спасибо.
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>bool VerifySerialNumber( char *serialNumber ) {
int num;
char* charPtr = serialNumber;if( strlen( serialNumber ) < 10 ) {
printf("The entered serial number seems incorrect.");
printf("It's less than 10 characters.\n");
return false;
}
while( *charPtr != '\0' ) {
if( !isalnum(*charPtr) ) {
return false;
}
*charPtr++;
}
return true;
}int main() {
char* str1 = "abcdABCD1234";
char* str2 = "abcdef##";
char* str3 = "abcdABCD1234$#";
bool result;
result = VerifySerialNumber( str1 );
printf("str= %s, result=%d\n\n", str1, result);
result = VerifySerialNumber( str2 );
printf("str= %s, result=%d\n\n", str2, result);
result = VerifySerialNumber( str3 );
printf("str= %s, result=%d\n\n", str3, result);
return 0;
}
Выход:
str= abcdABCD1234, result=1
The entered serial number seems incorrect.It's less than 10 characters.
str= abcdef##, result=0
str= abcdABCD1234$#, result=0
Вам не нужно менять это. Компилятор неявно преобразует ваш char
для int
прежде чем передать его isalnum
, Функции как isalnum
принимать int
аргументы, потому что функции, такие как fgetc
вернуть int
значения, которые учитывают специальные значения, такие как EOF
существовать.
Обновить: Как уже упоминали другие, будьте осторожны с отрицательными ценностями вашего char
, Ваша версия библиотеки C может быть быть реализованным аккуратно, чтобы отрицательные значения обрабатывались без каких-либо ошибок во время выполнения. Например, glibc
(реализация стандартной библиотеки C для GNU), по-видимому, обрабатывает отрицательные числа, добавляя 128 к int
аргумент.* Однако вы не всегда сможете рассчитывать на isalnum
(или любой другой <ctype.h>
функции) спокойно обрабатывать отрицательные числа, поэтому привыкание не проверять было бы очень плохой идеей.
* Технически, это не добавление 128 к самому аргументу, а скорее использование аргумента в качестве индекса в массиве, начиная с индекса 128, так что передача, скажем, -57
приведет к доступу к индексу 71
массива. Результат такой же, так как array[-57+128]
а также (array+128)[-57]
указать на то же место.
Обычно хорошо пройти char
значение функции, которая принимает int
, Он будет преобразован в int
с тем же значением. Это не плохая практика.
тем не мение, есть конкретная проблема с isalnum
и другие функции C для классификации символов и преобразования. Вот это из ISO / IEC 9899: TC2 7.4 / 1 (выделено мной):
Во всех случаях аргумент является
int
, значение которого должно быть
представляемый как неподписанный символ или должен быть равен значению
макросEOF
, Если аргумент имеет любое другое значение, поведение
не определено.
Так что если char
является типом со знаком (это зависит от реализации), и если вы столкнулись с char
с отрицательным значением, то он будет преобразован в int
с отрицательным значением перед передачей в функцию. Отрицательные числа не могут быть представлены как unsigned char
, Числа представимые в виде unsigned char
являются 0
в UCHAR_MAX
, Таким образом, у вас есть неопределенное поведение, если вы передаете любое отрицательное значение, кроме EOF
бывает.
По этой причине вы должны написать свой код в C:
if( !isalnum((unsigned char)*charPtr) )
или в C ++ вы можете предпочесть:
if( !isalnum(static_cast<unsigned char>(*charPtr)) )
Этот пункт стоит изучить, потому что при первом знакомстве это кажется абсурдным: не проходите char
к функциям персонажа.
Кроме того, в C ++ есть версия с двумя аргументами isalnum
в шапке <locale>
, Эта функция (и ее друзья) char
в качестве входа, так что вам не нужно беспокоиться об отрицательных значениях. Вы будете удивлены, узнав, что второй аргумент — это локаль 😉