Как читать из ввода, пока не будет найдена новая строка с помощью scanf()?

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

scanf("%2000s %2000s", a, b);

Он будет следовать первому правилу, но не второму.
Если я напишу:

I am smart

То, что я получаю, эквивалентно:
a = "Я";
b = "я";
Но должно быть:
a = "Я";
b = "я умный" ";

Я уже пробовал:

scanf("%2000s %2000[^\n]\n", a, b);

а также

scanf("%2000s %2000[^\0]\0", a, b);

В первом он ждет, пока пользователь нажмет Ctrl+D (для отправки EOF), а это не то, что мне нужно. Во втором не компилируется. Согласно компилятору:

предупреждение: нельзя закрывать ‘]’ для формата ‘%[’

Любой хороший способ решить эту проблему?


person brunoais    schedule 11.11.2011    source источник
comment
Почему бы не использовать gets(); и манипулировать оттуда возвращаемой строкой?   -  person Neigyl R. Noval    schedule 11.11.2011
comment
Похоже на домашнее задание? Возможно, вы захотите взглянуть на getc(), если задание требует, чтобы вы не читали строку, а затем анализировали ее.   -  person Brian Roach    schedule 11.11.2011
comment
@brianroach Пожалуйста, не комментируйте природу, это похоже на домашнюю работу. Это не продуктивно.   -  person Philip DiSarro    schedule 22.12.2018


Ответы (7)


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

Это означает, что завершающий '\n' пытается сопоставить не только новую строку, но и любой последующий пробел. Он не будет считаться совпавшим, пока вы не просигнализируете об окончании ввода или не введете какой-либо символ, отличный от пробела.

Один из способов справиться с этим выглядит примерно так:

scanf("%2000s %2000[^\n]%c", a, b, c);

if (c=='\n')
    // we read the whole line
else
    // the rest of the line was more than 2000 characters long. `c` contains a 
    // character from the input, and there's potentially more after that as well.

В зависимости от ситуации вы также можете проверить возвращаемое значение из scanf, которое сообщает вам количество успешных конверсий. В этом случае вы будете искать 3, чтобы указать, что все преобразования были успешными.

person Jerry Coffin    schedule 11.11.2011
comment
Это больше походит на это! Теперь я понимаю. Я не знал этой части о пустом символе из спецификации. Спасибо, это то, что мне действительно было нужно. Кроме того, спасибо за подсказку %c, она будет полезна для других целей. - person brunoais; 11.11.2011
comment
«за пределами набора сканирования» недостаточно: %c и %n также являются исключениями. - person user411313; 12.11.2011

используйте getchar и время, которое выглядит так

while(x = getchar())
{   
    if(x == '\n'||x == '\0')
       do what you need when space or return is detected
    else
        mystring.append(x)
}

Извините, если я написал псевдокод, но я не работаю с языком C какое-то время.

person darkito.net    schedule 11.11.2011
comment
Теперь я понял, что вы имеете в виду. Тем не менее... Я думаю, что это немного похоже на усложнение того, что можно сделать проще. Тем не менее, это работает. - person brunoais; 11.11.2011

Я слишком поздно, но вы можете попробовать и этот подход.

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

int main() {
    int i=0, j=0, arr[100];
    char temp;
    while(scanf("%d%c", &arr[i], &temp)){
        i++;
        if(temp=='\n'){
            break;
        }
    }
    for(j=0; j<i; j++) {
        printf("%d ", arr[j]);
    }

    return 0;
}
person sameera sy    schedule 16.09.2016

Звучит как проблема с домашним заданием. scanf() — неправильная функция для решения проблемы. Я бы рекомендовал getchar() или getch().

Примечание. Я намеренно не решаю проблему, так как это похоже на домашнее задание, а просто указываю вам правильное направление.

person bsegraves    schedule 11.11.2011
comment
Примечание. Я намеренно не решаю проблему, так как это похоже на домашнее задание, а просто указываю вам правильное направление. Да, это то, что я хочу. - person brunoais; 11.11.2011
comment
Собственно, сканф сделал именно так, как я хотел. Это была просто проблема с \n в качестве последнего символа. Он потреблял более 1 символа. - person brunoais; 11.11.2011

#include <stdio.h>
int main()
{
    char a[5],b[10];
    scanf("%2000s %2000[^\n]s",a,b);
    printf("a=%s b=%s",a,b);
}

Просто напишите s вместо \n :)

person Web King    schedule 28.04.2018
comment
Также s здесь не имеет смысла. %[^\n] уже запрашивает все символы, кроме новой строки. - person alk; 25.11.2018

// увеличьте размер массива символов, если вы хотите взять больше нет. персонажей.

#include <stdio.h>
int main()
{
    char s[10],s1[10];
    scanf("\n");//imp for below statement to work
    scanf("%[^\n]%c",s);//to take input till the you click enter
    scanf("%s",s1);//to take input till a space
    printf("%s",s);
    printf("%s",s1);
    return 0;
}
person Meghana Mendu    schedule 29.10.2020
comment
В вашем примере вы игнорируете ввод до новой строки, вы не выполняете проверки безопасности, s всегда будет \n. Пожалуйста, смотрите принятый ответ для примера ответа. - person brunoais; 30.10.2020

person    schedule
comment
Почему такое сложное решение? Зачем делать так много операций, которые не нужны? - person brunoais; 19.10.2014
comment
Да, бруноэ. Вы сделали правильное замечание! В моем коде я считываю символ за символом, что оправдывает вопрос до тех пор, пока не появятся хорошие оптимизированные способы. но для тех, кто начал кодировать. Мое решение будет хорошим примером того, как все работает. - person Bharadwaj_Turlapati; 20.10.2014
comment
@Bharadwaj_Turlapati Включение ‹conio.h› и использование getch() - не очень хорошая вещь. Может быть, кто-то не разрабатывает или не учится на Windows. - person Paul Stelian; 24.04.2018