Может ли scanf идентифицировать символ формата в строке? - PullRequest
1 голос
/ 12 июля 2009

Допустим, я ожидаю список элементов из стандартного ввода, разделенных запятыми, например:

 item1, item2, item3,...,itemn

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

item1,item2,item3,...,itemn

Если я использую scanf, как это:

scanf("%s,%s,%s,%s,...,%s", s1, s2, s3, s4,...,sn);

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

Ответы [ 3 ]

8 голосов
/ 13 июля 2009

Быстрый ответ - никогда, никогда не используйте scanf для чтения ввода пользователя. Он предназначен для чтения строго отформатированных входных данных из файлов, и даже тогда не очень хорош. По крайней мере, вы должны читать целые строки, а затем анализировать их с помощью sscanf (), что дает вам шанс исправить ошибки. в лучшем случае вы должны писать свои собственные функции синтаксического анализа

Если вы на самом деле используете C ++, изучите использование строковых и потоковых классов c ++, которые гораздо более мощные и безопасные.

7 голосов
/ 12 июля 2009

Вы можете взглянуть на strtok. Сначала прочитайте строку в буфер, затем токенизируйте:

const int BUFFERSIZE = 32768;
char buffer[BUFFERSIZE];
fgets(buffer, sizeof(buffer), stdin);

const char* delimiters = " ,\n";
char* p = strtok(buffer, delimiters);
while (p != NULL)
{
  printf("%s\n", pch);
  p = strtok(NULL, delimiters);
}

Однако, с strtok вам необходимо знать о потенциальных проблемах, связанных с повторным входом .

2 голосов
/ 13 июля 2009

Полагаю, для этого лучше написать собственную функцию синтаксического анализа.Но если вы все еще предпочитаете scanf, несмотря на все его недостатки, вы можете обойти это, просто заменив% s на% [^, \ t \ r \ n].

Проблема в том, что% s соответствует последовательности небелыхпробел, поэтому он тоже глотает запятую.Поэтому, если вы замените% s на% [^, \ t \ r \ n], он будет работать почти так же (разница в том, что% s использует isspace (3) для сопоставления пробелов, но в этом случае вы явно указываете, какие пробелыmatch и этот список, вероятно, не такой, как для isspace).

Обратите внимание: если вы хотите разрешить пробелы до и после запятой, вы должны добавить пробел в строку формата.Строка формата "% [^, \ t \ r \ n],% [^, \ t \ r \ n]" соответствует строкам типа "привет, мир", "привет, мир", "привет, мир".

...