C printf无法从终端

时间:2018-09-14 13:35:25

标签: java c++ c command-line terminal

我已尽最大可能将问题减少到以下最小代码段。如果需要更多信息,请询问。

可以说我有一个名为A的Java类,其主要方法是:

public static void main (String args[])throws Exception{
    Process p = new ProcessBuilder(args).redirectErrorStream(true).start();
    Scanner in = new Scanner(new InputStreamReader(p.getInputStream())); 
    System.out.println(in.nextLine());
}

基本上,它从终端运行一个程序,从该程序读取一行,然后回显它。很简单。

现在我有第二个用c ++编写的程序,如下所示:

int main() 
{
    string s;
    cout << "example2 in c++"<<endl;;
    cin >> s;
    return 0;
}

当我调用时:

java A pathToC++Program

程序按预期运行,输出从cpp程序发送的字符串并终止。

我在c中有一个等效程序:

int main()
{
   char s[10];
   printf("example1 in c\n");
   fgets(s,10,stdin); 
   return 0;
}

当我调用时:

java A pathToCprogram

程序停止,什么也没打印出来。

当我从c程序中删除fgets行时,它看起来像这样:

int main()
{
   printf("example1 in c\n");
   return 0;
}

然后Java程序便能够识别该行并将其打印出来。因此,似乎fgets是有问题的行,但是当包含fgets时,即使它之前的行也不起作用。

这是怎么回事?

(我不知道这是Java还是C的特殊性,所以我包括了两个标签。)

1 个答案:

答案 0 :(得分:6)

默认行缓冲写入到stdoutprintf将写入其输出的位置),这意味着缓冲区将在换行符处刷新。

但是 是直接从终端运行时的默认设置。如果输出是 not 终端,则stdout将被完全缓冲,这意味着仅当您填充缓冲区时才将其刷新。或进行明确的fflush(stdout)调用。

在C ++程序中,您使用std::endl 显式刷新输出(它写换行符 刷新缓冲的输出)。在您的C程序中,没有输出缓冲区的这种刷新。

这确实是特定于平台的,但是对于POSIX平台(例如Linux或macOS),就像上面描述的那样。我认为它与Windows非常相似。

关于删除fgets语句时它为什么起作用的原因,可能是因为fgets阻止执行,直到文件结束或某些(换行符终止)输入已被读取。如果没有fgets,程序将在printf之后立即退出,这将导致stdout缓冲区被刷新。