除了fprintf(stdin, bug 你还忘了stdin 不是键盘。最新的C11 标准不了解键盘。在 Linux 图形桌面上,只有 X11 服务器正在从物理键盘读取数据。
实际上,在POSIX 系统上,尤其是Linux 等系统上,stdin 可以是pipe(7)(在你的shell 中使用pipelines 很常见),fifo(7),socket(7),一个普通的文件(通过redirection)甚至/dev/null,当然还有terminal。
最近有趣的是终端通常是虚拟仿真设备(我在本世纪没有看到任何真正的物理终端,除了博物馆),请阅读pseudotty。由于历史原因,细节相当神秘。阅读tty demystified 页面。另请参阅 ANSI escape code wikipage & console_codes(4) 和 tty(4)(所以请考虑 /dev/tty 和也许 /dev/console)
您可以使用isatty(STDIN_FILENO)检查(使用isatty(3))stdin 是一个终端(实际上是一个伪终端)...
实际上,当你真的想使用终端时,我强烈建议使用ncurses 或GNU readline 之类的库(两者都在使用termios(3))
别忘了I/O一般是buffered,要明智地使用fflush(3)。
顺便说一句,您应该使用所有警告和调试信息 (gcc -Wall -Wextra -g) 进行编译,然后使用 gdb 调试器。 strace(1) 也会非常有用。
也许你想通过管道传输到你自己的程序(但这很奇怪,而且经常是错误的,除非你非常注意所有的含义;然而,在面向事件的程序中处理signal(7) 是一个非常有用的技巧,尤其是那些有一些GUI)。请注意管道的缓冲区大小有限(因此请避免使用deadlocks,可能通过将event loop 与poll(2) 放在一起)并阅读有关PIPE_BUF 和write 的信息。您可能已经尝试过:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int pfd[2] = {-1,-1};
int a= 0;
if (pipe(pfd)) { perror("pipe"); exit (EXIT_FAILURE); };
if (dup2(pfd[0],STDIN_FILENO)<0)
{ perror("dup2 stdin"); exit(EXIT_FAILURE);};
if (dup2(pfd[1],STDOUT_FILENO)<0)
{ perror("dup2 stdout"); exit(EXIT_FAILURE);};
if (printf("%d\n", 123)<=0) { perror("printf"); exit(EXIT_FAILURE); };
if (fflush(stdout)) { perror("fflush"); exit(EXIT_FAILURE); };
if (scanf("%d", &a)<1) { perror("scanf"); exit(EXIT_FAILURE); };
if (a != 123) { fprintf(stderr, "impossible happened a=%d\n", a); };
fprintf(stderr, "done...got a=%d\n", a);
}
您应该阅读Advanced Linux Programming 并了解有关syscalls(2) 的更多信息;它有几个与此相关的章节。仔细阅读pipe(2) 和dup2(2) 并注意上面的程序对于更大的输出是错误的(更大的PIPE_BUF,在我的系统上是几千字节)
顺便说一句,您可以使用fmemopen(3) 从内存缓冲区中获取可读的FILE*。对于写入(例如使用fprintf)到输出缓冲区,请考虑open_memstream,并且在访问输出缓冲区之前不要忘记fflush。