Fork me on GitHub

C语言缓冲区

调试一下c语言程序

自我感觉很久没写C语言了

getchar函数

1
2
3
4
5
6
7
   char a = getchar();
printf("a is %c\n", a);
char b = getchar();
printf("b is %c\n", b);
char c = getchar();
printf("c is %c\n", c);
return 0;

getchar函数是依次从缓冲区中取出字符来,会取走的!!

1
2
3
4
nihao
a is n
b is i
c is h

这一行

1
2
for (; scanf("%d", &nums[i]) != 0 && getchar() == ' '; ++i)
nums = (int*)realloc(nums, sizeof(int) * (i + 1)); //数组为非降序排列

这里会要求用户输入数据,用户输入的数据就是会存放在缓冲区内,然后之后scanf每次读一个数字,getchar紧随其后读一个字符,所以我们输入的时候必须是一个数字一个空格

1
while (getchar() == '\n' || getchar() == EOF || getchar() == '\0');

之后把缓冲区的字符读干净

测试一下,如果我输入12 21\n

那么scanf读完21之后,getchar函数读\n

1
2
3
4
5
6
7
00D52466  je          main+0DEh (0D524AEh)  
00D52468 mov esi,esp
00D5246A call dword ptr [__imp__getchar (0D5F220h)] ;函数返回值存放在eax中,十进制10,代表LF
00D52470 cmp esi,esp
00D52472 call __RTC_CheckEsp (0D51357h)
00D52477 cmp eax,20h
00D5247A jne main+0DEh (0D524AEh)

关键是这两条指令:

1
2
00D52472  call        __RTC_CheckEsp (0D51357h)  
00D52477 cmp eax,20h

所以之后比较cmp eax 20h就会跳出循环

之后进入那个while循环

1
2
3
4
5
6
7
while (getchar() == '\n' || getchar() == EOF || getchar() == '\0');
00D524AE mov esi,esp
00D524B0 call dword ptr [__imp__getchar (0D5F220h)]
00D524B6 cmp esi,esp
00D524B8 call __RTC_CheckEsp (0D51357h)
00D524BD cmp eax,0Ah
00D524C0 je main+119h (0D524E9h)

此时缓冲区已经是空的了,所以会要求用户继续输入数据
我此时输入了 1\n
所以调用完getchar函数之后eax存放了十六进制的49

那么第二个调用getchar读取的结果就是0Ah

1
2
3
4
5
00D524C2  mov         esi,esp  
00D524C4 call dword ptr [__imp__getchar (0D5F220h)]
00D524CA cmp esi,esp
00D524CC call __RTC_CheckEsp (0D51357h)
00D524D1 cmp eax,0FFFFFFFFh

继续。此时缓冲区已经空了

那么会要求用户继续输入
我又输入了一个换行符,很明显此时读取的结果非空,所以跳出while循环

1
2
3
4
5
6
00D524D8  call        dword ptr [__imp__getchar (0D5F220h)]  
00D524DE cmp esi,esp
00D524E0 call __RTC_CheckEsp (0D51357h)
00D524E5 test eax,eax ;检查eax是否为空
00D524E7 jne main+11Bh (0D524EBh)
00D524E9 jmp main+0DEh (0D524AEh)

eax

遇到的尴尬

如果要程序的健壮性,那么用户多输入一个空格就会出错,因为多输入一个空格程序就不知道后面那个是什么了,同时还涉及到getchar函数清空缓冲区,那个while循环的写法确实很经典,但是就没有考虑过如果缓冲区本身就是空的呢?

我修改了一下原有的代码,加入了cin.peek函数来帮助判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
while (1)
{

nums = (int*)realloc(nums, sizeof(int) * (i + 1));
scanf("%d", &nums[i]);
i++;
char ch = getchar();
if (ch == ' ')
{
if (isdigit(cin.peek()))
{
continue;
}
else
{
break;
}
}
if (ch == '\n')
{
break;
}
}
// for(;scanf("%d", &nums[i]) != 0 && getchar() == '\n'; i++)
// {
// nums = (int *)realloc(nums, sizeof(int)*(i+1));
// }
fflush(stdin);