Почему две подсказки в этой программе для получения ввода показываются на одной строке? - PullRequest
0 голосов
/ 07 октября 2019

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

Я хочу, чтобы два запроса были в отдельных строках.

СледующееКод является простым примером проблемы:

#include <stdio.h>
int main(void)
{
    char name[20];
    int age = 0;
    int index;

    printf("1- Insert a new student.\n");
    printf("2- Delete a student.\n");
    printf("3- Show all students.\n");
    printf("4- Exit.\n\nChoose: ");
    scanf("%d", &index);

    printf("Enter your name: ");
    scanf("%20[^\n]s", name);
    //fgets(name, 20, stdin); // <--- Does the same thing.

    printf("Enter your age: ");
    scanf("%d", &age);

    printf("Name: %s, Age: %d\n", name, age);
    return 0;
}

Результат в виде текста:

1- Insert a new student.
2- Delete a student.
3- Show all students.
4- Exit.

Choose: 2
Enter your name: Enter your age: 

Изображение:

Почему два запроса отображаются в одной строке?

Ответы [ 3 ]

3 голосов
/ 07 октября 2019

Как говорят другие комментарии, вам лучше использовать %19[^\n]. Тем не менее, выполнение этого все еще вызовет вашу проблему. Это должно работать:

#include <stdio.h>

int main(void) {

int age = 0;
int index;
char name[20];

printf("1- Insert a new student.\n");
printf("2- Delete a student.\n");
printf("3- Show all students.\n");
printf("4- Exit.\n\nChoose: ");
scanf("%d", &index);

printf("Enter your name: ");
scanf(" %19[^\n]", name);


printf("Enter your age: ");
scanf("%d", &age);

printf("Name: %s, Age: %d\n", name, age);
  return 0;
}

Обратите внимание на начальные пробелы, добавленные в функцию scanf. Лидирующий пробел должен занимать любой завершающий символ в stdin, который мог быть оставлен предыдущим пользовательским вводом.

Program output
 clang-7 -pthread -lm -o main main.c
 ./main
1- Insert a new student.
2- Delete a student.
3- Show all students.
4- Exit.

Choose: 1
Enter your name: jimm
Enter your age: 12
Name: jimm, Age: 12

Надеюсь, это поможет!

1 голос
/ 07 октября 2019

Это код, который должен добиться цели. Пожалуйста, смотрите комментарии, содержащиеся в коде:

#include <stdio.h>

int main(void) {

  int age = 0;
  int index;
  char name[20];
  int ignore; // Not char as EOF is -1

  // Keep repeating the menu until a valid input
  do {
    printf("1- Insert a new student.\n");
    printf("2- Delete a student.\n");
    printf("3- Show all students.\n");
    printf("4- Exit.\n\nChoose: ");
  while (scanf("%d", &index) != 1 || index < 1 || index > 4); // Check for a valid index

  if (index == 1) { // Choice 1 chosen (maybe switch would be better?

    printf("Enter your name: ");
    fflush(stdout); // So it goes to the terminal
    scanf(" %19[^\n]", name);

    while (1) {
      printf("Enter your age: ");
      fflush(stdout); // So it goes to the terminal
      if (scanf(" %d", &age) == 1 && age > 0) { // I.e. valid age has been read
        break; // We are done with this loop
      }
      // Consume up to end of line
      do {
        ignore == fgetc(stdin);
        if (ignore == EOF) { // Nothing more to be read - error as no age entered
          return -1;
        }
      } while (ignore != '\n');
    }
    printf("Name: %s, Age: %d\n", name, age);
    // Do not need fflush as printf contains \n at the end
    return 0;
  }
    // ... for the other options
}
1 голос
/ 07 октября 2019

Я предлагаю вам изменить это:

scanf("%20[^\n]s", name);

на это:

scanf(" %19[^\n]", name);

по этим причинам:

  • Размер буфера выуказать scanf не включает конечный терминатор NUL (в отличие от fgets).

  • Предыдущий scanf оставил новую строку во входном буфере и форматСпецификаторы %[] и %c не фильтруют его автоматически (в отличие от %d и других спецификаторов). Добавление пробела говорит scanf отфильтровать его.

  • Финальный s не является частью формата %[], но является частой ошибкой кодеров, которые использовали %s.

Обратите также внимание, что scanf с %[] не эквивалентно fgets(), который считывает любой финальный символ новой строки и помещает его в предоставленный буфер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...