C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案

13.1

#include <stdio.h>
#include <stdlib.h>
#define LEN 50

int main(int argc, char *argv[])
{
    int ch;
    FILE *fp;
    unsigned long count = 0;
    char filename[LEN];

    printf("Please enter a filename:\n");
    scanf("%30s", filename);

    if((fp = fopen(filename, "r")) == NULL)
    {
        printf("Can't open %s\n", filename);
        exit(EXIT_FAILURE);
    }

    while((ch = getc(fp)) != EOF)
    {
        putc(ch, stdout);
        count++;//对字符数量进行统计
    }

    fclose(fp);
    printf("file %s has %lu characters\n", filename, count);


    return 0;
}

13.2

#include <stdio.h>
#include <stdlib.h>
#define BUF 512

int main(int argc, char *argv[])
{
    size_t bytes;
    FILE *source;
    FILE *target;
    char temp[BUF];

//第一步判断
    if(argc != 3)
    {
        fprintf(stderr, "本程序文件名:%s.\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if((source = fopen(argv[1], "rb")) == NULL)
    {
        fprintf(stderr, "无法打开%s!\n", argv[1]);
        exit(EXIT_FAILURE);
    }
    if((target = fopen(argv[2], "wb")) == NULL)
    {
        fprintf(stderr,"无法打开%s!\n", argv[2]);
        exit(EXIT_FAILURE);
    }

 //源文件、目标文件都可以打开,开始对源文件读取并写入目标文件
    while((bytes = fread(temp,sizeof(char), BUF, source)) > 0)
    {
        fwrite(temp, sizeof(char), bytes, target);
    }


 //结束,关闭两个文件
    if (fclose(source) != 0)
        {
            fprintf(stderr, "关闭%s文件失败!\n", argv[1]);
        }
        if (fclose(target) != 0)
        {
            fprintf(stderr, "关闭%s文件失败!\n", argv[2]);
        }

    return 0;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案

13.3

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define LEN 50

int main(int argc, char *argv[])
{
    int ch;
    FILE *fp;
    long last = 0;
    long last1 = 0;
    char filename[LEN];//存储我们输入的文件名
    printf("请您输入一个文件名:\n");
    scanf("%30s", filename);//文件已经实际创建好,且已有内容

    if((fp = fopen(filename, "r+")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", filename);
        exit(EXIT_FAILURE);
    }

    while((ch = getc(fp)) != EOF)
    {
        fseek(fp, -1L, SEEK_CUR);//回退一个字节;
        //last = ftell(fp);//辅助判断当前字符坐在位置(建议加上方便理解)
        //printf("last = %lu\n", last);
        putc(toupper(ch), fp);
        fseek(fp, 0L,SEEK_CUR);//改变文件状态,使得下一个字符可以被正常读取;
       // last1 = ftell(fp);//辅助判断当前字符坐在位置
        //printf("last1 = %lu\n", last1);
    }

    rewind(fp);
    printf("%s文件中的所有字符已被转换为大写:\n", filename);
    while((ch = getc(fp)) != EOF)
    {
        putchar(ch);
        /*↑显示到屏幕上检测
                字符是否成功转换为大写*/
    }

    putchar('\n');
    if(fclose(fp) != 0)
    {
        fprintf(stderr,"关闭%s文件失败!\n", filename);
    }
    return 0;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案

13.4

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int i, temp;
    FILE *source;

    if(argc == 1)
    {
        fprintf(stderr,"本程序名是:%s.\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    for(i = 1; i < argc; i++)//i从1开始,去处文件名
    {
        if((source = fopen(argv[i], "r")) == NULL)
        {
            //打开命令行上面的各类文件
            fprintf(stderr, "无法打开%s文件!\n", argv[i]);
            continue;
        }
        while((temp = getc(source)) != EOF)
        {
            //将文件指针指向的以读方式打开的文件内容提取出来
            putchar(temp);
        }

        putchar('\n');
        if (fclose(source) != 0)
        {
          fprintf(stderr, "关闭%s文件失败!\n", argv[i]);
        }
    }

    return 0;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案

13.5

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 4096
#define SLEN 81

void append(FILE *source, FILE *dest);

int main(int argc, char *argv[])
{
    int i, ch;
    int files = 0;
    FILE *fa;
    FILE *fs;

    if(argc < 3)
    {
        printf("Usage: %s appendfile sourcefile.\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    if((fa = fopen(argv[1], "a+")) == NULL)
    {
        fprintf(stderr, "can't open %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }

//打开成功,开始分配缓冲区
    if(setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0)
    {
        //函数自己分配的缓冲区不为0,错误
                 //因为第二个参数buf指向待使用的缓冲区,且值为空,因此会自己分配
                 //操作成功 返回0
        //↑设置缓冲区大小为BUFSIZE;
                //↑_IOFBF表示完全缓冲;
                //↑NULL表示为fa(目标文件)指向的文件分配缓冲区;
        fputs("Can't create output buffer\n", stderr);
        exit(EXIT_FAILURE);
    }

    for(i = 2; i < argc; i++)
    {
        if(strcmp(argv[i], argv[1]) == 0)
        {
            fputs("Can't append file to itself\n", stderr);
             //↑拷贝文件与源文件名对比,防止文件自身附加在文件末尾;
        }
        else if((fs = fopen(argv[i], "r")) == NULL)
        {
            fprintf(stderr, "Can't open %s\n", argv[i]);
        }
        else
        {
            if(setvbuf(fs, NULL, _IOFBF, BUFSIZE) != 0)
            {
                //↑同上一个setvbuf函数所述;
                                //↑本次调用是为fs指向的文件分配缓冲区;
                //拷贝内容的文件缓冲区创建失败就不需要继续执行程序了
                fputs("Can't create input buffer\n", stderr);
                continue;
            }
            append(fs, fa);
            if(ferror(fs) != 0)
            {
                fprintf(stderr, "Error in reading file %s.\n", argv[i]);
            }
            if(ferror(fa) != 0)
            {
                fprintf(stderr, "Error in writing file %s.\n", argv[1]);
            }
            fclose(fs);
            files++;//统计拼接文件次数
            printf("File %s appended.\n", argv[i]);

        }
    }

    printf("Done appending. %d files appended.\n",files);
    rewind(fa);
    printf("文件%s 内容:\n",argv[1]);

    while(ch = getc(fa) != EOF)
    {
        putchar(ch);
    }
    putchar('\n');
    puts("Done displaying.");

    fclose(fa);
    return 0;
}

void append(FILE *source, FILE *dest)
{
    size_t bytes;
    static char temp[BUFSIZE];

    /*fread函数把source指向的
    文件中的BUFSIZE块char类型的
    数据写入temp数组中,返回值是成功
    读取数据块的数量;*/
    while((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0)
    {
        fwrite(temp, sizeof(char), bytes, dest);
        /*↑fwrite函数把temp数组中的
          bytes块char类型的数据写入dest
          指向的文件中,返回值是成功写入数据
          块的数量;*/
    }

    return;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案
.
.

13.6

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 40


int main(int argc, char *argv[])
{

    FILE *in, *out;
    int ch;
    char name[LEN];
    int count = 0;
    char temp[LEN];

    printf("Please enter a filename:\n");
    scanf("%39s", temp);//我们已经创建好的文件名

    if((in = fopen(temp, "r")) == NULL)
    {
        fprintf(stderr, "I could't open the file \"%s\"\n", temp);
        exit(EXIT_FAILURE);
    }
    //↓拷贝文件名;
    strncpy(name, temp, LEN - 5);
    name[LEN - 5] = '\0';
    //↓在文件名后面添加.red
    strcat(name, ".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)//3个字符切换一行
        {
            putc(ch, out);
             //↑将字符输出到out文件指针所指文件中去
        }
    }
    if (fclose(in) != 0 || fclose(out) != 0)
    {
        fprintf(stderr, "Error in closing files\n");
    }
    return 0;
}

.
.

13.7(1) :a、错行打印1文件和2文件内容

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *fp;
    FILE *ft;
    int i, j, ch, ct;
    i = j = 1;

    if(argc != 3)
    {
        fprintf(stderr, "本程序名是:%s.\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    if((fp = fopen(argv[1], "r")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", argv[1]);
        exit(EXIT_FAILURE);
    }
    if((ft = fopen(argv[2], "r")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", argv[2]);
        exit(EXIT_FAILURE);
    }

    ch = getc(fp);//←读取第一个文件的第一个字符;
    ct = getc(ft);

//每行循环一次
    while((ch != EOF) || (ct != EOF))//其中一个没有遇到文件结尾就继续进入循环
    {
        if(ch != EOF)
        {
            printf("打印第1个文件第%d行:\n", i++);
        }
        while((ch != EOF) && (ch != '\n'))
        {
            putchar(ch);//此时输出的是上述第一个字符
            ch = getc(fp);
            //↑获取下一个字符,读取第一个文件下一个字符;
        }
        //↓若读取到换行符时执行此块语句
        if(ch != EOF)
        {
            putchar('\n');
            /*换行后,先获取字符,这里先进入下面ct的代码,
             *此处获取的字符在下一次循环中进入while,
             *将字符输出*/
            ch = getc(fp);
        }


        if(ct != EOF)
        {
            printf("打印第2个文件第%d行:\n", j++);
        }
        while((ct != EOF) && (ct != '\n'))
        {
            putchar(ct);
            ct = getc(ft);
            //↑读取第二个文件下一个字符;
        }
        if(ct != EOF)
        {
            putchar('\n');
            ct = getc(ft);
        }
    }

    if (fclose(fp) != 0)
    {
        fprintf(stderr, "关闭%s文件失败!\n", argv[1]);
    }
    if (fclose(ft) != 0)
    {
        fprintf(stderr, "关闭%s文件失败!\n", argv[2]);
    }


    exit(0);
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案
.
.

13.7(b):两个文件的相同行号打印到一起,再换行

  1. 对两个while循环(ch\ct的)逻辑顺序的理解,不然容易搞混
  2. 此处是相同行一起输出,因此只需要一个换行符‘\n’即可
  3. 同样需要对命令行上的文件,进行能否打开进行读写操作的判断
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *fp;
    FILE *ft;
    int ch, ct, count;
    count = 1;

    if (argc != 3)
    {
        fprintf(stderr, "本程序名是:%s.\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", argv[1]);
        exit(EXIT_FAILURE);
    }
    if ((ft = fopen(argv[2], "r")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", argv[2]);
        exit(EXIT_FAILURE);
    }
    ch = getc(fp);
    ct = getc(ft);
    while ((ch != EOF) || (ct != EOF))
    {
        printf("打印2文件第%d行:\n", count++);
        while ((ch != EOF) && (ch != '\n'))
        {

            putc(ch, stdout);
            ch = getc(fp);
            putchar('\n');/*1.4号测试,
                           需在这里加上'\n'才会先打印1文件,
                           再跟着2文件内容*/
        }
        if (ch != EOF)
        {
             //puts("3");
            if (ct == EOF)
            {
                //↑若遇到第二个文件EOF则换行;
                putchar('\n');
            }
            else
            {
                 //puts("4");
                putchar(' ');
                //↑打印空格隔开2个文件内容;
            }
            ch = getc(fp);
        }
        while ((ct != EOF) && (ct != '\n'))
        {
             //puts("5");
            putc(ct, stdout);
            ct = getc(ft);
        }
        if (ct != EOF)
        {
             //puts("6");
            putchar('\n');//两个文件相同行放到一起打印了,ch就不需要进行换行操作,在ct这里换行即可
            ct = getc(ft);
        }
        putchar('\n');
    }
    if (fclose(fp) != 0)
    {
        fprintf(stderr, "关闭%s文件失败!\n", argv[1]);
    }
    if (fclose(ft) != 0)
    {
        fprintf(stderr, "关闭%s文件失败!\n", argv[2]);
    }

    return 0;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案

13.8

  1. 对不同命令行进行判断
  2. 在命令行==2时,输入的终止条件与多命令行时不可以相同
  3. argc ==2和argc >2时,文件指针的接收不同
  4. 多个命令行的循环条件要注意
  5. 单个字符的提取,使用多维数组辅以理解运用 : ch = argv[1][0],命令行第二行就算是一个“字符”,也算是一个字符串“a”,单独截取后,才成为一个字符’a’(此时是第二行第一个字符)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int search(int ch, FILE *fp);
int search2(int ch, FILE*fp);

int main(int argc, char *argv[])
{
    FILE *fp;
    int i, ch, ct;
    int count = 0;

    if(argc < 2)
    {
        fprintf(stderr,"本程序名是:%s.\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    if(strlen(argv[1]) != 1)
    {
        fprintf(stderr, "第二个命令行参数必须是一个字符!\n");
         //英文占一个字节,中文字符占两个字节
        exit(EXIT_FAILURE);
    }

    if(argc == 2)
    {
        puts("进入命令行只有两个的程序中:");
        fp = stdin;//从键盘输入
        ch = argv[1][0];
         //↑argv[1]命令行第二行,[0]第二行字符串的子一个字符

        printf("请您输入字符串(遇EOF退出):\n");
        count = search2(ch, fp);
         //↑此处判断不能再是EOF时停止,需是‘\n’换行符时停止(因为不再是文件,没有结束标志)
        printf("字符%c总共出现了%d次.\n", ch, count);

    }
    else if(argc > 2)
    {
        puts("进入命令行有多个的程序中:");
        ch = argv[1][0];
        for(i = 2; i < argc; i++)
        {
            puts("3");
            if((fp = fopen(argv[i], "r")) == NULL)
            {
                fprintf(stderr, "无法打开%s文件!\n", argv[i]);
                continue;
            }
            printf("%s文件中的内容是:\n", argv[i]);
            while((ct = getc(fp)) != EOF)
            {
                putchar(ct);
            }

            rewind(fp);
            count = search(ch, fp);
            printf("字符%c在%s文件中总共出现了%d次.\n", ch, argv[i], count);

            if (fclose(fp) != 0)
            {
                fprintf(stderr, "关闭%s文件失败!\n", argv[i]);
            }

        }
    }


    return 0;
}

int search(int ch, FILE*fp)
{
    int find;
    int n = 0;
    while((find = getc(fp)) != EOF)
    {
        if(ch == find)
        {
            n++;

        }
    }
    return n;
}

int search2(int ch, FILE*fp)
{
    int find;
    int n = 0;
    while((find = getc(fp)) != '\n')
    {
        if(ch == find)
        {
            n++;

        }
    }
    return n;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案
.
.

13.9

#include <stdio.h>
#include <stdlib.h>
#define MAX 41

int main(void)
{
    FILE *fp;
    int ct = 0;
    char words[MAX];

    if((fp = fopen("wordy", "a+")) == NULL)
    {
        fprintf(stdout, "Can't open \"wordy\" file.\n");
        exit(EXIT_FAILURE);
    }

    while(fgets(words, MAX, fp) != NULL)
    {
        puts("文件存在内容-");
        ct++;//若文件之前存在且有内容,进行统计
    }
    rewind(fp);
    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] != '#'))
    {
        puts("内容输入⬆");
        fprintf(fp, "%-3d : %s\n", ++ct, words);
         //将统计的次数(包含此前次数的统计)、数组中的内容一起输入到文件中
    }
     puts("文件目录:");
     rewind(fp);
     while(fgets(words, MAX, fp)!= NULL)
     {
         puts("内容输出--");
         fputs(words, stdout);

     }
     puts("done!");
     if(fclose(fp) != 0)
     {
         fprintf(stderr, "Error in closing file\n");

     }

    return 0;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案
C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案
C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案
.
.

13.10

#include <stdio.h>
#include <stdlib.h>
#define LEN 50

int main(int argc, char *argv[])
{
    int ch;
    FILE *fp;
    long int number;
    char filename[LEN];


    printf("请您输入一个文件名:\n");
    scanf("%49s", filename);

    if((fp = fopen(filename, "r")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", filename);
        exit(EXIT_FAILURE);
    }
     printf("请输入一个文件位置(<0或q退出):");
     while((scanf("%ld", &number)) == 1 && (number > 0))
     {
         fseek(fp, number, SEEK_CUR);//定位到当前number所在位置
         while(((ch = getc(fp)) != '\n') && (ch != EOF))
         {
             /*↓打印从该位置开始到
                下一个换行符之前的内容;*/
             putchar(ch);
         }
         if(ch == EOF)
         {
             printf("此位置已遇到EOF!\n");
             break;
         }
         printf("\n您可以再次输入一个文件位置(<0或q退出):");
     }

     printf("本程序完成!\n");
     if (fclose(fp) != 0)
     {
         fprintf(stderr, "关闭%s文件失败!\n", filename);
     }
    exit(0);
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案
.
.

13.11

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 256

int main(int argc, char *argv[])
{
    FILE *fp;
    char temp[LEN];
    char *pt;

    if (argc != 3)
    {
        fprintf(stderr, "本程序名是:%s.\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if((fp = fopen(argv[2], "r")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", argv[2]);
        exit(EXIT_FAILURE);
    }

    printf("打印%s文件中包含%s字符串的所有行:\n", argv[2], argv[1]);
    while((fgets(temp, LEN, fp)) != NULL)
    {
       pt =  strstr(temp, argv[1]);
       if(pt)
       {
           fputs(temp, stdout);
       }
    }
    putchar('\n');

    if(fclose(fp) != 0)
    {
        fprintf(stderr, "关闭%s文件失败!\n", argv[2]);
    }

    return 0;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案

13.12

  理解 :若文件指针fp已指向一个已打开的文本文件,a、b分别为整型变量,则以下语句从fp所指的文件中读入两个整数放入变量a和b中:fscanf(fp, “%d%d”,&a,&b);注意:文件中的两个整数之间用空格(或跳格符、回车符)隔开。

        b[row][col] = trans[a[row][col]];
         //↑进行数字对应的字符转换;
         /*trans数组可以将多维数组a当作参数,相当于
          *把多维数组a的每行每列的元素下标对应的数据,
          *与trans数组中的对应元素下标中的数据对应,
          *相同位进行替换*/
#include <stdio.h>
#include <stdlib.h>
#define ROWS 20
#define COLS 30
#define LEVELS 10
#define LEN 50



const char trans[LEVELS + 1] = " .':~*=&%#";//存储需要转换的字符;
void change(int (*a)[COLS], char (*b)[COLS], int rows);//int (*a)[COLS]多维数组的首地址
void showarray(int (*figure)[COLS],int rows);


int main(void)
{
    int row, col;
    FILE *infile;
    char filename[LEN];
    int figure[ROWS][COLS];
    char picture[ROWS][COLS];

    puts("请输入一个文件名:");
    scanf("%49s", filename);

    if((infile = fopen(filename, "r")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", filename);
        exit(EXIT_FAILURE);
    }

    for(row = 0; row < ROWS; row++)
    {
        for(col = 0; col < COLS; col++)
        {
            fscanf(infile, "%d", &figure[row][col]);
            //↑从文件中读取数字,按照‘%s‘格式输入到二维数组中去
        }
    }
    showarray(figure,ROWS);
    putchar('\n');

    if(ferror(infile))
    {
        fprintf(stdout, "进行读或写文件时出现错误!\n");
        exit(EXIT_FAILURE);
    }

    change(figure, picture, ROWS);//一行一行进行交互
    printf("%s文件中的数字成功转换成图片如下:\n", filename);

//交互完成,进行输出展示
    for(row = 0; row < ROWS; row++)
    {
        for(col = 0; col < COLS; col++)
        {
            putchar(picture[row][col]);
        }
        putchar('\n');//每输出一行进行一次换行
    }


    fseek(infile, 0L, SEEK_END);
    putc('\n', infile);
    //↓将结果存储到文本文件中;
    for(row = 0; row < ROWS; row++)
    {
        for(col = 0; col < COLS; col++)
        {
            fprintf(infile, "%c", picture[row][col]);
        }
        putc('\n', infile);//每行末尾添加一个换行符

    }

    if(fclose(infile) != 0)
    {
        fprintf(stderr, "关闭%s文件失败!\n", filename);
    }

    exit(0);
}


void change(int (*a)[COLS], char (*b)[COLS], int rows)
{
    int row, col;

    for(row = 0; row < ROWS; row++)
    {
        for(col = 0; col < COLS; col++)
        {
            b[row][col] = trans[a[row][col]];
             //↑进行数字对应的字符转换;
             /*trans数组可以将多维数组a当作参数,相当于
              *把多维数组a的每行每列的元素下标对应的数据,
              *与trans数组中的对应元素下标中的数据对应,
              *相同位进行替换*/
        }

    }
    return;
}

void showarray(int (*figure)[COLS],int rows)
{
    int row, col;
    for(row = 0; row < rows; row++)
    {
        for(col = 0; col < COLS; col++)
        {
            printf("%d", figure[row][col]);
        }
        putchar('\n');
    }
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案
.
.

13.14

额外添加 :且将转换后的图片按照%c的格式发送到另一个txt文件中去

#include <stdio.h>
#include <stdlib.h>
#define ROWS 20
#define COLS 30
#define LEVELS 10
#define LEN 50
#define BUFSIZE 10000

int clean_distortian(int (*a)[COLS], int rows, int x, int y);
void change(int (*a)[COLS], char (*b)[COLS], int rows);

const char trans[LEVELS + 1] = " .':~*=&%#";//存储需要转换的字符;

int main(void)
{
    int row, col;
    FILE *infile;
    FILE *fp;
    char filename[LEN];
    int figure[ROWS][COLS];
    char picture[ROWS][COLS];

    printf("请输入一个文件名:\n");
    scanf("%49s", filename);
    if((infile = fopen(filename, "r+")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", filename);
        exit(EXIT_FAILURE);
    }
    if((fp = fopen("filename.txt", "a+")) == NULL)
    {
        fprintf(stderr, "无法打开%s文件!\n", filename);
        exit(EXIT_FAILURE);
    }
    else
    {
        puts("filename.txt创建成功。");
    }
    putchar('\n');


    if(setvbuf(infile, NULL, _IOFBF, BUFSIZE) != 0)
    {
        //函数自己分配的缓冲区不为0,错误
        fputs("can't create output file.\n", stderr);
        exit(EXIT_FAILURE);
    }

    for(row = 0; row < ROWS; row++)
    {
        for(col = 0; col < COLS; col++)
        {
            fscanf(infile, "%d", &figure[row][col]);
             //↑从文件中读取数字,按照%d的格式;
        }
    }

    if(ferror(infile))
    {
        fprintf(stderr, "进行读或写%s文件时出现错误!\n", filename);
        exit(EXIT_FAILURE);
    }

    for(row = 0; row < ROWS; row++)
    {
        for(col = 0; col < COLS; col++)
        {
            figure[row][col] = clean_distortian(figure, ROWS, row, col);
                                //多维数组的每一行的上下左右
            //将计算过后的所有相邻值的平均值 赋值 给原数组中的元素
        }
    }

    change(figure, picture, ROWS);
     //对应数字类型进行图片转换

    printf("%s文件中的数字成功转换成图片如下:\n", filename);
    for(row = 0; row < ROWS; row++)
    {
        for(col = 0; col < COLS; col++)
        {
            putchar(picture[row][col]);
        }
        putchar('\n');
    }
    fseek(infile, 0L, SEEK_END);
    putc('\n', infile);

    for (row = 0; row < ROWS; row++)
    {
        for (col = 0; col < COLS; col++)
        {
            fprintf(fp, "%c", picture[row][col]);
            //将picture数组输入到新的文件中去
        }
        putc('\n', fp);
    }

    if (fclose(infile) != 0)
    {
        fprintf(stderr, "关闭%s文件失败!\n", filename);
    }
    if (fclose(fp) != 0)
    {
        fputs( "关闭filename.txt文件失败!\n", stderr);
    }

    return 0;
}


int clean_distortian(int (*a)[COLS], int rows, int x, int y)
{
    int average;
        //用于四舍五入的中间局部变量;

/*与边界上的点相邻的点少于4个,所以做特殊处理。*/
    if(x == 0) //←矩形的上边
    {
        if(y == 0)//←矩形左上顶点;
        {
            if((a[x][y] - a[x][y + 1]) > 1 && (a[x][y] - a[x + 1][y]) > 1)
            {
                average =( (a[x][y + 1] + a[x + 1][y]) / 2.0 + 0.5 );
                //四舍五入公式;
                //计算的左上角顶点的右边、下边的平均值
                return average;
            }
        }
        if(y == COLS -1)//←矩形右上顶点;(-1 :减去'\n')
        {
            if((a[x][y] - a[x][y - 1]) > 1 && (a[x][y] - a[x + 1][y]) > 1)
            {
                average =( (a[x][y - 1] + a[x + 1][y]) / 2.0 + 0.5 );
                //四舍五入公式;
                //计算的右上顶点的zuo边、下边的平均值
                return average;
            }
        }
        //↓矩形的上边除了顶点之外的点;
        if((a[x][y] - a[x][y - 1]) > 1 && (a[x][y] - a[x][y + 1]) > 1 && (a[x][y] - a[x + 1][y]) > 1)
        {
            average = ((a[x][y - 1] + a[x][y + 1] + a[x + 1][y]) / 3.0 + 0.5);
            return average;
        }
    }
    else if(x == rows -1)//←矩形的下边;矩形的最后一行
    {
        if(y == 0)
        {
            //↑矩形左下顶点;
            if ((a[x][y] - a[x - 1][y]) > 1 && (a[x][y] - a[x][y + 1]) > 1)
            {
                average = ((a[x - 1][y] + a[x][y + 1]) / 2.0 + 0.5);
                return average;
            }
        }
        if(y == COLS - 1)
        {
            //↑矩形右下顶点;
            if ((a[x][y] - a[x][y - 1]) > 1 && (a[x][y] - a[x - 1][y]) > 1)
            {
                average = ((a[x][y - 1] + a[x - 1][y]) / 2.0 + 0.5);
                return average;
            }
        }
        //↓矩形的下边除了顶点之外的点;
        if ((a[x][y] - a[x][y - 1]) > 1 &&
            (a[x][y] - a[x][y + 1]) > 1 &&
            (a[x][y] - a[x - 1][y]) > 1)
        {
            average = ((a[x][y - 1] + a[x][y + 1] + a[x - 1][y]) / 3.0 + 0.5);
            return average;
        }

    }
    if(y == 0)//←矩形的左边除了顶点之外的点;第1列的所有点
    {
        if ((a[x][y] - a[x - 1][y]) > 1 &&
            (a[x][y] - a[x + 1][y]) > 1 &&
            (a[x][y] - a[x][y + 1]) > 1) //上、下、右
        {
            average = ((a[x - 1][y] + a[x + 1][y] + a[x][y + 1]) / 3.0 + 0.5);
            return average;
        }
    }
    else if(y == COLS - 1)//←矩形的右边除了顶点之外的点;最后一列的所有点
    {
        if ((a[x][y] - a[x - 1][y]) > 1 &&
            (a[x][y] - a[x + 1][y]) > 1 &&
            (a[x][y] - a[x][y - 1]) > 1)//上、下、左
        {
            average = ((a[x - 1][y] + a[x + 1][y] + a[x][y - 1]) / 3.0 + 0.5);
            return average;
        }
    }

/*正常处理剩余的点。上、下、左、右*/
    if((a[x][y] - a[x + 1][y]) > 1 && a[x][y] - a[x - 1][y] > 1
            && a[x][y] - a[x][y - 1] && a[x][y] - a[x][y + 1] > 1)
    {
        average = ((a[x - 1][y] + a[x + 1][y] + a[x][y - 1] + a[x][y + 1]) / 4.0 + 0.5);
        return average;
    }

    return a[x][y];//←以上条件都不符合则返回原值;

}

void change(int (*a)[COLS], char (*b)[COLS], int rows)
{
    int row, col;

    for (row = 0; row < ROWS; row++)
    {
        for (col = 0; col < COLS; col++)
        {
            b[row][col] = trans[a[row][col]];
             //↑进行数字对应的字符转换;
        }
       // putchar('\n');
    }
    return;
}

C Primer Plus 第六版(中文版)第十三章(完美版---》加个人注释)编程练习答案

上一篇:从零开始用PYTHON写一个抓取联想SR650的MEC数值


下一篇:某生鲜App 签名计算方法 脱个壳试试