2010-02-20 115 views
2

在此代码中,scanf只能使用一次。我究竟做错了什么?scanf in while循环

#include <stdio.h> 
#include <unistd.h> 

int main() 
{ 
    int i = 1; 
    if (! fork()) 
    { 
     while(i) 
     { 
      printf("Enter i"); 
      scanf("%d", &i); 
      fflush(stdin); 
      fflush(stdout); 
     } 
    } 
    else 
    { 
     printf("Parent\n"); 
    } 
    return(0); 
} 
+1

scanf()是邪恶的。不要使用它。 – 2010-02-20 19:40:55

+1

为什么你在这里使用'fork()'?它不会直接影响逻辑,但是......您的子进程正在读取标准输入,而您的父进程正在打印并退出(无需等待子进程)。这个孩子是孤儿。你确定它不只是坐在后台,与shell讨论谁将阅读下一行数据(并丢失)? – 2010-02-20 21:44:09

+0

减去'fork()',代码显示有趣的行为。出现提示(在输入数据之前没有空格)。它循环;重复几次。读取值未显示。键入EOF并且程序进入无限循环。不好。总是检查从scanf()返回! – 2010-02-20 21:46:54

回答

1

尝试检查i> 0。

0

首先,我试图提取出问题的最简单代码(很长一段时间没有使用C/scanf)。没有fork的代码工作正常。有点谷歌搜索“fork scanf”gave me the answer

在fork之后,输入流被关闭。所以scanf进入了一个糟糕的状态。以下程序是对你的稍作修改。它打印“流关闭”。

#include<stdio.h> 
#include<unistd.h> 
int main() 
{ 
     int i = 1; 
     if(!fork()) 
     { 
       while(i) 
       { 
         printf("Enter i"); 
         int j = scanf("%d",&i); // changed 
         if(j == EOF) {    // added 
           printf("stream closed"); // added 
           return 1;  // added 
         }      // added 
         fflush(stdin); 
         fflush(stdout); 
       } 
     } 
     else 
     { 
       printf("Parent\n"); 
     } 
     return(0); 
} 
+2

当你'fork()'时,这两个过程几乎完全相同 - 特别是,它们打开了相同的文件。孩子的标准输入未关闭。 – 2010-02-20 21:51:40

1

没有看到您提供的输入有点难以说出。如果它没有fork,那么它可能是阿米特描述的冲突。另外两件事:

  1. 请勿使用scanf

  2. fflush(stdin)未定义的行为。不要这样做。

从comp.lang.c常见问题:

+0

+1链接到comp.lang.c FAQ – jschmier 2010-02-21 07:29:40

3

它已建议您not use scanf。如果您觉得必须使用scanf,则应该检查返回值以确定在转换之前是否发生了输入错误。

它也被指出,你不应该冲洗stdin通过fflush,因为它调用未定义的行为。如果您认为您必须冲洗stdin,则可能需要参考this question的回答。

如果输入了一个无效值,如“1234”被scanf将接受“1”“ 234/N”将左输入流英寸由于fflush(stdin)无法保证正常工作,因此后续拨打scanf将会一再拒绝同一个',',永远不会有任何进展。如果检查返回值为零(表明提前匹配失败),则可以避免无限循环。在另一次拨打scanf之前,还需要从输入流中删除无效字符。


scanf() causing infinite loop为好。

1

父进程返回后,它将控制权交还给shell,该shell可以自由关闭它的stdin。即使stdin保持有效并处于活动状态,用户也会收到令人困惑的shell提示。

要保留孩子对stdin/out的访问权限,您需要停止父母的终止操作,直到孩子完成为止。使用wait或相关功能。

#include <sys/wait.h> 

...

else { 
    printf("parent\n"); 
    wait(NULL); 
} 

这修正了我的机器上的错误。我不是Unix文件描述符语义方面的专家,但它看起来最终的程序可能是可移植的。为什么你想这样做是另一回事...