Как реализовать ввод целых чисел в бесконечном цикле?

Задание: По двум введенным целым числам (день и месяц) вывести количество дней, оставшихся до Нового года (считать, что в феврале 28 дней), двумя способами: a) используя конструкцию switch ... case.

/* Online C Compiler and Editor */
#include <stdio.h>

int main()
{
    int d,m,td,tm;
    do{
        printf("vedite days: ");
        td=scanf("%d",&d);
        printf("vedite mesac: ");
        tm=scanf("%d",&m);
        if ((tm!=0)&&(td!=0)){
            if ((0<m<13)&&(0<d<32)){
                switch(m){
                    case 2: 
                        if (!(d<29)){
                        td=0;
                        break;
                        }
                    case 4: 
                        if (!(d<31)){
                        td=0;
                        break;
                        }
                    case 6: 
                        if (!(d<31)){
                        td=0;
                        break;
                        }
                    case 9: 
                        if (!(d<31)){
                        td=0;
                        break;
                        }
                    case 11:
                        if (!(d<31)){
                        td=0;
                        break;
                        }
                    default: break;
                        }
                }
                else{
                    td=0;
                    tm=0;
                }
            }
        }while(td==0 && tm==0);
    switch(m){
        case 1: printf("%d\n",365-d+1); break;
        case 2: printf("%d\n",334-d+1); break;
        case 3: printf("%d\n",306-d+1); break;
        case 4: printf("%d\n",275-d+1); break;
        case 5: printf("%d\n",245-d+1); break;
        case 6: printf("%d\n",214-d+1); break;
        case 7: printf("%d\n",184-d+1); break;
        case 8: printf("%d\n",153-d+1); break;
        case 9: printf("%d\n",122-d+1); break;
        case 10: printf("%d\n",92-d+1); break;
        case 11: printf("%d\n",61-d+1); break;
        case 12: printf("%d\n",31-d+1); break;
        default: printf("no"); break;
    };

    return 0;
}

Первая часть кода, это проверка на "дурака", с ней у меня и возникли сложности. Если пользователь вводит день и месяц, которого не существует, то первый цикл должен это проверить и попросить пользователя ввести еще раз ввести день/месяц. Проблемы с которыми я столкнулся: когда я ввожу символы, а не числа, то у меня бесконечно выводится printf("vedite days: "); и printf("vedite mesac: "); не давая возможности ввести день/месяц; когда я вожу не существующий день/месяц первый цикл завераештся и считает количество дней (второй switch, доходит до default и выводит "no"). Я только начал изучать С, прошу отнестить с пониманием.


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

Автор решения: Nik

1)По поводу бесконечного цикла, если упростить, то вводя символ, он никуда не девается, он со следующей итерацией пытается куда-то попасть. Например, мы ввели 'a', первый scanf() возвращает 0, символ по-прежнему никуда не пропал, поэтому он пытается записаться во втором scanf() и так же возвращает 0. С новой итерацией он никуда не пропадает и так по кругу. Вот один из вариантов решения проблемы:

`while ((td = scanf("%d",&d)) != 1){
     while (getchar() != '\n')
     {
          continue;
     }
     printf("Неправильный ввод. Попробуйте ещё раз!\n");
     printf("vedite days: ");
  }`

Суть в том, что функция getchar() ловит символы, пока не словит символ новой строки '\n' (он у нас появился при нажатии Enter, scanf() его если что пропускает, но нам нужен маркер окончания цикла).

2)В первом switch() добавьте tm = 0; в каждый case, так как условие while() не удовлетворяется или можна сделать while(td==0 || tm==0).

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

Вот, что в итоге у меня получилось:

#include<stdio.h>

int main ()
{
    int d,m,td,tm,fl;
    char c;
    do{
        fl=0;
        do{
            printf("vedite days: ");
            td=scanf("%d",&d);
            while ((c=getchar())!=EOF && c!='\n');
        }while(td!=1);
        do{
            printf("vedite mesac: ");
            tm=scanf("%d",&m);
            while ((c=getchar())!=EOF && c!='\n');
        }while(tm!=1);
            if (((0<m)&&(m<13))&&((0<d)&&(d<32))){
                fl=1;
                switch(m){
                    case 2: 
                        if (!(d<29)){
                            fl=0;
                            break;
                        }
                    case 4: 
                        if (!(d<31)){
                            fl=0;
                            break;
                        }
                    case 6: 
                        if (!(d<31)){
                            fl=0;
                            break;
                        }
                    case 9: 
                        if (!(d<31)){
                            fl=0;
                            break;
                        }
                    case 11:
                        if (!(d<31)){
                            fl=0;
                            break;
                        }
                    default: break;
                        }
                }
        }while(fl==0);
  int x[12]={31,28,31,30,31,30,31,31,30,31,30,31};
  int t=365;
  for(int i = 0; i < m-1; i++){
    t=t-x[i];
  }
  printf("До Нового Года осталось %d дней\n",t-d);
  return 0;
}
→ Ссылка