非法字符的处理 有一个小问题


#include<stdio.h>     //十进制转二进制
#define N 16
int main()
{
    short n;
    int i,ret;
    int num[N] = {0};
     do
    {
      printf("n=");
      ret = scanf("%hd",&n);
      if(ret != 1)                                              //这个如果去掉为什么会有问题呢,我感觉不判断也行呀
      while(getchar() == '\n');
    }while(n <= 0 && ret != 1);
    for(i = 0;i < N && n != 0;i ++)
    {
        num[i] = n % 2;
        n = n / 2;
    }
    printf("the binary number is ");
    for(i = N - 1;i >= 0;i --)
    {
        printf("%d",num[i]);
    }
    return 0;
}

建议去看一下scanf的说明文档:https://man7.org/linux/man-pages/man3/scanf.3.html
其中,return value里面提到:

RETURN VALUE
On success, these functions return the number of input items
successfully matched and assigned; this can be fewer than
provided for, or even zero, in the event of an early matching
failure.
The value EOF is returned if the end of input is reached before
either the first successful conversion or a matching failure
occurs. EOF is also returned if a read error occurs, in which
case the error indicator for the stream (see ferror(3)) is set,
and errno is set to indicate the error.

这里scanf返回值ret有3种情况

  1. > 0,表示成功输入了ret个参数;
  2. == 0, 表示匹配失败,比如要求数字,你输入字母;
  3. EOF(值为-1),表示在成功匹配前,或者已经匹配失败,输入就结束了;

你只考虑正常情况,中间那个if 语句当然可以不需要。
但是,当输入异常的时候,比如输入一个字母,ret = scanf("%hd",&n); 因为无法读取到整数,就返回0,并且缓冲区内容由于读取失败而没有被清除(一直留在scanf对应库缓冲区),这样就会形成无限循环。
如果加上读取失败判断:if (ret != 1),进而用getchar()读取并清除库缓冲区,也就不会形成无限循环。