启动一个C语言程序时,操作系统环境负责打开三个文件,并将这3个文件的指针提供给该程序。这3个文件分别为标准输入(stdin)、标准输出(stdout)、标准错误(stderr)。它们在<stdio.h>中声明,大多数环境中,stdin指向键盘,stdout、stderr指向显示器。之所以使用stderr,若因某种原因造成其中一个文件无法访问,相应的诊断信息要在该链接的输出的末尾才能打印出来。当输出到屏幕时,这种处理方法尚可接受,但如果输出到一个文件或通过管道输出到另一个程序时,就无法接受了。若有stderr存在,即使对标准输出进行了重定向,写到stderr中的输出通常也会显示在屏幕上。 exit():在主程序main中,语句return expr等价于exit(expr)。但是,函数exit有一个优点,它可以从其他函数中调用,并且可以用查找程序查找这些调用。exit(0)为正常退出,exit(1)只要里面的参数不为零,为非正常退出,。 fgets: char *fgets(char *line, int maxline, FILE *fp); fp指向的文件中读取下一个输入行(包括换行符),并将它存放在字符数组line中,最多读取maxline-1个字符。读取的行将以‘\0‘结尾,结尾保存到数组中。通常,fgets返回line,遇到文件结尾或发生错误,返回NULL。 晚上做了一个题,用去了很长时间,就因为一些简单错误,在此记录。《C程序设计语言》第2版(中文)P145 7-6: 编写一个程序,比较两个文件并打印它们第一个不相同的行。 1 #include <stdio.h> 2 3 #define MAXSIZE 100 4 5 main(int argc, char *argv[]) 6 { 7 FILE *fp1, *fp2; 8 void filecmp(FILE *, FILE *); 9 char *prog = argv[0]; 10 11 if (argc < 3) { 12 fprintf(stderr, "error: no enough files!\n"); 13 exit(1); 14 } 15 else { 16 if ((fp1 = fopen(*++argv, "r")) == NULL) { 17 fprintf(stderr, "%s: can‘t open %s\n", prog, *argv); 18 exit(2); 19 } 20 else if ((fp2 = fopen(*++argv, "r")) == NULL) { 21 fprintf(stderr, "%s: can‘t open %s\n", prog, *argv); 22 exit(3); 23 } 24 else { 25 filecmp(fp1, fp2); 26 fclose(fp1); 27 fclose(fp2); 28 } 29 } 30 exit(0); 31 } 32 33 void filecmp(FILE *ifp1, FILE *ifp2) 34 { 35 char line1[MAXSIZE], line2[MAXSIZE]; 36 37 int count = 0; 38 int full = 0; 39 40 while ((fgets(line1, MAXSIZE, ifp1) != NULL) && 41 (fgets(line2, MAXSIZE, ifp2) != NULL)) { 42 if ((strcmp(line1, line2)) == 0) { 43 count++; 44 full = 1; 45 } 46 else { 47 fprintf(stdout, "The number of different line is %d\n", count); 48 fprintf(stdout, "%s\n", line1); 49 fprintf(stdout, "%s\n", line2); 50 return; 51 } 52 } 53 if (!full) 54 fprintf(stderr, "error: cannont read!\n"); 55 else 56 fprintf(stderr, "same files!\n"); 57 } 错误1:将第35行写为: 这里明显混淆了数组与指针的关系,若为当做数组,实际是第一个数的地址,而不是整个数组。 错误2:第42行后,加了两句: fp1、fp2实际是指向文件的文件描述符,不能做加减运算。按照我的本意是fp1自加后指向文件的下一行,实际上fgets函数读取下一行时已经加上换行符了。 fgets函数如下: 1 char *fgets(char *s, int n, FILE *fp) 2 { 3 register int c; 4 register char *cs; 5 6 while (--n > 0 && (c = getc(iop)) != EOF) 7 if ((*cs++ = c) == ‘\n‘) 8 break; 9 *cs = ‘\0‘; 10 return (c == EOF && cs == s) ? NUll : s; 11 } 第7行写的很清楚,读了换行符。 总结经验:要先弄清函数各个参数的用法再动手,否则事倍功半。 关于 stdin、stdout、stderr 的说明如下:
By default, standard input is read from the keyboard, while standard output and standard error are printed to the screen
默认情况下,标准输入从键盘读取,同时标准输出和标准错误会打印到屏幕。
在控制台测试 :
void main( void ) { fprintf(stderr, "%s:%d", __FILE__, __LINE__); system("pause"); }
会在屏幕显示当前文件的路径和fprintf语句所在的行数。 ^_^ |