栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C Primer Plus 第六版 第十三章 编程练习

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C Primer Plus 第六版 第十三章 编程练习

1.修改程序清单13.1中的程序,要求提示用户输入文件名,并读取用户输入的信息,不使用命令行参数。

#include 
#include 
#define SIZE 40
int main(void)
{
	char filename[SIZE];
	int ch;
	FILE *fp;
	unsigned long count=0;

	puts("Enter the filename: ");
	if(scanf("%s",filename)!=1)
	{
		puts("Filename intput error.");
		exit(EXIT_FAILURE);
	}
	if((fp=fopen(filename,"r"))==NULL)
	{
		printf("Can't open file:%s.n",filename);
		exit(EXIT_FAILURE);
	}
	while((ch=getc(fp))!=EOF)
	{
		putchar(ch);     // putc(ch,stdout);
		count++;
	}
	putchar('n');
	fclose(fp);
	printf("File %s has %lu characters.n",filename,count);

	return 0;
}

2.编写一个文件拷贝程序,该程序通过命令行获取原始文件名和拷贝文件名。尽量使用标准I/O 和二进制模式。

#include 
#include 
int main(int argc,char * argv[])
{
	int ch;
	FILE * fp1;
	FILE * fp2;

	if(argc!=3)
	{
		printf("%s:Usage filename.n",argv[1]);
		exit(EXIT_FAILURE);
    }
	if((fp1=fopen(argv[1],"rb"))==NULL)
	{
		printf("Couldn't open file:%sn",argv[1]);
		exit(EXIT_FAILURE);
	}
	if((fp2=fopen(argv[2],"wb"))==NULL)
	{
		printf("Couldn't open file:%sn",argv[2]);
		exit(EXIT_FAILURE);
	}
	printf("Originally file:%sn",argv[1]);
	while((ch=getc(fp1))!=EOF)
		putc(ch,stdout);
	putchar('n');
	fseek(fp1,0L,SEEK_SET);     // 定位到文件开头
	while((ch=getc(fp1))!=EOF)  // 把第一个文件的内容复制到第二个文件
		putc(ch,fp2);
	fclose(fp1);
	fclose(fp2);
	if((fp2=fopen(argv[2],"rb"))==NULL)
	{
		printf("couldn't open file:%sn",argv[2]);
		exit(EXIT_FAILURE);
	}
	printf("Now,file:%sn",argv[2]);  // 显示第二个文件的内容
	while((ch=getc(fp2))!=EOF)
		putc(ch,stdout);
	fclose(fp2);

	return 0;
}

3.编写一个文件拷贝程序,提示用户输入文本文件名,并以该文件名作为原始文件名和输出文件名。该程序要使用ctype.h中的toupper()函数,在写入到输出文件时把所有文本转换成大写,使用标准I/O和文本模式。

#include 
#include 
#include 
int main(void)
{
	char filename[40];
	char ch;
	FILE * fp;

	printf("Enter the filename:n");
	if(scanf("%s",filename)!=1)
	{
		printf("Filename input error.n");
		exit(EXIT_FAILURE);
	}
	if((fp=fopen(filename,"r+"))==NULL)
	{
		printf("Couldn't open file:%sn",filename);
		exit(EXIT_FAILURE);
	}
	getchar();
	printf("Enter the characters:n");
	while((ch=getchar())!=EOF)    从标准I/0中写入,并转换为大写后,写入文件
	{
		ch=toupper(ch);
		putc(ch,fp);
	}
	fseek(fp,0,SEEK_SET);
	printf("Now,file %s:n",filename);
	while((ch=getc(fp))!=EOF)    //显示文件内容
		putc(ch,stdout);
	fclose(fp);

	return 0;
}

 

 4.编写一个程序,按顺序在屏幕上显示命令行中列出的所有文件。使用argc控制循环。

