C++ - scanf () и printf () выполняются не по порядку

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

Однако printf() и scanf() ведут себя странно и не в порядке.

Вот отрывок из кода:

int main(int argc, char * argv[]) {
    char op;
    int pan;
    MyList list;
    do {
        printf("a = add\nd = delete\ns = sort\nu = unsort\np = print\nq = quit\n");
        scanf("%c",&op);
        switch (op) {
            case 'a':
                printf("Enter value: ");
                scanf("%i\n", &pan);
                list.push(pan);
                printf("%i pushed\n", pan);
                break;
            case 'd':
                printf("Enter value: ");
                scanf("%i\n", &pan);
                printf("%i removed\n", pan);
                list.remove(pan);
                break;
            case 's':
                list.setSortedList(true);
                break;
            case 'u':
                list.setSortedList(false);
                break;
            case 'p':
                list.print();
                break;
            case 'q':
                return 0;
                break;
            default:
                printf("I have no idea what you want me to do.\n");
        }
    } while (true);
    return 0;
}

Проблема в том, что в некоторых моментах программа, кажется, выполняет scanf() раньше, чем printf(), даже если они написаны в другом порядке!

Вот результат выполнения файла. Для удобства строки с моим собственным вводом были добавлены с помощью <<.

a = add
d = delete
s = sort
u = unsort
p = print
q = quit
a    << chose "add"
Enter value: 16    << input value
    << pressing return to see if anything changes
    << pressing it again, just in case
6    << maybe you didn't hear me, program?
16 pushed
a = add
d = delete
s = sort
u = unsort
p = print
q = quit
I have no idea what you want me to do.
a = add
d = delete
s = sort
u = unsort
p = print
q = quit
I have no idea what you want me to do.
a = add
d = delete
s = sort
u = unsort
p = print
q = quit

Что мне делать, чтобы исправить этот неправильный порядок выполнения?

scanf("%i\n", &pan); почему \n?
macroland 10.09.2018 07:53

Желательно прекратить использование scanf.

melpomene 10.09.2018 07:53
scanf и printf - это функции, которые происходят из языка C, и вы не должны использовать их в программах на C++. В C++ у вас есть классы std::istream и std::ostream с объектами cin и cout для таких целей.
Avert 10.09.2018 07:58

Обратите внимание, что использование cin >> примерно так же плохо, как и scanf, так что не делайте этого тоже.

melpomene 10.09.2018 08:03

удалите \n из строки формата scanf

M.M 10.09.2018 08:30

@melpomene cin >> намного лучше, если кто-то знает управление потоком этого класса. Проблема в том, что ни в одном руководстве по C++ я никогда не видел обзоров этой части функциональности. Потоковый ввод / вывод необходим на некоторых платформах. Самым большим преимуществом iostream является безопасность типов и переносимость (строки формата scanf \ printf не переносимы).

Swift - Friday Pie 10.09.2018 10:19

@ Swift-FridayPie Ты не имеешь особого смысла. Самым большим преимуществом iostream является std::getline, который вы должны использовать для пользовательского ввода. Я понятия не имею, что вы имеете в виду под управлением потоком или переносимостью. Безопасность типов тоже не проблема.

melpomene 10.09.2018 10:21

@melpomene - это не только пользовательский ввод. Извините, но cin::getline уступает getline в стиле C, и вам все равно нужно анализировать ввод и работать со строками C. У iostreams есть состояния потоков, которые вы контролируете, и способ буферизации ввода, это гарантирует, что никакие данные не будут потеряны до того, как программа их обработает, при обнаружении ошибки синтаксического анализа остальные данные сохраняются в буфере и поднимается флаг ошибки. iostreams также используются для автоматического ввода \ конвейера.

Swift - Friday Pie 10.09.2018 10:25

@ Swift-FridayPie Я никогда не упоминал cin::getline (также, что вы имеете в виду под "getline в стиле C"?). Я даже не понимаю, о чем вы сейчас спорите. Как вы думаете, у объектов FILE нет буфера или состояния?

melpomene 10.09.2018 10:30

Извините, std::getline. В стиле C (или POSIX) man7.org/linux/man-pages/man3/getline.3.html Следует различать файловый буфер ОС и входной буфер программы. Если вам нужна функциональность cin, вам придется реализовать последнее самостоятельно. Определение объектов FILE зависит от платформы, также потоки C++ не обязательно должны реализовываться через них. Конечно, ввод-вывод Steam и ввод-вывод файлов также имеют собственный контроль, это намного сложнее, разные платформы могут иметь для этого разные API ... или некоторые незначительные отличия.

Swift - Friday Pie 10.09.2018 10:41

зачем вам использовать scanf и printf в программе на C++? Либо отметьте вопрос как C, либо используйте cin и cout, которые являются лучшим выбором.

Harshith Rai 17.09.2018 10:32
0
11
117
2

Ответы 2

возможно, вы можете добавить две строки в свой scanf позади, scanf ("% * [^ \ n]"); scanf ("% * c");

должен переключиться позади

Wjiyao 10.09.2018 09:54

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

Проблема заключается в новой строке в конце строки формата scanf.

scanf("%i\n", &pan);

Пробельный символ в строке формата приводит к тому, что все пробелы используются. Таким образом, scanf не завершится, пока вы не введете следующий непробельный символ, который в вашем случае будет следующим выбором меню. вот почему ваш ввод и вывод выходит из строя.

Попробуйте вместо этого

    scanf(" %c",&op); // space before

а также

    scanf("%i", &pan); // no spaces or newlines

Помещая пробел до в %c, вы пропускаете все незавершенные пробелы, прежде чем пытаться прочитать символ выбора меню, что вам и нужно.

Другие вопросы по теме