Проблемы с функцией scanf и циклом while

Код:

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


void get_num ( int *pi )
{
    printf("Введите число: ");
    scanf("%d\n", pi);
}


int main ( void )
{
    int i = 1;
    
    while ( i != 0 )
    {
        get_num(&i);
        printf("Ваше число: %d\n", i);
    }

    return EXIT_SUCCESS;
}

Вывод:

user@user:~$ ./a.out 
Введите число: 1 
2
Ваше число: 1
Введите число: 3
Ваше число: 2
Введите число: 4
Ваше число: 3
Введите число: a
Введите число: Ваше число: 4
Введите число: Ваше число: 4
Введите число: Ваше число: 4
Введите число: Ваше число: 4
Введите число: Ваше число: 4
Введите число: Ваше число: 4
...

После ввода числа предполагался его вывод, но выводится число, введенное в прошлый раз, а при вводе букв возникает бесконечный вывод. Почему такое происходит?


Ответы (3 шт):

Автор решения: Miracle-

Не так хорош в C, но, мне кажется основная причина, почему у вас выводится предыдущее число - это escape символ или new line кому как удобней: \n.

Почему бесконечный цикл?, ответ, как мне кажется это потому что, когда вы вводите нецифровой символ то оператор ввода scanf %d не может спарсить веденный символ как целое число и он оставляет его в буфере.Так что при следующей итерацией цикла while,он считывает точно такой же символ еще раз, повторно.

→ Ссылка
Автор решения: nomnoms12

Потому что вы передали scanf строку формата с пробельным символом:

scanf("%d\n", pi);
//       ^^

Любой отдельный символ пробела в строке формата потребляет все доступные последовательные символы пробела из входных данных (определяется как если бы вызывался isspace в цикле). Обратите внимание, что нет никакой разницы между "\n", " ", "\t\t" или другими пробелами в строке формата.

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

То есть первый вызов scanf будет ожидать число, последовательность пробелов, а потом любой символ (этот символ останется непрочитанным).

Второй вызов будет ожидать то же самое, но в качестве ввода ему будет передан непрочитанный символ с первой итерации. И если он не может быть преобразован в число, произойдёт сбой сопоставления.

В случае сбоя символ так и останется непрочитанным, и на следующей итерации произойдёт то же самое. Поэтому ввод буквы приводит к зацикливанию

→ Ссылка
Автор решения: Andrei

Наверное Вы бы хотели получить вот такое поведение вашей программы:

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


int get_num ( int *pi )
{
    printf("Введите число: ");
    return scanf("%d", pi);
}


int main ( void )
{
    int i = 1, c = 0;

    do
    {
        if ( get_num(&i) != 0)
            printf("Ваше число: %d\n", i);
    
        while ((c = getchar() != '\n') && c != EOF){}
    } while ( i != 0 );

    return EXIT_SUCCESS;
}
→ Ссылка