C Primer Plus (中文版)第13章编程练习 参考答案(仅供参考~)

C Primer Plus (中文版)第13章编程练习 参考答案(仅供参考~)

C Primer Plus第13章编程练习~ 加油加油!
这一章是文件I/O相关 是文件处理相关章节~
一起闪闪发光~⭐️

☘️欢迎大家讨论 批评指正~

文章目录

  • C Primer Plus (中文版)第13章编程练习 参考答案(仅供参考~)
    • 第1题
    • 第2题
    • 第3题
    • 第4题
    • 第5题
    • 第6题
    • 第7题
    • 第8题
    • 第9题
    • 第10题
    • 第11题
    • 第12题
    • 第13题
    • 第14题

第1题

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;
}

第2题

编写一个文件拷贝程序,该程序通过命令行获取原始文件名和拷贝文件名。尽量使用标准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题

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题

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题

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题

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题

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题

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题

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题

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题

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; 
}

第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
#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题

⚙️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题

⚙️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,完结~(●’◡’●) 看到这里 点个赞叭 (●’◡’●)

你可能感兴趣的:(C语言学习,c语言,开发语言)