我使用isalnum
编写了一些代码来验证C中的序列号是字母数字。假设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
答案 0 :(得分:10)
您无需更改它。在将char
传递给int
之前,编译器会隐式将isalnum
转换为isalnum
。 int
之类的函数会使用fgetc
个参数,因为像int
这样的函数会返回EOF
个值,这样就可以存在char
之类的特殊值。
更新:正如其他人所提到的,请注意glibc
的负值。您的C库版本可能可以小心实施,以便处理负值而不会导致任何运行时错误。例如,int
(标准C库的GNU实现)似乎通过向isalnum
参数添加128来处理负数。 * 但是,您并不总是能够依靠<ctype.h>
(或任何其他-57
函数)悄悄地处理负数,所以养成不检查的习惯是一个非常糟糕的主意。
* 从技术上讲,它不会在参数本身中添加128,而是它似乎使用参数作为数组的索引,从索引128开始,这样传入,比方说, 71
将导致访问数组的索引array[-57+128]
。但结果是相同的,因为(array+128)[-57]
和{{1}}指向同一位置。
答案 1 :(得分:2)
通常可以将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
作为输入,因此您不必担心负值。你会惊讶地发现第二个参数是一个语言环境; - )