【问题标题】:Correct *scanf("%d",...) implementation, especially handling a string with a sign follwed by non-numbers, according to ANSI/ISO C?正确的 *scanf("%d",...) 实现,特别是根据 ANSI/ISO C 处理带有非数字符号的字符串?
【发布时间】:2021-07-03 02:00:45
【问题描述】:

我正在尝试在 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;
}

澄清:我只想知道官方的算法是什么。

【问题讨论】:

    标签: c scanf


    【解决方案1】:

    scanf("%d",&amp;i); 首先使用前导空格:isspace(),而不是 isblank()。如果下一个输入不是有效的int 文本序列。至少 1 个字符被放回 stdin。如果像"-+" 中需要放回更多字符,则它是UB 或实现定义的。如果输入超出int 范围,则 UB(做任何有意义的事情)。数字输入后的输入被放回。

    【讨论】:

    • 那么,例如,scanf("%d",&amp;x) 是否应该针对输入“- 3”返回 0,不变的变量 x?
    • @tailsparkrabbitear 是 - 应该返回 0。要读取的下一个字符是 "-"" "。通常是"-"(后推2 个字符),但只能保证1 个后推。 x 值在返回 0 时不会更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    相关资源
    最近更新 更多