C Primer Plus第13章编程练习~ 加油加油!
这一章是文件I/O相关 是文件处理相关章节~
一起闪闪发光~⭐️
☘️欢迎大家讨论 批评指正~
1.修改程序清单13.1中的程序,要求提示用户输入文件名,并读取用户输入的信息,不使用命令行参数。
程序清单13.1 count.c程序
/* count.c -- 使用标准 I/O */
#include
#include // 提供 exit()的原型
int main(int argc, char *argv [])
{
int ch; // 读取文件时,储存每个字符的地方
FILE *fp; // “文件指针”
unsigned long count = 0;
if (argc != 2)
{
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
printf("Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF)
{
putc(ch, stdout); // 与 putchar(ch); 相同
count++;
}
fclose(fp);
printf("File %s has %lu characters\n", argv[1], count);
return 0;
}
解答部分
#include
#include // 提供 exit()的原型
#define LEN 10
int main(void)
{
char name[LEN];
FILE *fp; // “文件指针”
char ch;
unsigned long count = 0;
printf("please enter the file name:");
scanf("%s",name);
fp=fopen(name,"r");
if(fp==NULL){
fprintf(stderr, "Can't open %s\n", name);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF){
putc(ch, stdout);
count++;
}
fclose(fp);
printf("\nFile %s has %lu characters\n", name, count);
return 0;
}
编写一个文件拷贝程序,该程序通过命令行获取原始文件名和拷贝文件名。尽量使用标准I/O和二进制模式。
/*
* @Description: 编写一个文件拷贝程序,该程序通过命令行获取原始文件名和拷贝文
件名。尽量使用标准I/O和二进制模式。
* @Author: ~光~~
* @Date: 2024-01-08 17:24:13
* @LastEditTime: 2024-01-08 17:38:10
* @LastEditors:
*/
#include
#include
#include
int main(int argc, char *argv []){
FILE *fp1,*fp2;
char ch;
if((fp1=fopen(argv[1],"r"))==NULL){
fprintf(stderr, "Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
if((fp2=fopen(argv[2],"w+"))==NULL ){
fprintf(stderr, "Can't open %s\n", argv[2]);
exit(EXIT_FAILURE);
}
while((ch = getc(fp1))!=EOF){
fprintf(fp2,"%c",ch);
//putc(ch,fp2);
}
fclose(fp1);
fclose(fp2);
return 0;
}
3.编写一个文件拷贝程序,提示用户输入文本文件名,并以该文件名作为原始文件名和输出文件名。该程序要使用 ctype.h 中的 toupper()函数,在写入到输出文件时把所有文本转换成大写。使用标准I/O和文本模式。
/*
* @Description: 编写一个文件拷贝程序,提示用户输入文本文件名,并以该文件名作
为原始文件名和输出文件名。该程序要使用 ctype.h 中的 toupper()函数,在
写入到输出文件时把所有文本转换成大写。使用标准I/O和文本模式。
* @Author: ~光~~
* @Date: 2024-01-08 17:39:56
* @LastEditTime: 2024-01-08 17:51:12
* @LastEditors:
*/
#include
#include
#include
#include
#define LEN 10
int main(void){
FILE *fp1,*fp2;
char ch;
char name[LEN];
if((fp1=fopen("a.txt","r"))==NULL){
fprintf(stderr, "Can't open %s\n","a.txt");
exit(EXIT_FAILURE);
}
fprintf(stdout,"please enter the output file name:");
fscanf(stdin,"%s",name);//输出的时候是stdin
if((fp2=fopen(name,"w+"))==NULL){
fprintf(stderr, "Can't open %s\n", name);
exit(EXIT_FAILURE);
}
while((ch=getc(fp1))!=EOF){
ch=toupper(ch);
fprintf(fp2,"%c",ch);
}
fclose(fp1);
fclose(fp2);
return 0;
}
4. 编写一个程序,按顺序在屏幕上显示命令行中列出的所有文件。使用argc控制循环。
/*
* @Description: 编写一个程序,按顺序在屏幕上显示命令行中列出的所有文件。使用
argc控制循环。
* @Author: ~光~~
* @Date: 2024-01-08 17:56:17
* @LastEditTime: 2024-01-08 18:03:05
* @LastEditors:
*/
#include
#include
#include
int main(int argc,char *argv[]){
int i;
FILE *fp;
char ch;
if(argc>1){
printf("there are %dth files\n",argc-1);
for(i=1;i<argc;i++){
if((fp=fopen(argv[i],"r"))==NULL){
fprintf(stderr, "Can't open %s\n", argv[i]);
exit(EXIT_FAILURE);
}
while((ch=getc(fp))!=EOF){
putchar(ch);
}
fclose(fp);
fprintf(stdout,"\n%dth file is over\n",i);
printf("\n");
}
}
return 0;
}
5.修改程序清单13.5中的程序,用命令行界面代替交互式界面。
程序清单13.5
/* append.c -- 把文件附加到另一个文件末尾 */
#include
#include
#include
#define BUFSIZE 4096
#define SLEN 81
void append(FILE *source, FILE *dest);
char * s_gets(char * st, int n);
int main(void)
{
FILE *fa, *fs; // fa 指向目标文件,fs 指向源文件
int files = 0; // 附加的文件数量
char file_app[SLEN]; // 目标文件名
char file_src[SLEN]; // 源文件名
int ch;
puts("Enter name of destination file:");
s_gets(file_app, SLEN);
if ((fa = fopen(file_app, "a+")) == NULL)
{
fprintf(stderr, "Can't open %s\n", file_app);
exit(EXIT_FAILURE);
}
if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0)
{
fputs("Can't create output buffer\n", stderr);
exit(EXIT_FAILURE);
}
puts("Enter name of first source file (empty line to quit):");
while (s_gets(file_src, SLEN) && file_src[0] != '\0')
{
if (strcmp(file_src, file_app) == 0)
fputs("Can't append file to itself\n", stderr);
else if ((fs = fopen(file_src, "r")) == NULL)
fprintf(stderr, "Can't open %s\n", file_src);
else
{
if (setvbuf(fs, NULL, _IOFBF, BUFSIZE) != 0)
{
fputs("Can't create input buffer\n", stderr);
continue;
}
append(fs, fa);
if (ferror(fs) != 0)
fprintf(stderr, "Error in reading file %s.\n",file_src);
if (ferror(fa) != 0)
fprintf(stderr, "Error in writing file %s.\n",file_app);
fclose(fs);
files++;
printf("File %s appended.\n", file_src);
puts("Next file (empty line to quit):");
}
}
printf("Done appending.%d files appended.\n", files);
rewind(fa);
printf("%s contents:\n", file_app);
while ((ch = getc(fa)) != EOF)
putchar(ch);
puts("Done displaying.");
fclose(fa);
return 0;
}
// append()函数完成拷贝任务。该函数使用fread()和fwrite()一次拷贝4096
// 字节,而不是一次拷贝1字节:
void append(FILE *source, FILE *dest)
{
size_t bytes;
static char temp[BUFSIZE]; // 只分配一次
while ((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0)
fwrite(temp, sizeof(char), bytes, dest);
}
char * s_gets(char * st, int n)
{
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
find = strchr(st, '\n'); // 查找换行符
if (find) // 如果地址不是NULL,
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
解答部分
#include
#include
#include
#define BUFSIZE 4096
#define SLEN 81
void append(FILE *source, FILE *dest);
char *s_gets(char *st, int n);
int main(int argc, char *argv[])
{
FILE *fa, *fs; // fa 指向目标文件,fs 指向源文件
int files = 0; // 附加的文件数量
char file_app[SLEN]; // 目标文件名
char file_src[SLEN]; // 源文件名
int ch;
if (argc != 2) {
fprintf(stderr, "Usage: %s destination_file\n", argv[0]);
exit(EXIT_FAILURE);
}
strcpy(file_app, argv[1]);
if ((fa = fopen(file_app, "a+")) == NULL)
{
fprintf(stderr, "Can't open %s\n", file_app);
exit(EXIT_FAILURE);
}
if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0)
{
fputs("Can't create output buffer\n", stderr);
exit(EXIT_FAILURE);
}
printf("Enter name of source file (empty line to quit):\n");
while (s_gets(file_src, SLEN) && file_src[0] != '\0')
{
if (strcmp(file_src, file_app) == 0)
fputs("Can't append file to itself\n", stderr);
else if ((fs = fopen(file_src, "r")) == NULL)
fprintf(stderr, "Can't open %s\n", file_src);
else
{
if (setvbuf(fs, NULL, _IOFBF, BUFSIZE) != 0)
{
fputs("Can't create input buffer\n", stderr);
continue;
}
append(fs, fa);
if (ferror(fs) != 0)
fprintf(stderr, "Error in reading file %s.\n", file_src);
if (ferror(fa) != 0)
fprintf(stderr, "Error in writing file %s.\n", file_app);
fclose(fs);
files++;
printf("File %s appended.\n", file_src);
printf("Enter next source file (empty line to quit):\n");
}
}
printf("Done appending. %d files appended.\n", files);
rewind(fa);
printf("%s contents:\n", file_app);
while ((ch = getc(fa)) != EOF)
putchar(ch);
puts("Done displaying.");
fclose(fa);
return 0;
}
void append(FILE *source, FILE *dest)
{
size_t bytes;
static char temp[BUFSIZE]; // 只分配一次
while ((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0)
fwrite(temp, sizeof(char), bytes, dest);
}
char *s_gets(char *st, int n)
{
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
find = strchr(st, '\n'); // 查找换行符
if (find) // 如果地址不是NULL,
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
6.使用命令行参数的程序依赖于用户的内存如何正确地使用它们。重写程序清单 13.2 中的程序,不使用命令行参数,而是提示用户输入所需信息。
⚙️该程序(程序清单13.2)以保留每3个字符中的第1个字符的方式压缩第1个文件的内容。最后,把压缩后的文本存入第2个文件。 第2个文件的名称是第1个文件名加上.red后缀(此处的red代表reduced)。使用命令行参数,同时打开多个文件,以及在原文件名后面加上后缀,都是相当有用的技巧。这种压缩方式有限,但是也有它的用途(很容易把该程序改成用标准 I/O 而不是命令行参数提供文件名)
程序清单 13.2
#include
#include // 提供 exit()的原型
#include // 提供 strcpy()、strcat()的原型
#define LEN 40
int main(int argc, char *argv [])
{
FILE *in, *out; // 声明两个指向 FILE 的指针
int ch;
char name[LEN]; // 储存输出文件名
int count = 0;
// 检查命令行参数
if (argc < 2)
{
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
// 设置输入
if ((in = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "I couldn't open the file \"%s\"\n",
argv[1]);
exit(EXIT_FAILURE);
}
// 设置输出
strncpy(name, argv[1], LEN - 5); // 拷贝文件名
name[LEN - 5] = '\0';
strcat(name, ".red"); // 在文件名后添加.red
if ((out = fopen(name, "w")) == NULL)
{ // 以写模式打开文件
fprintf(stderr, "Can't create output file.\n");
exit(3);
}
// 拷贝数据
while ((ch = getc(in)) != EOF)
if (count++ % 3 == 0)
putc(ch, out);// 打印3个字符中的第1个字符
// 收尾工作
if (fclose(in) != 0 || fclose(out) != 0)
fprintf(stderr, "Error in closing files\n");
return 0;
}
解答部分
#include
#include // 提供 exit()的原型
#include // 提供 strcpy()、strcat()的原型
#define LEN 40
int main(void)
{
FILE *in, *out; // 声明两个指向 FILE 的指针
int ch;
char name1[LEN],name2[LEN]; // 储存输出文件名
int count = 0;
printf("please enter the first file name:");
scanf("%s",name1);
// 设置输入
if ((in = fopen(name1, "r")) == NULL)
{
fprintf(stderr, "I couldn't open the file \"%s\"\n",
name1);
}
// 设置输出
strncpy(name2, name1,LEN-5); // 拷贝文件名
name2[LEN - 5] = '\0';
strcat(name2, ".red"); // 在文件名后添加.red
if ((out = fopen(name2, "w")) == NULL)
{ // 以写模式打开文件
fprintf(stderr, "Can't create output file.\n");
exit(EXIT_FAILURE);
}
// 拷贝数据
while ((ch = getc(in)) != EOF)
if (count++ % 3 == 0)
putc(ch, out);// 打印3个字符中的第1个字符
// 收尾工作
if (fclose(in) != 0 || fclose(out) != 0)
fprintf(stderr, "Error in closing files\n");
return 0;
}
7.编写一个程序打开两个文件。可以使用命令行参数或提示用户输入文件名。
1️⃣该程序以这样的顺序打印:打印第1个文件的第1行,第2个文件的第1行,第1个文件的第2行,第2个文件的第2行,以此类推,打印到行数较多文件的最后一行。
2️⃣修改该程序,把行号相同的行打印成一行。
/*
* @Description: 编写一个程序打开两个文件。可以使用命令行参数或提示用户输入文
件名。
a.该程序以这样的顺序打印:打印第1个文件的第1行,第2个文件的第1
行,第1个文件的第2行,第2个文件的第2行,以此类推,打印到行数较多文
件的最后一行。
b.修改该程序,把行号相同的行打印成一行。
* @Author: ~光~~
* @Date: 2024-01-08 18:40:29
* @LastEditTime: 2024-01-10 16:52:27
* @LastEditors:
*/
#include
#include
#include
#define LEN 40
void function1(FILE *fp1,FILE *fp2);
void function2(FILE *fp1,FILE *fp2);
char *s_gets(char *s,int n,FILE *fp);
int main(int argc ,char *argv[]){
char name1[LEN],name2[LEN];
FILE *fp1,*fp2;
char ch;
if(argc>1){
strcpy(name1,argv[1]);
strcpy(name2,argv[2]);
}else{
printf("please enter the file1 name:");
scanf("%s",name1);
printf("please enter the file2 name:");
scanf("%s",name2);
}
if((fp1=fopen(name1,"r"))==NULL){
fprintf(stderr, "Can't create output file.\n");
exit(EXIT_FAILURE);
}else{
printf("there are the content of file1\n");
while((ch=getc(fp1))!=EOF){
putchar(ch);
}
}
printf("\n");
if((fp2=fopen(name2,"r"))==NULL){
fprintf(stderr, "Can't create output file.\n");
exit(EXIT_FAILURE);
}else{
printf("there are the content of file2\n");
while((ch=getc(fp2))!=EOF){
putchar(ch);
}
}
printf("\n");
printf("\nfuntion 1\n");
rewind(fp1);
rewind(fp2);
function1(fp1,fp2);
printf("\nfuntion 2\n");
rewind(fp1);
rewind(fp2);
function2(fp1,fp2);
fclose(fp1);
fclose(fp2);
return 0;
}
void function1(FILE *fp1,FILE *fp2){
int count=1,flag1=1,flag2=1;
char line2[LEN],line1[LEN];
do{
if((fgets(line1,LEN,fp1))!=NULL) fputs(line1,stdout);
else flag1=0;
if((fgets(line2,LEN,fp2))!=NULL) fputs(line2,stdout);
else flag2=0;
} while (flag1==1 || flag2==1);
}
void function2(FILE *fp1,FILE *fp2){
//fp1 在前 fp2 在后
char line1[LEN],line2[LEN];
int flag1=1,flag2=1;
do{
if((s_gets(line1,LEN,fp1))!=NULL){
flag1=1;
}else flag1=0;
if((s_gets(line2,LEN,fp2))!=NULL) {
strcat(line1,line2);
fputs(line1,stdout);
}else flag2=0;
printf("\n");
}while(flag1==1 || flag2==1);
}
char *s_gets(char *s, int n, FILE *fp) {
char *real;
char *find;
char c;
real = fgets(s, LEN, fp);
if (real) { // 即ret_val != NULL
find = strchr(s, '\n');
if (find) {
*find = '\0';
} else {
while (c=getchar() != '\n'&&c!=EOF) continue;
}
return real;
} else if (feof(fp)) { // 文件结束
return NULL;
} else {
return NULL;
}
}
8.编写一个程序,以一个字符和任意文件名作为命令行参数。如果字符后面没有参数,该程序读取标准输入;否则,程序依次打开每个文件并报告每个文件中该字符出现的次数。文件名和字符本身也要一同报告。程序应包含错误检查,以确定参数数量是否正确和是否能打开文件。如果无法打开文件,程序应报告这一情况,然后继续处理下一个文件。
/*
* @Description: 编写一个程序,以一个字符和任意文件名作为命令行参数。如果字符
后面没有参数,该程序读取标准输入;否则,程序依次打开每个文件并报告
每个文件中该字符出现的次数。文件名和字符本身也要一同报告。程序应包
含错误检查,以确定参数数量是否正确和是否能打开文件。如果无法打开文件,
程序应报告这一情况,然后继续处理下一个文件。
* @Author: ~光~~
* @Date: 2024-01-09 09:26:07
* @LastEditTime: 2024-01-09 10:39:59
* @LastEditors:
*/
#include
#include
#include
#define LEN 20
void cnt(char s[],char st);
int main(int argc,char *argv[]){
FILE *fp;
char name[LEN];
char line[LEN];
int i,j,count=0;
if(argc==2){
fprintf(stdout,"please enter:");
fscanf(stdin,"%s",name);
cnt(name,argv[1][0]);
}else if(argc>=3){
for(i=2;i<argc;i++){
cnt(argv[i],argv[1][0]);
}
}else{
fprintf(stderr, "no enough file\n");
exit(EXIT_FAILURE);
}
return 0;
}
void cnt(char s[],char st){
int count=0,i,j;
char line[LEN];
FILE *fp;
printf("st is %c\n",st);
if((fp=fopen(s,"r"))==NULL){
fprintf(stderr, "Can't create output file.\n");
exit(EXIT_FAILURE);
}
while(fgets(line,LEN,fp)!=NULL){
for(j=0;line[j]!='\0';j++){
if(line[j]-st==0){
fputs(line,stdout);
count++;
}
}
}
fclose(fp);
if(count>0){
printf("\n%c appear in %s for %dth\n",st,s,count);
}
}
9. 修改程序清单 13.3 中的程序,从 1 开始,根据加入列表的顺序为每个单词编号。当程序下次运行时,确保新的单词编号接着上次的编号开始。
程序清单 13.3
/* addaword.c -- 使用 fprintf()、fscanf() 和 rewind() */
#include
#include
#include
#define MAX 41
int main(void)
{
FILE *fp;
char words[MAX];
if ((fp = fopen("wordy.txt", "a+")) == NULL)
{
fprintf(stdout, "Can't open \"wordy\" file.\n");
exit(EXIT_FAILURE);
}
puts("Enter words to add to the file; press the #");
puts("key at the beginning of a line to terminate.");
while ((fscanf(stdin, "%40s", words) == 1) && (words[0] != '#'))
fprintf(fp, "%s\n", words);
puts("File contents:");
rewind(fp); /* 返回到文件开始处 */
while (fscanf(fp, "%s", words) == 1)
puts(words);
puts("Done!");
if (fclose(fp) != 0)
fprintf(stderr, "Error closing file\n");
return 0;
}
解答部分
#include
#include
#include
#define MAX 41
int main(void)
{
FILE *fp;
char words[MAX];
char line[MAX];
int count = 1;
if ((fp = fopen("wordy.txt", "a+")) == NULL)
{
fprintf(stdout, "Can't open \"wordy\" file.\n");
exit(EXIT_FAILURE);
}
puts("Enter words to add to the file; press the #");
puts("key at the beginning of a line to terminate.");
rewind(fp); /* 返回到文件开始处 */
while (fscanf(fp, "%s", words) == 1)
count++;
fseek(fp, 0, SEEK_END); /* 定位到文件末尾 */
while ((fscanf(stdin, "%40s", words) == 1) && (words[0] != '#'))
{
fprintf(fp, "%d. %s\n", count++, words);
}
puts("File contents:");
rewind(fp); /* 返回到文件开始处 */
while((fgets(line,MAX,fp))!=NULL){
fputs(line,stdout);
}
puts("Done!");
if (fclose(fp) != 0)
fprintf(stderr, "Error closing file\n");
return 0;
}
10.编写一个程序打开一个文本文件,通过交互方式获得文件名。通过一个循环,提示用户输入一个文件位置。然后该程序打印从该位置开始到下一个换行符之前的内容。用户输入负数或非数值字符可以结束输入循环。
/*
* @Description: 编写一个程序打开一个文本文件,通过交互方式获得文件名。通过
一个循环,提示用户输入一个文件位置。然后该程序打印从该位置开始到下一个换行符之前的内容。
用户输入负数或非数值字符可以结束输入循环。
* @Author: ~光~~
* @Date:
* @LastEditTime: 2024-01-10 21:23:06
* @LastEditors:
*/
#include
#include
#define MAX 40
int main(void){
FILE *fp;
int position=1;
char ch;
char name[MAX];
char path[MAX];
printf("please enter the file name :");
scanf("%s",name);
if((fp=fopen(name,"r"))==NULL){
fprintf(stdout, "Can't open the file.\n");
exit(EXIT_FAILURE);
}
printf("please enter the position:");
while(scanf("%d",&position) && position>0){
printf("enter the location of the file\n");
fseek(fp,position,SEEK_SET);
printf("the content are:");
while((ch=getc(fp))!='\n') putchar(ch);
printf("\n");
printf("please enter the position:");
fflush(stdin);
}
fclose(fp);
return 0;
}
11. 编写一个程序,接受两个命令行参数。第1个参数是一个字符串,第2个参数是一个文件名。然后该程序查找该文件,打印文件中包含该字符串的所有行。因为该任务是面向行而不是面向字符的,所以要使用fgets()而不是getc()。使用标准C库函数strstr()(11.5.7节简要介绍过)在每一行中查找指定字符串。假设文件中的所有行都不超过255个字符。
/*
* @Description: 编写一个程序,接受两个命令行参数。第1个参数是一个字符串,第
2个参数是一个文件名。然后该程序查找该文件,打印文件中包含该字符串
的所有行。因为该任务是面向行而不是面向字符的,所以要使用fgets()而不
是getc()。使用标准C库函数strstr()(11.5.7节简要介绍过)在每一行中查找
指定字符串。假设文件中的所有行都不超过255个字符。
* @Author: ~光~~
* @Date: 2024-01-10 21:23:44
* @LastEditTime: 2024-01-10 21:31:55
* @LastEditors:
*/
#include
#include
#include
#define MAX 25
int main(int argc, char*argv[]){
FILE *fp;
char line[MAX];
if(argc==3){
if((fp=fopen(argv[2],"r"))==NULL){
fprintf(stdout, "Can't open the file.\n");
exit(EXIT_FAILURE);
}else{
while((fgets(line,MAX,fp))!=NULL){
if((strstr(line,argv[1]))) fputs(line,stdout);
}
}
fclose(fp);
}else{
fprintf(stderr, "out\n");
exit(EXIT_FAILURE);
}
return 0;
}
创建一个文本文件,内含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
#define ROW 20
#define COLUMN 30
int main(void){
char num[20][31]={'0'};
FILE *fp;
int i=0,j=0;
char c;
if((fp=fopen("c.txt","r"))==NULL){
printf("ERROR!\n");
exit(EXIT_FAILURE);
}
while((c=getc(fp))!=EOF){
if(c!=' ' && c!= '\n'){
// printf("%c enter\n",c);
switch(c){
case '0':num[i][j]=' ';
break;
case '1':num[i][j]='.';
break;
case '2':num[i][j]='*';
break;
case '3':num[i][j]='/';
break;
case '4':num[i][j]='-';
break;
case '5':num[i][j]='!';
break;
case '6':num[i][j]='?';
break;
case '7':num[i][j]='=';
break;
case '8':num[i][j]='~';
break;
case '9':num[i][j]='#';
break;
default: num[i][j]=' ';
break;
}
j++;
if(j==30){
i++;
j=0;
}
if(i==20) break;
}
}
fclose(fp);
printf("over!\n");
for(i=0;i<ROW;i++){
for(j=0;j<COLUMN;j++){
printf("%c",num[i][j]);
}
printf("\n");
}
return 0;
}
⚙️13.用变长数组(VLA)代替标准数组,完成编程练习12。
/*
* @Description: 13.用变长数组(VLA)代替标准数组,完成编程练习12。
* @Author: ~光~~
* @Date: 2024-01-11 14:55:18
* @LastEditTime: 2024-01-11 14:57:42
* @LastEditors:
*/
#include
#include
#include
#define ROW 20
#define COLUMN 30
int main(void){
int m=20,n=31;
char num[m][n];
FILE *fp;
int i=0,j=0;
char c;
if((fp=fopen("c.txt","r"))==NULL){
printf("ERROR!\n");
exit(EXIT_FAILURE);
}
while((c=getc(fp))!=EOF){
if(c!=' ' && c!= '\n'){
switch(c){
case '0':num[i][j]=' ';
break;
case '1':num[i][j]='.';
break;
case '2':num[i][j]='*';
break;
case '3':num[i][j]='/';
break;
case '4':num[i][j]='-';
break;
case '5':num[i][j]='!';
break;
case '6':num[i][j]='?';
break;
case '7':num[i][j]='=';
break;
case '8':num[i][j]='~';
break;
case '9':num[i][j]='#';
break;
default: num[i][j]=' ';
break;
}
j++;
if(j==n-1){
i++;
j=0;
}
if(i==m) break;
}
}
fclose(fp);
printf("over!\n");
for(i=0;i<ROW;i++){
for(j=0;j<COLUMN;j++){
// printf("%c",&num[i][j]);
printf("%c",num[i][j]);
}
printf("\n");
}
return 0;
}
⚙️14.数字图像,尤其是从宇宙飞船发回的数字图像,可能会包含一些失真。为编程练习12添加消除失真的函数。该函数把每个值与它上下左右相邻的值作比较,如果该值与其周围相邻值的差都大于1,则用所有相邻值的平均值(四舍五入为整数)代替该值。注意,与边界上的点相邻的点少于4个,所以做特殊处理。
/*
* @Description: 数字图像,尤其是从宇宙飞船发回的数字图像,可能会包含一些失
真。为编程练习12添加消除失真的函数。该函数把每个值与它上下左右相邻
的值作比较,如果该值与其周围相邻值的差都大于1,则用所有相邻值的平
均值(四舍五入为整数)代替该值。注意,与边界上的点相邻的点少于4
个,所以做特殊处理。
* @Author: ~光~~
* @Date: 2024-01-11 14:59:01
* @LastEditTime: 2024-01-11 15:57:40
* @LastEditors:
*/
#include
#include
#include
#define ROW 20
#define COLUMN 30
int compare(int x,int y,int m,int n,int num[m][n]);//x,y是特定左边 m,n是总的坐标
int main(void){
int m=20,n=31;
int num[m][n];
int new[m][n];
FILE *fp;
int i=0,j=0;
char c;
if((fp=fopen("c.txt","r"))==NULL){
printf("ERROR!\n");
exit(EXIT_FAILURE);
}
while((c=getc(fp))!=EOF){
if(c!=' ' && c!= '\n'){
switch(c){
case '0':num[i][j]=0;
break;
case '1':num[i][j]=1;
break;
case '2':num[i][j]=2;
break;
case '3':num[i][j]=3;
break;
case '4':num[i][j]=4;
break;
case '5':num[i][j]=5;
break;
case '6':num[i][j]=6;
break;
case '7':num[i][j]=7;
break;
case '8':num[i][j]=8;
break;
case '9':num[i][j]=9;
break;
default: num[i][j]=0;
break;
}
j++;
if(j==n-1){
i++;
j=0;
}
if(i==m) break;
}
}
fclose(fp);
printf("over!\n");
printf("orignal:\n");
for(i=0;i<m;i++){
for(j=0;j<n-1;j++){
printf("%d",num[i][j]);
}
printf("\n");
}
printf("after:\n");
for(i=0;i<m;i++){
for(j=0;j<n-1;j++){
new[i][j]=compare(i,j,m,n,num);
printf("%d",new[i][j]);
}
printf("\n");
}
return 0;
}
int compare(int x,int y,int m,int n,int num[m][n]){
//x,y是特定左边 m,n是总的坐标
int sum=0,cnt=0,org=0,flag=0;
int avg=0;
org=num[x][y];
//依次判断上下左右是不是合法的
if(x+1<=m-1){
if(org-num[x+1][y]>1) flag=1;
else flag=0;
sum+=num[x+1][y];
cnt+=1;
}
if(x-1>0){
if(org-num[x+1][y]>1) flag=1;
else flag=0;
sum+=num[x-1][y];
cnt++;
}
if(y+1<=n-1){
if(org-num[x+1][y]>1) flag=1;
else flag=0;
sum+=num[x][y+1];
cnt++;
}
if(y-1>0){
if(org-num[x+1][y]>1) flag=1;
else flag=0;
sum+=num[x][y-1];
cnt++;
}
if(flag) return sum/cnt;
else return org;
}
⛵️完成啦~
☘️如果有其他解法~ 欢迎大家讨论 批评指正~
此编程练习参考答案为本人所写,如有错误欢迎大家批评指正~~ 如转载请说明来源~
ok,完结~(●’◡’●) 看到这里 点个赞叭 (●’◡’●)