2014-03-13 4 views
1

Я написал код для проверки, что серийный номер является буквенно-цифровым в C, используя isalnum. Я написал код, предполагающий, что isalnum input is char. Все сработало. Однако, после просмотра isalnum позже, я вижу, что он хочет ввода как int. Мой код в порядке, как я должен его изменить?Является ли char и int взаимозаменяемыми для аргументов функции в C?

Если мне нужно изменить, что было бы правильно? Должен ли я просто объявить 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 

ответ

8

Вам не нужно, чтобы изменить его. Компилятор будет неявно преобразовать ваш char в int, прежде чем передать его isalnum. Такие функции, как isalnum, принимают аргументы int, поскольку такие функции, как fgetc, возвращают значения int, что позволяет использовать специальные значения, например EOF.

Обновление: Как уже упоминалось, будьте осторожны с отрицательными значениями вашего char. Ваша версия библиотеки C может быть реализована в тщательно, чтобы отрицательные значения обрабатывались без каких-либо ошибок во время выполнения. Например, glibc (реализация GNU стандартной библиотеки C), как представляется, обрабатывает отрицательные числа, добавляя 128 к аргументу int. * Однако вы не всегда сможете рассчитывать на то, что isalnum (или любая другая функция <ctype.h>) спокойно обрабатывают отрицательные числа, поэтому привычка не проверять будет очень плохой идеей.

* Технически, это не добавляет 128 к самому аргументу, а это, как представляется, используя аргумент в качестве индекса в массиве, начиная с индекса 128, таким образом, что проходит, скажем, -57 приведет доступ к индексу 71 массива. Результат тот же, хотя, с array[-57+128] и (array+128)[-57] указывают на то же местоположение.

+0

Спасибо, @MikeHolt Является ли это плохой практикой программирования или все в порядке? – user1527227

+3

Будьте осторожны с подписанными значениями без знака. Если вы используете только символы в диапазоне 0-127, тогда проблем нет. –

+2

@ user1527227 Нет, это неплохая практика программирования. Плохая практика программирования будет передавать 'int' функции, которая ожидает' char', не принимая меры предосторожности, чтобы гарантировать, что значение не будет усечено. –

2

Обычно это прекрасно, чтобы передать значение char на функцию, которая принимает int. Он будет преобразован в int с тем же значением. Это не плохая практика.

Однако, есть особая проблема с isalnum и другими функциями C для классификации символов и преобразования. Здесь, с ISO/IEC 9899: TC2 7,4/1 (курсив):

Во всех случаях аргумент является int, значение которого должно быть представимое как беззнаковое полукокса или должен равняться значению макроса EOF. Если аргумент имеет любое другое значение, поведение равно undefined.

Так что, если 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))) 

Дело в том, стоит учиться, потому что при первой встрече он кажется absurd: не передают char символьным функциям.

В качестве альтернативы, в C++ существует версия с двумя аргументами isalnum в заголовке <locale>. Эта функция (и ее друзья) принимает вход char, поэтому вам не нужно беспокоиться о отрицательных значениях. Вы будете удивлены, узнав, что второй аргумент - это локаль ;-)

 Смежные вопросы

  • Нет связанных вопросов^_^