LINUX下一个C语言的小问题

来源:百度知道 编辑:UC知道 时间:2024/05/28 06:28:36
小弟在LINUX下编写的一个很小的C程序时出现了一个很奇怪的问题,请各位大侠帮忙看下:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int main(int ac, char *av[])
{
void f2(int);
int i;

scanf("%d",&i);

switch(i)//因程序还需要做扩展,所以此处用了一个switch
{
case 1:
signal( SIGQUIT, f2 );
while(1)
{
printf("hello\n");
sleep(1);
}
break;
}
}

void f2(int signum)
{
char ans[BUFSIZ];

printf(" Interrupted! OK to quit (y/n)? ");
if ( fgets(ans, BUFSIZ, stdin) != NULL && (ans[0]=='y'||ans[0]=='Y') )
exit(0);
}

程序运行如下:
hello
hello
(注:小弟按 Ctrl + \ )
Interrupted! OK to quit (y/n)?hello (注:此处没有停下等待输入,而是继续打印hello)
hello
hello
(小弟再次按 Ctrl + \ )
Interrupted! OK to quit (y/n)? (注:此时程序停下等待输入)

出现你这种情况的原因:
scanf和fgets都使用了标准IO,标准IO是带有缓冲区的,main函数里的scanf修改了stdin的标志位,而紧接着在f2函数里使用fgets读取stdin,可能是由于scanf和fgets对stdin标志位处理方式不同,以至于fgets函数直接读取了标准IO缓冲区中现有的数据(这个缓冲区由上一个输入函数scanf填写,其缓冲区数据为31 0a 00 00 ......),而没有调用系统的read函数去中断终端,此后fgets又设置了stdin的标志位,所以在第二次interrupt时,fgets函数就能正确读取缓冲区数据。

修改的方法:
方法1:把你的f2函数改成如下即可
void f2(int signum)
{
char ans[BUFSIZ];
char* str = " Interrupted! OK to quit (y/n)? ";
write(1, str, strlen(str));
if (read(0, ans, BUFSIZ) && (ans[0]=='y'||ans[0]=='Y') )
exit(0);
}
没有使用标准IO,所以就不会有缓冲区的问题

方法2:
void f2(int signum)
{
char ans[BUFSIZ];
printf(" Interrupted! OK to quit (y/n)? ");
if ( scanf("%s", ans) != 0 && (ans[0]=='y'||ans[0]=='Y') )
exit(0);
}
同main函数里的scanf一样使用scanf函数输入数据,使对stdin的标志位设置统一