编辑代码

程序清单13.5 append.c程序
/* append.c -- 把文件附加到另一个文件末尾 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);//从目标文件中读取SLEN个字符串

    if ((fa = fopen(file_app, "a+")) == NULL)//打开目标文件,附加模式
    {
        fprintf(stderr, "Can't open %s\n", file_app);//错误,用Stderr文件流输出所有错误
        exit(EXIT_FAILURE);//结束程序
    }

    if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0)//建立目标文件的缓冲区//_IOFBF全缓冲:对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。
    {
        fputs("Can't create output buffer\n", stderr);//错误,用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')//从源文件中读取SLEN个字符串
    {
        if (strcmp(file_src, file_app) == 0)//比较文件大小,=0前等后,>0前大后,<0前小后//防止打开的是同一个文件
            fputs("Can't append file to itself\n", stderr);//错误,用Stderr文件流输出所有错误
        else if ((fs = fopen(file_src, "r")) == NULL)//如源文件打开失败
            fprintf(stderr, "Can't open %s\n", file_src);//错误,用Stderr文件流输出所有错误
        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;
}


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);//写数据到目标文件,从temp,即读取的总数开始写
}


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'); // 查找换行符,如果未找到该字符则返回 NULL。
        if (find) // 如果地址不是NULL,
            *find = '\0'; // 在此处放置一个空字符
        else
            while (getchar() != '\n')//清除非换行符的值
                continue;//跳出当前循环,再继续下一轮循环,如果用back则跳出整个循环,不再继续了
    }
    return ret_val;
}