一. 几个特殊的宏
putchar(char ch);
int getchar();
putc(char ch, FILE * fp);
int getc(FILE * fp)
以上从从用户角度看都是函数,但实质是宏。都是从库函数fputc(char ch, FILE * fp)以及 fgetc(FILE * fp)定义出来的宏。不同的是,有一个标准输入stdin(键盘),有一个标准输出stdout(终端),进行了如下宏定义:
#define putchar(ch) fputc(ch,stdout)
#define getchar() fgetc(stdin)
#define putc(ch,fp) fputc(ch,fp)
#define getc(fp) fgetc(fp)
二. 重定向
标准输入stdin(键盘)、标准输出stdout(终端-显示器)和标准错误stderr(终端-显示器),在默认情况下,都是按照标准进行的。比如scanf、getchar是从键盘得到输入,printf、putchar是输出显示器上。大多数情况下,我们也是按照默认的标准输入输出做的,但某些特定环境,我们希望从另外一个地方得到“输入”,而将结果“输出”到其它地方。这时,就产生了重定向的概念。
所谓重定向,就是不使用系统的标准输入端口、标准输出端口或标准错误端口,而进行重新的指定,所以重定向分为输出重定向、输入重定向和错误重定向。以下分别举例。
(1)输入重定向:编译后程序名为prog1.exe 在 C盘下存在文件test.txt,内容为"Bulls"
示例代码: scanf("%c",&ch);putchar(ch);
在cmd中运行:prog1 < C:/test.txt
显示器结果:B
分析:"< "将标准输入重定向"C:/text.txt",即从text.txt中得到第一个字符B,然后putchar到显示器上
(2)输出重定向:编译后程序名为prog2.exe 在 C盘下存在文件test.txt,内容为"Bulls"
示例代码:ch=getchar();ch++;printf("%c",ch);
在cmd中运行:prog2 >C:/test.txt
显示器:(输入)A (空回显) 打开test.txt文件,内容变为"B"
再在cmd中运行:prog2 >>c:/text.txt
显示器:(输入)C (空回显) 打开test.txt文件,内容变为"BD"
分析:">"或">>"将标准输出重定向到"C:/test.txt",即输出不显示到显示器上,而直接写入重定向的文件中。">"是重写文件,而">>"是追加文件。
备注:当然你可以这样写"prog2 <C:/test.txt >>C:/test.txt",既重定向标准输入,又重定向标准输出。
(3)错误重定向:编译后程序为prog3.exe
看代码:if((fp=fopen("C:/test1.txt","r"))==NULL) printf("Open Error!");
当打开特定文件失败时,prog3会向标准输出字符串"Open Error!"。当没有重定向标准输出时,没问题,"Open Error!"只是在显示器中出现。但不幸的是,当我们重定向了标准输出到一个文件,那么,"Open Error!"就会出现在该文件中,这可能是我们不需要的,因为"Open Error!"只是提示我们打开文件失败。
此时,修改代码:if((fp=fopen("C:/test1.txt","r"))==NULL) fprintf(stderr,"Open Error!");
在cmd中运行:prog3 >>C:/test.txt 即使找不到文件,"Open Error!"也只出现在显示器上,而不追加到test.txt中。
三. 管道
类似于水管一样,水在t时刻(输出)流向t+1时刻(输入)。从程序上来看,就是一个程序的输出,作为另一个程序的输入,这就是管道的定义。管道在某种程度上是输入和输出重定向的结合。用prog1.exe和prog2.exe来举例说明。我们看到,prog1.exe的功能是得到一个字符,再输出;而prog2.exe的功能是得到一个字符,变成下一个字符后输出。
在cmd中运行:prog1 | prog2
显示器:(输入)A (回显)B
分析:"A"是输入到prog1.exe中的,然后prog1.exe会直接将A输出,此时,"|"定义了管道,将prog1.exe的输出作为prog2.exe的输入,于是,"A"作为prog2.exe的输入字符,加1后变成"B",再输出。
如果在cmd中运行:prog2 | prog2
显示器:(输入)A (回显)C
当然,可以将重定向和管道结合,如:prog1 <test.txt | prog2 >test1.txt