#include 
#include 
int main(int argc,char * argv[])
{
	char ch;
	FILE * fp;
	int i;

	for(i=0;i

 

5.修改程序清单13.5中的程序,用命令行界面代替交互式界面。

#include 
#include 
#include 
#define BUFFSIZE 4096
void append(FILE * fs,FILE * fa);
int main(int argc, char * argv[])
{
	char ch;
	int i;
	FILE * fs,* fa;

	if(argc<3)
	{
		printf("Need at least 2 file.n");
		exit(EXIT_FAILURE);
	}
	if((fa=fopen(argv[1],"a+"))==NULL) // 以更新模式打开文件,在末尾添加
	{
		fprintf(stderr,"error in open file %sn",argv[1]);
		exit(EXIT_FAILURE);
	}
	if(setvbuf(fa,NULL,_IOFBF,BUFFSIZE)!=0)   // 为写设置缓冲区
	{
		fprintf(stderr,"error in set buffer for input.n");
		exit(EXIT_FAILURE);
	}
	for(i=0;i0)
		fwrite(temp,sizeof(char),bytes,fa);
}

6.使用命令行参数的程序依赖于用户的内存如何正确地使用它们。重写程序清单13.2中的程序, 不使用命令行参数,而是提示用户输入所需信息。

#include 
#include 
#include 
#define LEN 40
char * s_gets(char * st,int n);
int main(void)
{
	FILE * in,* out;
	char file_src[LEN];
	char file_app[LEN];
	char ch;
	int count=0;

	printf("Enter the source file:n");
	while(s_gets(file_src,LEN)==NULL||file_src[0]=='')
	{
		fprintf(stderr,"File name input error.n");
		printf("Try again:n");
	}
	if((in=fopen(file_src,"r"))==NULL)
	{
		fprintf(stderr,"Can't open file:%s.n",file_src);
		exit(EXIT_FAILURE);
	}
	strncpy(file_app,file_src,LEN-5);
	file_app[LEN-5]='';
	strcat(file_app,".red");
	if((out=fopen(file_app,"w"))==NULL)
	{
		fprintf(stderr,"Can't open file:%s.n",file_app);
		exit(EXIT_FAILURE);
	}
	while((ch=getc(in))!=EOF)   // 压缩文件到输出
	{
		if(count++%3==0)
			putc(ch,out);
	}
	if(fclose(in)!=0||fclose(out)!=0)
		fprintf(stderr,"Error in closing file.n");

	return 0;
}

char * s_gets(char * st,int n)
{
	char * ret_val;
	int i=0;

	ret_val=fgets(st,n,stdin);
	while(st[i]!='/0'&&st[i]!='n')
		i++;
	if(st[i]=='n')
		st[i]='';
	else
		while(getchar()!='n')
			continue;

	return ret_val;
}

  

7.编写一个程序打开两个文件。可以使用命令行参数或提示用户输入文件名。

a.该程序以这样的顺序打印:打印第1个文件的第1行,第2个文件的第1行,第1个文件的第2 行,第2个文件的第2行,以此类推,打印到行数较多文件的最后一行。    

b.修改该程序,把行号相同的行打印成 一行。

#include 
#include 
void fun_a(FILE * fp1,FILE * fp2);  // 按a的方式打印
void fun_b(FILE * fp1,FILE * fp2);  // 按b的方式打印
int main(int argc,char * argv[])
{
	FILE * fp1,* fp2;

	if(argc<3)
	{
		fprintf(stderr,"Hasn't enough arc.n");
		exit(EXIT_FAILURE);
	}
	if((fp1=fopen(argv[1],"r"))==NULL)
	{
		fprintf(stderr,"Can't open file:%sn",argv[1]);
		exit(EXIT_FAILURE);
	}
	if((fp2=fopen(argv[2],"r"))==NULL)
	{
		fprintf(stderr,"Can't open file:%sn",argv[2]);
		exit(EXIT_FAILURE);
	}
	fun_a(fp1,fp2);
	printf("n");
	rewind(fp1);
	rewind(fp2);
	fun_b(fp1,fp2);
	if(fclose(fp1)!=0||fclose(fp2)!=0)
		fprintf(stderr,"Error in closing file.n");

	return 0;
}

void fun_a(FILE * fp1,FILE * fp2)
{
	char ch1,ch2;

	do
	{
		while((ch1=getc(fp1))!='n'&&ch1!=EOF)
			putc(ch1,stdout);
		putchar('n');
		while((ch2=getc(fp2))!='n'&&ch2!=EOF)
			putc(ch2,stdout);
		putchar('n');
	}while(ch1!=EOF||ch2!=EOF);
}

void fun_b(FILE * fp1,FILE * fp2)
{
	char ch1,ch2;

	do
	{
		while((ch1=getc(fp1))!='n'&&ch1!=EOF)
			putc(ch1,stdout);
		while((ch2=getc(fp2))!='n'&&ch2!=EOF)
			putc(ch2,stdout);
		putchar('n');
	}while(ch1!=EOF||ch2!=EOF);
}

 

8.编写一个程序,以一个字符和任意文件名作为命令行参数。如果字符后面没有参数,该程序读取标准输入;否则,程序依次打开每个文件并报告每个文件中该字符出现的次数。文件名和字符 本身也要一同报告。程序应包含错误检查,以确定参数数量是否正确和是否能打开文件。如果无法 打开文件,程序应报告这一情况,然后继续处理下一个文件。

#include 
#include 
#include 
#define MAXSIZE 81
int main(int argc,char * argv[])
{
	FILE * fp;
	char temp[MAXSIZE];
	int i=0,count=0;
	char ch;

	if(argc<2)
	{
		fprintf(stderr,"Usage filename:%sn",argv[0]);
		exit(EXIT_FAILURE);
	}
	if(argc==2)   //标准输入
	{
		if(fgets(temp,MAXSIZE,stdin)!=NULL)
		{
			while(temp[i]!='')
			{
				if(temp[i]==*argv[1])
					count++;
				i++;
			}
			printf("Character %c appeared %d times in the input stream.n",*argv[1],count);
		}
		else
			printf("Input NULL.n");
	}
	count=0;
	if(argc>2)   // .txt文件输入
		{
		for(i=2;i

9.修改程序清单13.3中的程序,从1开始,根据加入列表的顺序为每个单词编号。当程序下次运行时,确保新的单词编号接着上次的编号开始。

#include 
#include 
#include 
#define SIZE 40
int main(void)
{
	FILE * fp;
	char words[SIZE];
	int i=0;    // i为单词编号

	if((fp=fopen("file.txt","a+"))==NULL)
	{
		fprintf(stderr,"Can't open file.txt.n");
		exit(EXIT_FAILURE);
	}
	puts("Enter the words,press ");
    puts("# at the beginning of a line to terminate:");
	while(fscanf(fp,"%s",words)==1)  // 统计原有的单词数
		i++;
	while(fscanf(stdin,"%40s",words)==1&&words[0]!='#')  // 遇到空白字符,输入单词结束
		fprintf(fp,"%d%sn",++i,words);  // 读入新单词,并为其编号
	rewind(fp);
	puts("File content:");
	while(fscanf(fp,"%s",words)==1)
		puts(words);
	while(fclose(fp)!=0)
		fprintf(stderr,"Error in closing file.n");

	return 0;
}

  

10.编写一个程序打开一个文本文件,通过交互方式获得文件名。通过一个循环,提示用户输入 一个文件位置。然后该程序打印从该位置开始到下一个换行符之前的内容。用户输入负数或非数值 字符可以结束输入循环。

#include 
#include 
#include 
#define MAXSIZE 81
int main(void)
{
	char temp[MAXSIZE];
	FILE * fp;
	long pos;

	if((fp=fopen("file.txt","r"))==NULL)
	{
		fprintf(stderr,"Can't open file.txt.n");
		exit(EXIT_FAILURE);
	}
	puts("Enter the position:");
	while(scanf("%ld",&pos)==1&&pos>0)
	{
		fseek(fp,pos-1,SEEK_SET);         // 定位文件位置
		if(fgets(temp,MAXSIZE,fp)!=NULL)  // 输出该位置到下一个换行符的内容
			fputs(temp,stdout);
		rewind(fp);
	}
	if(fclose(fp)!=0)
		fprintf(stderr,"Error in closing file.n");

	return 0;
}

 

11.编写一个程序,接受两个命令行参数。第1个参数是一个字符串,第2个参数是一个文件名。 然后该程序查找该文件,打印文件中包含该字符串的所有行。因为该任务是面向行而不是面向字符 的,所以要使用fgets()而不是getc()。使用标准C库函数strstr()(11. 5. 7 节简要介绍过) 在每一行中查找指定字符串。假设文件中的所有行都不超过255个字符。

#include 
#include 
#include 
#define MAXSIZE 255
int main(int argc,char * argv[])
{
	char temp[MAXSIZE];
	FILE * fp;
	int count=0;

	if(argc<3)
	{
		fprintf(stderr,"Usage filename:%sn",argv[2]);
		exit(EXIT_FAILURE);
	}
	if((fp=fopen(argv[2],"r"))==NULL)
	{
		fprintf(stderr,"Can't open file:%sn",argv[2]);
		exit(EXIT_FAILURE);
	}
	while(fgets(temp,MAXSIZE,fp)!=NULL)  // 每一行输入到临时数组中,并与字符串做比较
	{
		if(strstr(temp,argv[1])!=0)
		{
			fputs(temp,stdout);
			count++;
		}
    }
	if(count==0)
		printf("No line include string:%sn",argv[1]);
	if(fclose(fp)!=0)
		printf("Error in closing file:%sn",argv[2]);

	return 0;
}

 

 

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

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

根据以上描述选择特定的输出字符,最终输出如下:

 

#include 
#include 
#include 
#include 
int main(void)
{
	FILE * fp1,* fp2;
	int arr1[20][30];  // 保存数字的数组
	int arr2[20][31];  // 保存字符的数组
	int i,j;
	char ch;

	if((fp1=fopen("1.txt","r"))==NULL)
	{
		fprintf(stderr,"Can't open file:1.txtn");
		exit(EXIT_FAILURE);
	}
	for(i=0;i<20;i++)     // 从文件读入数字到数组
		for(j=0;j<60;j++)
		{
			if((ch=getc(fp1))!=EOF&&isdigit(ch))
				arr1[i][j/2]=(int)ch-48;
		}
	if(fclose(fp1)!=0)
		fprintf(stderr,"Error in closing file 1.txtn");
	for(i=0;i<20;i++)     //  把数字转换为字符,并存入到arr2数组中
		for(j=0;j<30;j++)
		{
			switch(arr1[i][j])
			{
				case 0:arr2[i][j]=' ';  break;
				case 1:arr2[i][j]='.';  break;
				case 2:arr2[i][j]=''';  break;
				case 3:arr2[i][j]=':';  break;
				case 4:arr2[i][j]='~';  break;
				case 5:arr2[i][j]='*';  break;
				case 6:arr2[i][j]='=';  break;
				case 7:arr2[i][j]='^';  break;
				case 8:arr2[i][j]='%';  break;
				case 9:arr2[i][j]='#';  break;
				default: break;
			}
		}
	for(i=0;i<20;i++)
		arr2[i][30]='';
	if((fp2=fopen("2.txt","a+"))==NULL)
	{
		fprintf(stderr,"Can't open file:2.txtn");
		exit(EXIT_FAILURE);
	}
	for(i=0;i<20;i++)        // 把arr2数组的字符,读入到文件中
	{
		for(j=0;j<31;j++)
			putc(arr2[i][j],fp2);
		putc('n',fp2);
	}
	rewind(fp2);
	puts("Content output:");
	while((ch=getc(fp2))!=EOF)   //输出文件的内容
		putc(ch,stdout);
	if(fclose(fp2)!=0)
		fprintf(stderr,"Error in closing file 2.txtn");

	return 0;
}

          

13.用变长数组(VLA)代替标准数组,完成编程练习12。

#include 
#include 
#include 
#include 
int main(void)
{
	FILE * fp1,* fp2;
	int a=20;
	int b=30;
	int arr1[a][b];    // 声明变长数组
	int i,j;
	char ch;

	if((fp1=fopen("1.txt","r"))==NULL)
	{
		fprintf(stderr,"Can't open file:1.txtn");
		exit(EXIT_FAILURE);
	}
	if((fp2=fopen("2.txt","a+"))==NULL)
	{
		fprintf(stderr,"Can't open file:2.txtn");
		exit(EXIT_FAILURE);
	}
	for(i=0;i

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

#include 
#include 
#include 
#include 
void func(int a,int b,int arr[a][b]);  // 消除失真的函数
int main(void)
{
	FILE * fp1,* fp2;
	int a=20;
	int b=30;
	int arr1[a][b];
	int i,j;
	char ch;

	if((fp1=fopen("1.txt","r"))==NULL)
	{
		fprintf(stderr,"Can't open file:1.txtn");
		exit(EXIT_FAILURE);
	}
	if((fp2=fopen("2.txt","a+"))==NULL)
	{
		fprintf(stderr,"Can't open file:2.txtn");
		exit(EXIT_FAILURE);
	}
	for(i=0;i1&&         // 与上下左右做比较
			   abs(arr[i][j]-arr[i+1][j]>1)&&
			   abs(arr[i][j]-arr[i][j-1]>1)&&
			   abs(arr[i][j]-arr[i][j+1]>1))
			{
					arr[i][j]=(arr[i-1][j]+arr[i+1][j]+arr[i][j-1]+arr[i][j+1])/4;
					temp=((arr[i-1][j]+arr[i+1][j]+arr[i][j-1]+arr[i][j+1])/4.0-arr[i][j])>=0.5?1:0;                                               //四舍五入
					arr[i][j]+=temp;
			}
		}
}

因笔者水平有限,边界未作特殊处理。请见谅。


史蒂芬·普拉达(Stephen Prata). C Primer Plus(第6版)中文版(异步图书) (Kindle位置17210). 人民邮电出版社. Kindle 版本. 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/968876.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号