Цикл C печатает строку дважды? (используя сканф(%с))

Извините за, возможно, глупый вопрос, но я хотел немного попрактиковаться в циклах и пришел к этой идее. В основном он просит вас войти или нет в цикле, а когда вы в нем, он просит вас что-то сделать. Проблема заключается в том, что сразу после того, как я вхожу в цикл, он дважды печатает строку printf, прежде чем перейти к scanf и ожидать ввода. Я не могу понять это. Любая помощь приветствуется! Вот код:

#include <stdio.h>

int main() 
{
    char check = 'a';
    char int_check = 'a';
    int b = 0;
    printf("want to go in? [y or n]\n");
    scanf("%c",&check);
    if ( check == 'y') {
        while (1){
            printf("Waiting: \n");
            scanf("%c",&int_check);
            if ( int_check == 'q'){
                printf("You're out, bye!\n");
                break;
            };
        };
    } else if ( check == 'n'){
        printf("You're not in, see ya!\n");
    }else {
        printf("Please, type 'y' or 'n'\n");
    };
    return 0;
}

person WhiteEyeTree    schedule 23.02.2012    source источник
comment
Я не уверен, что это ошибка-ошибка, но у вас не должно быть всех этих точек с запятой после фигурных скобок.   -  person Dan Fego    schedule 24.02.2012
comment
@DanFego Это глупо (по крайней мере, мне так кажется), но это не имеет значения. Это рассматривается как оператор NOP IIRC.   -  person    schedule 24.02.2012
comment
Вы нажимаете y, а затем возвращаете. Это два символа, y и \n. y считывается предварительным циклом scanf, и первый scanf в цикле находит символ новой строки, все еще находящийся в буфере.   -  person maligree    schedule 24.02.2012
comment
@pst: посмотрите строку scanf в цикле while. В пункте назначения есть пробел. Это хороший пример для обучения хорошему стилю, когда кто-то изучает язык (например, наличие пробела после запятой в списке аргументов и т. д.).   -  person Platinum Azure    schedule 24.02.2012
comment
да, это пробел - ошибка редактирования, его нет в исходной программе, извините :( РЕДАКТИРОВАТЬ: исправлено сейчас   -  person WhiteEyeTree    schedule 24.02.2012


Ответы (2)


Если вы вводите в терминал следующее:

x

Первый цикл увидит x

Второй цикл увидит символ новой строки.

Самый простой способ обойти это — использовать sscanf и getline.

person Bill Lynch    schedule 23.02.2012
comment
Спасибо Шарт! я попробую это :) ... извините, если я потратил ваше время на глупые вопросы :) - person WhiteEyeTree; 24.02.2012
comment
@WhiteEyeTree: Не беспокойтесь. Это был не глупый вопрос. Это то, с чем сталкивается почти каждый при изучении C. Однако следует помнить одну вещь: лишние точки с запятой не нужны и могут изменить смысл вашей программы. Вы должны сделать if (condition) { ... } и пропустить последнюю точку с запятой. В этом нет необходимости, и он добавляет нулевой оператор, который будет выполняться после условного оператора. - person Bill Lynch; 24.02.2012

Вы можете изменить программу так, чтобы она реагировала на клавиатуру немедленно, т. е. не дожидаясь, пока пользователь нажмет Enter. Это требует изменения свойств входного терминала и, как правило, более беспорядочно и менее портативно, чем линейно-ориентированный ввод. Эта страница описывает, как это сделать, и вот код, модифицированный для работы, который способ:

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

struct termios saved_settings;

void
reset_term_mode(void)
{
  tcsetattr (STDIN_FILENO, TCSANOW, &saved_settings);
}

int main() 
{
    tcgetattr(STDIN_FILENO, &saved_settings);
    atexit(reset_term_mode);

    struct termios term_settings;

    tcgetattr(STDIN_FILENO, &term_settings);
    term_settings.c_lflag &= ~(ICANON|ECHO);
    term_settings.c_cc[VMIN] = 1;
    term_settings.c_cc[VTIME] = 0;
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_settings);

    char check = 'a';
    char int_check = 'a';
    int b = 0;
    printf("want to go in? [y or n]\n");
    scanf("%c",&check);
    if ( check == 'y') {
        while (1){
            printf("Waiting: \n");
            scanf("%c", &int_check);
            if ( int_check == 'q'){
                printf("You're out, bye!\n");
                break;
            };
        };
    } else if ( check == 'n'){
        printf("You're not in, see ya!\n");
    }else {
        printf("Please, type 'y' or 'n'\n");
    };
    return 0;
}
person gcbenison    schedule 23.02.2012