неизвестная ошибка функция 'scanf ("% [^ \ n]% * c", & отправлено);' - PullRequest
1 голос
/ 09 ноября 2019

Начнем с того, что я новичок в языке C и только что столкнулся со странным методом ввода строки в программе на C:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() {
    char ch, string[100], sent[100];
    scanf("%c", &ch);
    scanf("%s", &string);
    scanf("%[^\n]%*c", &sent);

    printf("%c\n", ch);
    printf("%s\n", string);
    printf("%s", sent);

    return 0;
}

Вот ошибка:последняя строка (предложение) не печатается, понятия не имею, где я не прав, но в ходе исследования я нашел этот код:

scanf(" %[^\n]%*c", &sent); //not theres a space before %[^\n]%*c; and then it worked (wtf)

Вы можете объяснить, почему он работает, просто добавив туда пробел.

1 Ответ

1 голос
/ 10 ноября 2019

Пробел () в строке формата заставляет scanf пропускать пробелы во входных данных. Обычно это не требуется, так как большинство преобразований scanf ТАКЖЕ пропускают пробелы, прежде чем что-либо сканировать, но не имеют значения %c и %[ - поэтому использование пробела до %[ дает видимый эффект. Давайте посмотрим, что делают ваши 3 вызова scanf:

scanf("%c",&ch);           // read the next character into 'ch'
scanf("%s",&string);       // skip whitespace, then read non-whitespac characters
                           // into 'string', stopping when the first whitespace after
                           // some non-whitespace is reached (that last whitespace
                           // will NOT be read, being left as the next character
                           // of the input.)
scanf("%[^\n]%*c",&sent);  // read non-newline characters into 'sent', up until a
                           // newline, then read and discard 1 character
                           // (that newline)

Таким образом, 3-й scanf начнет чтение с пробела, который завершил второе сканирование. Если вы добавите пробел в начало формата, он вместо этого будет читать и отбрасывать пробелы, пока не найдет непробельный символ, а затем начнет читать в sent с этим непробельным символом.

ТакжеИнтерес состоит в том, что произойдет, если пробел, заканчивающий второе сканирование, окажется новой строкой. В этом случае thrid scanf полностью потерпит неудачу (так как нет символов, не являющихся символом новой строки, которые нужно прочитать перед символом новой строки), и ничего не сделает. Добавление пробела здесь к третьему scanf гарантирует, что он не сработает из-за новой строки (он будет отброшен как пробел), поэтому он всегда будет считывать что-то в sent, если не достигнут EOF.

...