我有一个简单的问题。我正在学习链表,我的数据类型是int
。我想知道如何在不允许接受字母输入的情况下验证它。
当我按照我现有的方式进行操作时,它不会打印消息。那么,我该如何正确地做这样的事情呢?
我的代码:
node * createLinkedList()
{
node * head = NULL;
node * temp = NULL;
node * p = NULL;
while ((scanf("%d", &(temp->data))) !=EOF )
{
if ((temp->data>= 'a' && temp->data<= 'z') || (temp->data>= 'A' && temp->data<= 'Z')){
fprintf(stderr,"ERROR alph is not allowed");
}
}
}
%d
scanf
说明符用于读取int
,如果输入了字母字符,scanf
将无法读取,temp->data
将保留其以前的值。
你的周期的一个更好的条件是:
while (scanf("%d", &(temp->data)) == 0) //while input is not correctly parsed...
{
fprintf(stderr, "ERROR alph is not allowedn"); //...print error message...
int c;
while((c = getchar()) != 'n' && c != EOF) {} //...and clear stdin
}
这使得如果输入不能被解析为int
,则将要求新的输入,直到输入好的值。
请注意,正如@JohnNode所指出的,以数字开头但包含字母字符的输入将被解析,直到找到字符为止,即123abc4
将解析123
。如果您想避免这种情况,使用fgets
和strtoll
的组合是一种更稳健的方法,它将允许您验证如上所述的输入。
如果这是你想允许发生的事情,并继续使用scanf
,不要忘记,在请求新的输入之前,你需要清除stdin
,它将包含未解析的字符(在示例中为abc4n
(,@JohnNode的答案完美地涵盖了这些问题,请查看。
您显示的代码中还有另一个问题,您的temp
指针是NULL
,它无法存储任何数据。要么将其声明为对象,要么为其分配内存。实际上,这会导致未定义的行为。
如果需要验证整数输入,则不能仅依赖%d
。它不会捕获和拒绝像"12w45"
这样的坏条目——它会成功地转换和分配"12"
,但会将"w45"
留在输入流中,以破坏下一次读取。
有两种方法可以解决这个问题。一种是在输入后立即扫描和检查字符,就像这样:
int tmp;
char dummy = 0;
int r;
if ( (r = scanf( "%d%c", &tmp, &dummy )) == 2 )
{
// if following character is whitespace, then this is a valid numeric input
if ( isspace( dummy ) )
temp->data = tmp;
else
{
fprintf( stderr, "non-numeric character '%c' (%d) detected in inputn",
isprint( dummy ) ? dummy : '.', dummy );
fprintf( stderr, "clearing out input streamn" );
while ( getchar() != 'n' )
; // empty loop
}
}
else if ( r == 1 ) // only thing following numeric input was EOF
{
temp->data = tmp;
}
else if ( r == 0 )
{
fprintf( stderr, "Non-numeric input detected, clearing input streamn" );
while ( getchar() != 'n' )
; // empty loop
}
else
{
fprintf( stderr, "EOF or error detected on inputn" );
}
在我看来,更好的方法是避免完全使用scanf
——使用fgets
将输入读取为字符串,然后使用strtol
或strtod
执行转换:
char buffer[13]; // 11 decimal digits plus sign plus string terminator;
// should be able to store the decimal string representation
// of any 32-bit integer;
if ( fgets( buffer, sizeof buffer, stdin ) )
{
// chk will point to the first character *not* converted by strtol
char *chk;
int tmp = (int) strtol( buffer, &chk, 10 );
if ( !isspace( *chk ) && *chk != 0 )
{
fprintf( stderr, "Detected non-numeric character '%c' (%d) in inputn",
isprint( *chk ) ? *chk : '.', *chk );
}
else
{
temp->data = tmp;
}
}
else
{
fprintf( stderr, "EOF or error on inputn" );
}
当你进行这种验证时,使用一个临时的来存储转换后的值,直到你完成;在你知道价值是好的之前,不要更新你的实际目标。