由于您似乎使用的是 UNIX-y 系统,您通常可以这样做,而不是直接使用 getchar() 和朋友,而是使用其他带有文件指针的 stdio 函数(例如 fgets()、getc() ,等等),如果你创建这样一个指向你的终端的指针。
例如,下面的程序:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFSIZE 1024
/* Returns a file pointer to the terminal, exits on failure */
FILE * get_terminal(void)
{
char * tname = ctermid(NULL);
int fd = open(tname, O_RDWR);
if ( fd == -1 ) {
perror("couldn't open terminal");
exit(EXIT_FAILURE);
}
FILE * fp = fdopen(fd, "r+");
if ( !fp ) {
fprintf(stderr, "couldn't make file pointer\n");
exit(EXIT_FAILURE);
}
return fp;
}
/* Closes a file pointer to the terminal */
void close_terminal(FILE * fp)
{
if ( fclose(fp) == EOF ) {
perror("couldn't close terminal");
exit(EXIT_FAILURE);
}
}
/* Main function */
int main(void)
{
FILE * fp = get_terminal();
char buffer[BUFSIZE];
/* Get line from stdin and print to stdout */
fgets(buffer, BUFSIZE, stdin);
fprintf(stdout, "Line 1: %s", buffer, stdout);
/* Get string from terminal and print to terminal */
fputs("Enter a string: ", fp);
fflush(fp);
fgets(buffer, BUFSIZE, fp);
fprintf(fp, "You entered: %s", buffer);
/* Get another line from stdin and print to stdout */
fgets(buffer, BUFSIZE, stdin);
fprintf(stdout, "Line 2: %s", buffer, stdout);
close_terminal(fp);
return 0;
}
即使您的 shell 重定向程序的标准输入和标准输出,也会提供以下输出:
paul@thoth:~/src/sandbox$ cat input.txt
This is the first line of the file.
This is the second line of the file.
paul@thoth:~/src/sandbox$ ./prog < input.txt > output.txt
Enter a string: This is my string.
You entered: This is my string.
paul@thoth:~/src/sandbox$ cat output.txt
Line 1: This is the first line of the file.
Line 2: This is the second line of the file.
paul@thoth:~/src/sandbox$
请注意,ctermid() 生成的内容不能保证唯一标识终端(事实上,在大多数系统上不会 - 它通常是 /dev/tty)并且不能保证您能够打开它.但它可能会在现代 UNIX-y 个人计算机上运行。
您是否应该这样做完全是另一个问题。在绝大多数情况下,这将是非常不寻常和意想不到的行为。如果您希望用户能够指定诸如制表位大小之类的选项,则使用命令行参数将是比交互式获取更好的解决方案,例如:
./prog --tabstop=4 < input.txt > output.txt
K&R 在 5.10 节中介绍了命令行参数,getopt 库是使用它们的一种常见且简单的方法。
对于更持久的选项,使用配置文件甚至读取环境变量是其他潜在的解决方案。
显然以上所有内容都比 K&R 的第 1 章要先进得多,但是既然你说“我尽量不走得比 K&R 迄今为止教给我的更远”,然后立即问如何比 K&R 走得更远教你到目前为止,这就是即将发生的事情。就您而言,目前最好的选择就是完成其余章节,并且在您读完之前,您将回答大部分问题。