根据 ANSI/ISO C,正确的 *scanf("%d",...) 实现,尤其是处理带有符号后跟非数字的字符串?
Correct *scanf("%d",...) implementation, especially handling a string with a sign follwed by non-numbers, according to ANSI/ISO C?
我正在尝试在 shell 脚本和 POSIX 实用程序中从头开始实现一个 esolang 解释器。原始解释器使用函数 scanf("%d",&i);
,我试图完全模仿 C 标准库的工作方式。
我认为根据 C 标准,scanf("%d",&i);
或类似算法的正确算法应该是什么。
可以针对该函数假设多种输入,我想这些是示例(我认为 i
上的 ?
代表没有变化):
input /returns/i /next getchar() returns
"-1xxx" 1 -1 'x'
"WTF" 0 ? 'W'
"-++-" 0? ?? first '+' or first '-'?
"- 3" 0? ?? first ' ' or '-'?
我不确定要参考哪些文件。
我目前正在考虑的 AWK 实现:
function get_integer( c,sign,digits){
# assumes getchar() returns a digit of character codepoint; -1 for EOF
# also assumes ungetc() can be done as many times as you want;
# example
# ungetc(3); ungetc(4); c1=getchar(); c2=getchar(); c3=getchar();
# # c1==4, c2==3, c3 shall be actually next input
for(;;){
c=getchar();
if(isblank(c)) continue;
break;
}
sign=(c==43)-(c==45);
if(sign!=0) c=getchar();
if(sign==0&&!(48<=c&&c<=57)){
if(strict_mode) abort();
if(!strict_mode){
# TBH I know against " xyz"
# Also " +42" would not come here
# BUT what about " +hello"
# also what about " + 33 "
ungetc(c);
if(sign!=0) ungetc(44-sign); # TODO: should I delete this line?
return 0;
}
}
if(sign==0) sign=1;
# and then I know I shall repeat reading numbers until non-numbers come
# then: ungetc(first non-number);
# and finally: return final result;
}
澄清:我只想知道官方算法是什么
scanf("%d",&i);
首先消耗前导空格:isspace()
,而不是 isblank()
。如果下一个输入不是有效的 int
文本序列。至少 1 个字符被放回 stdin
。如果需要放回 "-+"
中的更多字符,则由 UB 或实现定义。如果输入超出 int
范围,则 UB(做任何有意义的事情)。数字输入放回后输入
我正在尝试在 shell 脚本和 POSIX 实用程序中从头开始实现一个 esolang 解释器。原始解释器使用函数 scanf("%d",&i);
,我试图完全模仿 C 标准库的工作方式。
我认为根据 C 标准,scanf("%d",&i);
或类似算法的正确算法应该是什么。
可以针对该函数假设多种输入,我想这些是示例(我认为 i
上的 ?
代表没有变化):
input /returns/i /next getchar() returns
"-1xxx" 1 -1 'x'
"WTF" 0 ? 'W'
"-++-" 0? ?? first '+' or first '-'?
"- 3" 0? ?? first ' ' or '-'?
我不确定要参考哪些文件。
我目前正在考虑的 AWK 实现:
function get_integer( c,sign,digits){
# assumes getchar() returns a digit of character codepoint; -1 for EOF
# also assumes ungetc() can be done as many times as you want;
# example
# ungetc(3); ungetc(4); c1=getchar(); c2=getchar(); c3=getchar();
# # c1==4, c2==3, c3 shall be actually next input
for(;;){
c=getchar();
if(isblank(c)) continue;
break;
}
sign=(c==43)-(c==45);
if(sign!=0) c=getchar();
if(sign==0&&!(48<=c&&c<=57)){
if(strict_mode) abort();
if(!strict_mode){
# TBH I know against " xyz"
# Also " +42" would not come here
# BUT what about " +hello"
# also what about " + 33 "
ungetc(c);
if(sign!=0) ungetc(44-sign); # TODO: should I delete this line?
return 0;
}
}
if(sign==0) sign=1;
# and then I know I shall repeat reading numbers until non-numbers come
# then: ungetc(first non-number);
# and finally: return final result;
}
澄清:我只想知道官方算法是什么
scanf("%d",&i);
首先消耗前导空格:isspace()
,而不是 isblank()
。如果下一个输入不是有效的 int
文本序列。至少 1 个字符被放回 stdin
。如果需要放回 "-+"
中的更多字符,则由 UB 或实现定义。如果输入超出 int
范围,则 UB(做任何有意义的事情)。数字输入放回后输入