質問

I wrote some code to verify a serial number is alpha numeric in C using isalnum. I wrote the code assuming isalnum input is char. Everything worked. However, after reviewing the isalnum later, I see that it wants input as int. Is my code okay the way it is should I change it?

If I do need to change, what would be the proper way? Should I just declare an int and set it to the char and pass that to isalnum? Is this considered bad programming practice?

Thanks in advance.

#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;
}

Output:

str= abcdABCD1234, result=1

The entered serial number seems incorrect.It's less than 10 characters.
str= abcdef##, result=0

str= abcdABCD1234$#, result=0
役に立ちましたか?

解決

You don't need to change it. The compiler will implicitly convert your char to an int before passing it to isalnum. Functions like isalnum take int arguments because functions like fgetc return int values, which allows for special values like EOF to exist.

Update: As others have mentioned, be careful with negative values of your char. Your version of the C library might be implemented carefully so that negative values are handled without causing any run-time errors. For example, glibc (the GNU implementation of the standard C library) appears to handle negative numbers by adding 128 to the int argument.* However, you won't always be able to count on having isalnum (or any of the other <ctype.h> functions) quietly handle negative numbers, so getting in the habit of not checking would be a very bad idea.

* Technically, it's not adding 128 to the argument itself, but rather it appears to be using the argument as an index into an array, starting at index 128, such that passing in, say, -57 would result in an access to index 71 of the array. The result is the same, though, since array[-57+128] and (array+128)[-57] point to the same location.

他のヒント

Usually it is fine to pass a char value to a function that takes an int. It will be converted to the int with the same value. This isn't a bad practice.

However, there is a specific problem with isalnum and the other C functions for character classification and conversion. Here it is, from the ISO/IEC 9899:TC2 7.4/1 (emphasis mine):

In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

So, if char is a signed type (this is implementation-dependent), and if you encounter a char with negative value, then it will be converted to an int with negative value before passing it to the function. Negative numbers are not representable as unsigned char. The numbers representable as unsigned char are 0 to UCHAR_MAX. So you have undefined behavior if you pass in any negative value other than whatever EOF happens to be.

For this reason, you should write your code like this in C:

if( !isalnum((unsigned char)*charPtr) )

or in C++ you might prefer:

if( !isalnum(static_cast<unsigned char>(*charPtr)) )

The point is worth learning because at first encounter it seems absurd: do not pass a char to the character functions.

Alternatively, in C++ there is a two-argument version of isalnum in the header <locale>. This function (and its friends) do take a char as input, so you don't have to worry about negative values. You will be astonished to learn that the second argument is a locale ;-)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top