目录
5.编写一个程序,接受两个命令行参数。第1个参数是字符,第2个参数是文件名。要求该程序只打印文件中包含给定字符的那些行。
6.二进制文件和文本文件有何区别?二进制流和文本流有何区别?
9."a+"、"r+"和"w+"模式打开的文件都是可读写的。哪种模式更适合用来更改文件中已有的内容?
复习题
1.下面的程序有什么问题?
int main(void)
{
int * fp;
int k;
fp = fopen("gelatin");
for (k = 0; k < 30; k++)
fputs(fp, "Nanette eats gelatin.");
fclose("gelatin");
return 0;
}
根据文件定义,应包含 #include <stdio.h> 。应该把 fp 声明为文件指针: FILE *fp;要给 fopen() 函数提供一种模式: fopen("gelatin","w") ,或者 "a" 模式。fputs() 函数的参数顺序应该反过来。输出字符串应该有一个换行符,提高可读性。fclose() 函数需要一个文件指针,而不是一个文件名:fclose(fp);下面是修改后的版本:#include <stdio.h>int main(void){FILE * fp;int k;fp = fopen("gelatin", "w");for (k = 0; k < 30; k++)fputs("Nanette eats gelatin.\n", fp);fclose(fp);return 0;}
2.下面的程序完成什么任务?(假设在命令行环境中运行)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv [])
{
int ch;
FILE *fp;
if (argc < 2)
exit(EXIT_FAILURE);
if ((fp = fopen(argv[1], "r")) == NULL)
exit(EXIT_FAILURE);
while ((ch = getc(fp)) != EOF)
if (isdigit(ch))
putchar(ch);
fclose(fp);
return 0;
}
如果可以打开的话,会打开与命令行第 1 个参数名相同名称的文件,并在屏幕上显示文件中的每个数字字符。
3.假设程序中有下列语句:
#include <stdio.h>
FILE * fp1,* fp2;
char ch;
fp1 = fopen("terky", "r");
fp2 = fopen("jerky", "w");
另外,假设成功打开了两个文件。补全下面函数调用中缺少的参数:
a.ch = getc();
b.fprintf( ,"%c\n", );
c.putc( , );
d.fclose(); /*
关闭
terky
文件
*/
a.ch=getc(fp1)b.fprint(fp2,"%c\n",ch);c.putc(ch,fp2);d.fclose(fp1);注意fp1用于输入操作,因为它识别以读模式打开的文件。与此类似, fp2 以写模式打开文件,所以常用于输出操作。
4.编写一个程序,不接受任何命令行参数或接受一个命令行参数。如果有一个参数,将其解释为文件名;如果没有参数,使用标准输入(stdin)作为输入。假设输入完全是浮点数。该程序要计算和报告输入数字的算术平均值。
#include <stdio.h>#include <stdlib.h>int main(int argc, char * argv []){FILE * fp;double n;double sum = 0.0;int ct = 0;if (argc == 1)fp = stdin;else if (argc == 2){if ((fp = fopen(argv[1], "r")) == NULL){fprintf(stderr, "Can't open %s\n", argv[1]);exit(EXIT_FAILURE);}}else{fprintf(stderr, "Usage: %s [filename]\n", argv[0]);exit(EXIT_FAILURE);}while (fscanf(fp, "%lf", &n) == 1){sum += n;++ct;}if (ct > 0)printf("Average of %d values = %f\n", ct, sum / ct);elseprintf("No valid data.\n");return 0;}
5.编写一个程序,接受两个命令行参数。第1个参数是字符,第2个参数是文件名。要求该程序只打印文件中包含给定字符的那些行。
注意
C
程序根据
'\n'
识别文件中的行。假设所有行都不超过
256
个字符,你可能会想到用fgets()
。
#include <stdio.h>#include <stdlib.h>#define BUF 256int has_ch(char ch, const char * line);int main(int argc, char * argv []){FILE * fp;char ch;char line[BUF];if (argc != 3){printf("Usage: %s character filename\n", argv[0]);exit(EXIT_FAILURE);}ch = argv[1][0];if ((fp = fopen(argv[2], "r")) == NULL){printf("Can't open %s\n", argv[2]);exit(EXIT_FAILURE);}while (fgets(line, BUF, fp) != NULL){if (has_ch(ch, line))fputs(line, stdout);}fclose(fp);return 0;}int has_ch(char ch, const char * line){while (*line)if (ch == *line++)return(1);return 0;}fgets() 和 fputs() 函数要一起使用,因为 fgets() 会把按下 Enter 键的 \n 留在字符串中, fputs() 与 puts() 不一样,不会添加一个换行符。
6.二进制文件和文本文件有何区别?二进制流和文本流有何区别?
二进制文件与文本文件的区别是,这两种文件格式对系统的依赖性不同。二进制流和文本流的区别包括是在读写流时程序执行的转换(二进制流不转换,而文本流可能要转换换行符和其他字符)。
7.
a.
分别用
fprintf()
和
fwrite()
储存
8238201
有何区别?
b.
分别用
putc()
和
fwrite()
储存字符
S
有何区别?
a. 用 fprintf() 储存 8238201 时,将其视为 7 个字符,保存在 7 字节中。用fwrite()储存时,使用该数的二进制表示,将其储存为一个 4 字节的整数。b.没有区别。两个函数都将其储存为一个单字节的二进制码。
8.下面语句的区别是什么?
printf("Hello, %s\n", name);
fprintf(stdout, "Hello, %s\n", name);
fprintf(stderr, "Hello, %s\n", name);
第 1 条语句是第 2 条语句的速记表示。第 3 条语句把消息写到标准错误上。通常,标准错误被定向到与标准输出相同的位置。但是标准错误不受标准输出重定向的影响。
9."a+"、"r+"和"w+"模式打开的文件都是可读写的。哪种模式更适合用来更改文件中已有的内容?
可以在以 "r+" 模式打开的文件中读写,所以该模式最合适。 "a+" 只允许在文件的末尾添加内容。"w+" 模式提供一个空文件,丢弃文件原来的内容。
编程题
暂时先放着
1.
修改程序清单
13.1
中的程序,要求提示用户输入文件名,并读取用户输入的信息,不使用命令行参数。
2.
编写一个文件拷贝程序,该程序通过命令行获取原始文件名和拷贝文件名。尽量使用标准I/O
和二进制模式。
3.
编写一个文件拷贝程序,提示用户输入文本文件名,并以该文件名作为原始文件名和输出文件名。该程序要使用 ctype.h
中的
toupper()
函数,在写入到输出文件时把所有文本转换成大写。使用标准I/O
和文本模式。
4.
编写一个程序,按顺序在屏幕上显示命令行中列出的所有文件。使用argc控制循环。
5.
修改程序清单
13.5
中的程序,用命令行界面代替交互式界面。
6.
使用命令行参数的程序依赖于用户的内存如何正确地使用它们。重写程序清单 13.2
中的程序,不使用命令行参数,而是提示用户输入所需信息。
7.
编写一个程序打开两个文件。可以使用命令行参数或提示用户输入文件名。
a.
该程序以这样的顺序打印:打印第
1
个文件的第
1
行,第
2
个文件的第
1行,第1
个文件的第
2
行,第
2
个文件的第
2
行,以此类推,打印到行数较多文件的最后一行。
b.
修改该程序,把行号相同的行打印成一行。
8.
编写一个程序,以一个字符和任意文件名作为命令行参数。如果字符后面没有参数,该程序读取标准输入;否则,程序依次打开每个文件并报告每个文件中该字符出现的次数。文件名和字符本身也要一同报告。程序应包含错误检查,以确定参数数量是否正确和是否能打开文件。如果无法打开文件,程序应报告这一情况,然后继续处理下一个文件。
9.
修改程序清单
13.3
中的程序,从
1
开始,根据加入列表的顺序为每个单词编号。当程序下次运行时,确保新的单词编号接着上次的编号开始。
10.
编写一个程序打开一个文本文件,通过交互方式获得文件名。通过一个循环,提示用户输入一个文件位置。然后该程序打印从该位置开始到下一个换行符之前的内容。用户输入负数或非数值字
符可以结束输入循环。
11.
编写一个程序,接受两个命令行参数。第
1
个参数是一个字符串,第2个参数是一个文件名。然后该程序查找该文件,打印文件中包含该字符串的所有行。因为该任务是面向行而不是面向字符的,所以要使用fgets()
而不是getc()
。使用标准
C
库函数
strstr()
(
11.5.7
节简要介绍过)在每一行中查找指定字符串。假设文件中的所有行都不超过255
个字符。
12.
创建一个文本文件,内含
20
行,每行
30
个整数。这些整数都在
0
~
9之间,用空格分开。该文件是用数字表示一张图片,0
~
9
表示逐渐增加的灰度。编写一个程序,把文件中的内容读入一个20×30
的
int
数组中。一种把这些数字转换为图片的粗略方法是:该程序使用数组中的值初始化一个20×31的字符数组,用值0
对应空格字符,
1
对应点字符,以此类推。数字越大表示字符所占的空间越大。例如,用#
表示
9
。每行的最后一个字符(第
31
个)是空字符,这样该数组包含了20
个字符串。最后,程序显示最终的图片(即,打印所有的字符串),并将结果储存在文本文件中。例如,下面是开
始的数据:
0 0 9 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 9 0 0 0 0 0 0 0 5 8 9 9 8 5 5 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 1 9 8 5 4 5 2 0 0 0 0 0 0 0 0 0
0 0 0 0 9 0 0 0 0 0 0 0 5 8 9 9 8 5 0 4 5 2 0 0 0 0 0 0 0 0
0 0 9 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 4 5 2 0 0 0 0 0 0 0
1003
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 1 8 5 0 0 0 4 5 2 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 4 5 2 0 0 0 0 0
5 5 5 5 5 5 5 5 5 5 5 5 5 8 9 9 8 5 5 5 5 5 5 5 5 5 5 5 5 5
8 8 8 8 8 8 8 8 8 8 8 8 5 8 9 9 8 5 8 8 8 8 8 8 8 8 8 8 8 8
9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 3 9 9 9 9 9 9 9
8 8 8 8 8 8 8 8 8 8 8 8 5 8 9 9 8 5 8 8 8 8 8 8 8 8 8 8 8 8
5 5 5 5 5 5 5 5 5 5 5 5 5 8 9 9 8 5 5 5 5 5 5 5 5 5 5 5 5 5
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 6 6 0 0 0 0 0 0
0 0 0 0 2 2 0 0 0 0 0 0 5 8 9 9 8 5 0 0 5 6 0 0 6 5 0 0 0 0
0 0 0 0 3 3 0 0 0 0 0 0 5 8 9 9 8 5 0 5 6 1 1 1 1 6 5 0 0 0
0 0 0 0 4 4 0 0 0 0 0 0 5 8 9 9 8 5 0 0 5 6 0 0 6 5 0 0 0 0
0 0 0 0 5 5 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 6 6 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0
根据以上描述选择特定的输出字符,最终输出如下:

13.
用变长数组(
VLA
)代替标准数组,完成编程练习
12
。
14.
数字图像,尤其是从宇宙飞船发回的数字图像,可能会包含一些失真。为编程练习12
添加消除失真的函数。该函数把每个值与它上下左右相邻的值作比较,如果该值与其周围相邻值的差都大于1
,则用所有相邻值的平均值(四舍五入为整数)代替该值。注意,与边界上的点相邻的点少于4
个,所以做特殊处理。