get () без извинений - PullRequest
       16

get () без извинений

0 голосов
/ 30 октября 2019

Я часто использую функцию gets () в своем собственном программировании. Я знаю, что:

  • входная строка может переполнять выделенное пространство

  • в некоторых средах, приведенное выше можно использовать для создания эксплойта

  • , что вместо этого можно использовать fgets () для чтения стандартного ввода

  • , что объявление заголовка было удалено (из stdio.h?)

  • , что использование get () не рекомендуется

  • , который get () устарел

Но я все равно хочу использовать это;возможно, «сохранение» копии заголовков и объектного кода до того, как она полностью исчезнет.

Мне не нравится fgets (), потому что если ввод слишком длинный, он просто возвращает то, что поместится без указания строкибыл усечен. Остальная часть (или, по крайней мере, следующая часть) строки возвращается при следующем вызове, что хорошо, если вы просто пишете программу для копирования стандартного ввода в стандартный вывод или файл (зачем кому-то писать программу? сделать это?) но бесполезно, если вы обрабатываете данные каким-либо образом.

Пожалуйста, не отвечайте на вопрос, откуда мне знать, что входная строка была усечена функцией fgets ()? Это не тот вопрос, на который я пытаюсь ответить. Правильный вопрос в том, как я могу использовать gets () без большого количества предупреждений о гибели и катастрофах?

И, пожалуйста, не читайте лекций о том, как я не хочу использовать gets ().

Я использую gcc c под Debian 9;нет IDE.

1 Ответ

5 голосов
/ 30 октября 2019

Ваше утверждение о том, что fgets just returns whatever will fit without any indication the string has been truncated явно неверно. Если символ в конце ввода не является новой строкой и вы не достигли конца файла, он усекается. На этом этапе вы можете выделить больший буфер, скопировать в него то, что у вас есть, и выполнить другие действия.

То, что вам нужно, - это функция, которая читает неограниченную строку. Это означает, что он должен будет выполнить выделение памяти, и поэтому он будет иметь подпись, отличную от gets(char *buffer), и вам потребуется освободить результат. Это означает, что как бы вы ни хотели отказаться от получения, у вас нет выбора, если вы хотите обрабатывать произвольные длинные строки.

Это соответствует функции getline делает.

Так что замените

  char buffer[128];
  char *input=gets(buffer);
  /* do something with input or buffer */

на

  char *input=NULL;
  size_t len=0;
  getline(&input, &len, stdin);
  /* do something with input */
  free(input);

Подробнее см. на странице руководства.

...