Как предотвратить переполнение буфера, когда мы рекурсивно запрашиваем ввод, если ввод недействителен

Необходимо взять входную строку размером 5. Также необходимо проверить достоверность в каком-то несвязанном смысле. Если ввод недействителен, пользователю будет предложено ввести его еще раз.

Используя scanf("%4s", input); Но если пользовательский ввод предполагает строку из 8 символов, scanf просто сканирует последние 4 символа, все еще находящиеся в буфере, прежде чем запрашивать фактический пользовательский ввод.

Я попытался создать буферную переменную, в которой будут храниться входные данные перед передачей их целевой переменной.

🤔 А знаете ли вы, что...
C является предшественником многих современных языков, включая C++, C#, и Objective-C.


61
2

Ответы:

Просто: всегда получайте от пользователя полную строку текста (используя fgets()).

Если пользователь не предоставляет вам полную строку текста, то введенные данные недействительны; либо пожаловаться и прервать выполнение, либо отбросить ввод, пока не найдете эту новую строку и не спросите еще раз.

Это связано с простым принципом:

⟶ Пользователь всегда нажимает Enter в конце каждого запрошенного ввода ⟵

Как только будет получена полная строка текста, попытайтесь преобразовать ее в int или что-то еще.


Решено

Как предотвратить переполнение буфера, когда мы рекурсивно запрашиваем ввод, если ввод недействителен?

  1. При поиске ввода до n символов (что составляет n + 1 символов, если считать Enter или '\n'), прочитайте хотя бы строку, содержащую не менее n + 1 символов. При использовании fgets() это должно поместиться в буфер размером n + 2. Дополнительная единица предназначена для хранения добавленного нулевого символа.
#define STRING_LENGTH_MAX 5

char buf[STRING_LENGTH_MAX + 2];
for (;;) {
  if (fgets(buf, sizeof buf, stdin) == NULL) {
    // There is no more input from stdin.
    // TBD code - perhaps quit?
  }
  ...
  1. Найдите строку, сохраненную для '\n'. Если нашли, отрежьте его и продолжайте. Если он не найден и строка длинная, прочитайте оставшуюся часть строки. Отбросить все и вернуться (не рекурсивно) к шагу 1.
  buf[strcspn(buf, "\n")] == '\0'; // Lop off a potential '\n'.
  if (strlen(buf) <= STRING_LENGTH_MAX) {
    // Perform other validation tests on `buf`.
    // Otherwise ...
    break;
  }
  // Read and toss rest of line.
  int ch;
  while ((ch = getchar()) != '\n' && ch != EOF) {
    ;
  }
}
  1. Подумайте о том, чтобы поместить все это во вспомогательную функцию.