scanf扫描集%1[x+-/]与%1[x/+-]行为差异原因探究
问题
扫描集%1[x+-/]与%1[x/+-]存在行为差异:前者会接受逗号(,)和句号(.),后者则拒绝这些字符。以下是验证该差异的C语言代码及运行结果,请问为何这两个scanf扫描集的行为会有此类差异?
代码示例
#include <stdio.h> #include <stdlib.h> char scanoperator ( ) { int scanned = 1; char operator[2] = ""; char nl[2] = ""; do { if ( ! scanned) { printf ( "try again\n"); } scanned = scanf ( "%1[x+-/]", operator); if ( EOF == scanned) { fprintf ( stderr, "EOF\n"); exit ( 1); } scanf ( "%*[^\n]"); // 扫描并丢弃换行前的所有字符 scanf ( "%1[\n]", nl); // 扫描换行符 } while ( ! scanned); return operator[0]; } char scanop ( ) { int scanned = 1; char operator[2] = ""; char nl[2] = ""; do { if ( ! scanned) { printf ( "try again\n"); } scanned = scanf ( "%1[x/+-]", operator); if ( EOF == scanned) { fprintf ( stderr, "EOF\n"); exit ( 1); } scanf ( "%*[^\n]"); // 扫描并丢弃换行前的所有字符 scanf ( "%1[\n]", nl); // 扫描换行符 } while ( ! scanned); return operator[0]; } int main ( void) { char op; printf ( "Select the operator((+ - x /)\n"); op = scanoperator ( ); printf ( "operator is %c\n", op); printf ( "Select the operator((+ - x /)\n"); op = scanop ( ); printf ( "operator is %c\n", op); return 0; }
运行结果
Select the operator((+ - x /) . operator is . Select the operator((+ - x /) . try again
调用scanoperator()会接受句号(.),而调用scanop()则会正确输出"try again"。
原因分析
问题出在scanf扫描集中-符号的特殊用法上:当-夹在两个字符中间时,它表示一个ASCII码的字符范围(从左边字符到右边字符之间的所有字符);只有当-在扫描集的开头或结尾时,才会被当作普通的-字符处理。
对于扫描集
%1[x+-/]:
这里的-位于+和/之间,会被解析为「从+(ASCII码43)到/(ASCII码47)的所有字符」,这个区间包含了+(43)、,(44)、-(45)、.(46)、/(47),再加上扫描集里的x(ASCII码120),所以这个扫描集实际会匹配x、+、,、-、.、/这些字符,这就是输入.会被接受的原因。对于扫描集
%1[x/+-]:
这里的-在扫描集的最后,只作为普通字符处理,所以这个扫描集仅匹配x、/、+、-四个指定字符,输入.不在其中,自然会被拒绝,触发try again提示。
内容的提问来源于stack exchange,提问作者xing
相关产品推荐
相关产品推荐

