Правильная реализация *scanf(«%d»,…), особенно обработка строки со знаком, за которым следуют не числа, в соответствии с ANSI/ISO C?

#c #scanf

Вопрос:

Я пытаюсь реализовать интерпретатор esolang с нуля, в скрипте оболочки и утилитах POSIX. Оригинальный интерпретатор использует эту функцию scanf("%d",amp;i); , и я пытаюсь полностью имитировать то, что делает стандартная библиотека C.

Я подумал, каким должен быть правильный алгоритм scanf("%d",amp;i); или аналогичные ему, в соответствии со стандартами C.

В отношении функции можно предположить множество видов ввода, и я думаю, что это примеры ( ? я 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==0amp;amp;!(48<=camp;amp;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 resu<
}
 

Пояснение: Я просто хотел бы знать, каков официальный алгоритм.

Ответ №1:

scanf("%d",amp;i); сначала используется начальный пробел: isspace() , нет isblank() . Если следующий ввод не является допустимой int текстовой последовательностью. по крайней мере, 1 символ вставляется обратно stdin . Если необходимо вернуть больше символов , как в "- " , это UB или определенная реализация. Если ввод за пределами int диапазона, то UB (делайте все, что имеет смысл). Ввод после числового ввода откладывается.

Комментарии:

1. Итак, scanf("%d",amp;x) следует ли возвращать 0, неизменяемую переменную x, против ввода «- 3», например?

2. @tailsparkrabbitear Да — должно вернуться 0. Следующий символ, который нужно прочитать, — это или "-" или " " . Как правило, это так "-" (2 символа отодвинуты назад), но гарантируется только 1 возврат. x значение не обновляется при возврате 0.