Чтение ввода с запятыми (с помощью sscanf) - PullRequest
1 голос
/ 06 апреля 2020

Привет. Я пытаюсь прочитать ввод пользователя в следующей форме:

param1,param2,param3

, полученной с помощью fgets. Проблема в том, что я не могу понять, почему это не так, после первой запятой это показывает мне странное поведение. Пример:

char input[60];
char a1, a2, a3, a4;


printf("Enter info");
fgets(input, 60, stdin);
sscanf(input,"%[^,\n] %[^,\n] %[^,\n] %[^,\n]", &a1, &a2, &a3, &a4);
printf("%c %c %c %c", a1, a2,a3, a4);

Если я, например, наберу a,b,c,d, я получу: a � Что мне здесь не хватает?

Ответы [ 2 ]

1 голос
/ 06 апреля 2020

Добавление к ответу. В вашей строке формата отсутствуют фактические , запятые, поэтому 1,2,3,4 не может соответствовать.

Вы можете сделать что-то вроде этого

#include <stdio.h>

int main()
{
  char input[60];
  char a1[2], a2[2], a3[2], a4[2];


  printf("Enter info");
  fgets(input, 60, stdin);
  if (4 != sscanf(input,"%1[^,\n], %1[^,\n], %1[^,\n], %1[^,\n]", a1, a2, a3, a4))
    return printf("Error"), 1;

  printf("%c %c %c %c", a1[0], a2[0],a3[0], a4[0]);
  return 0;
}

Обратите внимание на проверку ошибок с помощью sscanf, если это было успешно, это должно возвратить число переменных, которые это заполнило данными. Если это сработало, должно быть 4.

Измените размер массива вашего параметра и число после % в строке формата sscanf в соответствии с вашими потребностями.

Редактировать: Кому заставить его выдать ошибку, если на входе слишком много параметров, вы можете сделать это

#include <stdio.h>

int main()
{
  char input[60];
  char a1[2], a2[2], a3[2], a4[2];
  char temp[2];

  printf("Enter info");
  fgets(input, 60, stdin);
  if (4 != sscanf(input,"%1[^,\n], %1[^,\n], %1[^,\n], %1[^,\n] %1[^\n]", a1, a2, a3, a4, temp))
    return printf("Error"), 1;

  printf("%c %c %c %c", a1[0], a2[0],a3[0], a4[0]);
  return 0;
}

Добавив %1[^\n] в конец формата sscanf попытается прочитать другой символ без пробела после четыре параметра. Если это удастся, это значит, что на входе слишком много параметров, например: 1,2,3,4,5. Он вернет 5, то есть количество данных, которое он смог заполнить. Но этот последний спецификатор формата не должен совпадать ни с чем, если ввод действителен, поэтому sscanf должен возвращать ровно 4 в случае допустимого ввода.

0 голосов
/ 06 апреля 2020

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

Он должен иметь соответствующий аргумент типа char[], способный содержать хотя бы символ плюс нулевой символ, но относительный аргумент каждого %[ имеет только тип char в вашем примере.

Это вызывает неопределенное поведение, так как добавляемый \0 написан за пределами массив.

Если вы хотите прочитать и напечатать разделенное запятыми слово, вы можете использовать:

#include <stdio.h>

int main()
{
  char input[60];
  char a1[15], a2[15], a3[15], a4[15];

  for(int i; i < 10; i++)
  {
      a1[i] = a2[i] = a3[i] = a4[i] = 0;  // Initialize each character with `\0`.
  }

  printf("Enter info\n");
  fgets(input, 60, stdin);
  sscanf(input,"%[^,\n],%[^,\n],%[^,\n],%[^\n]", a1, a2, a3, a4);


  printf("%s %s %s %s", a1, a2, a3, a4);
  return 0;
}

Выполнение:

/a.out
hello,mister,tamborine,man
hello mister tamborine man
...