Программа для имитации scanf () с помощью системных вызовов - PullRequest
0 голосов
/ 22 ноября 2011

Как сказано в заголовке, я пытаюсь решить проблему прошлого года, которая требует, чтобы я написал программу, которая работает так же, как и scanf ().Ubuntu:

Вот мой код:

#include<unistd.h>
#include<stdio.h>
int main()
{
int fd=0;
char buf[20];
read(0,buf,20);
printf("%s",buf);
}

Теперь моя программа не работает точно так же.Как я могу сделать так, чтобы и целые, и символьные значения могли быть сохранены, так как мой данный код просто принимает строки символов.Кроме того, как мне сделать, чтобы мой ввод принимал любое количество данных (в данном случае только 20 символов).

1 Ответ

1 голос
/ 22 ноября 2011

Тщательно выполнять эту работу - нетривиальное упражнение.

То, что вы показываете, не очень хорошо подражает sscanf("%s", buffer);. Есть как минимум две проблемы:

  1. Вы ограничиваете ввод до 20 символов.
  2. Вы не прекращаете читать первый пробел, оставляя его и другие символы позади для чтения в следующий раз.

Обратите внимание, что системные вызовы не могут обеспечить функцию unget; это должно быть обеспечено типом FILE *. С файловыми потоками вам гарантирован один символ возврата. Недавно я провел эмпирическое исследование по пределам, обнаружив значения, в которых число сдвигаемых назад символов варьировалось от 1 (AIX, HP-UX) до 4 (Solaris) до «большого», то есть до 4 КиБ. , возможно, больше, на Linux и MacOS X (BSD). К счастью, scanf() требует только одного символа возврата. (Ну, это обычное утверждение; я не уверен, выполнимо ли это при различении между «1.23e + f» и «1.23e + 1»; для первого нужны три символа предвкушения, как мне кажется, прежде чем он сможет сказать, что e+f не является частью числа.)

Если вы пишете сменный модуль для scanf(), вам нужно будет использовать механизм <stdarg.h>. К счастью, все аргументы scanf() после строки формата являются указателями данных, а все указатели данных имеют одинаковый размер. Это упрощает некоторые аспекты кода. Однако вы будете анализировать строку формата сканирования (само по себе нетривиальное упражнение; см. Недавнее обсуждение синтаксический анализ строки формата печати ), а затем организуете соответствующие преобразования и назначения.

Если на вас не наложены необычно строгие условия, предположим, что вы будете использовать функции стандартной библиотеки ввода-вывода на уровне символов, такие как getchar(), getc() и ungetc(). Если вы даже не можете их использовать, напишите их собственные варианты. Имейте в виду, что полная интеграция с остальными функциями ввода-вывода является сложной задачей - такие вещи, как fseek(), усложняют ситуацию, и обеспечение правильного использования символов сдвига назад также не совсем тривиально.

...