用c语言将一个文件中的行向后复制到另一个文件中

用c语言将一个文件中的行向后复制到另一个文件中,c,C,我正在尝试以相同的权限、相同的大小、相同的所有内容复制到另一个文件(新),我这样做了,但复制内容正常,但现在尝试向后复制(新文件的最后一行是第一行),我如何计划这一点,首先获取文件的行数,如下所示: while (!feof(fp)) { ch = fgetc(fp); if (ch == '\n') { lines++; } } 然后创建一个数组来放置文件中的每一行,一旦我用for for (unsigned i = n; i-- > 0;) {

我正在尝试以相同的权限、相同的大小、相同的所有内容复制到另一个文件(新),我这样做了,但复制内容正常,但现在尝试向后复制(新文件的最后一行是第一行),我如何计划这一点,首先获取文件的行数,如下所示:

while (!feof(fp)) {
    ch = fgetc(fp);
    if (ch == '\n') {
        lines++;
    }
}
然后创建一个数组来放置文件中的每一行,一旦我用
for

for (unsigned i = n; i-- > 0;) {
    //n is the number of lines
}
那么在这个
上,对于
我写入一个文档,然后它将被向后写入,有更好的选择吗


如果是的话,你能给我举个例子吗?

我不能在这里写完整的代码,因为你似乎在设计上有很多问题

但你应该能够通过以下方式做你想做的事:

  • 使用大的
    read
    fread
  • 使用
    strchr
    strtok
    (更简单,但需要注意)查找所有换行符,将它们的位置存储到指针数组中(
    realloc
    如果您不知道前面有多少行,则是您的朋友)
  • 最后,通过指针数组向后写入每个字符串,指针之间有换行符(使用
    write
    fwrite
    )(您需要记住某个变量中的行数)
  • 请注意,我已经提到了用于步骤2的两个可能的库函数<代码>strtok可能是最容易使用的函数,但是有一些警告,例如忽略空行、不具有线程安全性以及修改输入参数,因此我只会在快速破解时使用它


    因此,如果您希望程序尽可能正常工作,则更适合
    strchr
    。然而,这将稍微难以使用。最重要的是,您需要记住每次依次调用它,以便在最后一次调用它的结果之后在char上调用它,并确保对字符串的结尾执行null检查。此外,您还需要确保在将行写回时只写到下一个换行符,因为
    strchr
    不会将它们替换为空字符。

    对于具有中等长度行的中等大小文件,下面是一个快速而肮脏的递归实现:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void) {
        static char buf[10000];
        if (fgets(buf, sizeof(buf), stdin)) {
            char *str = strdup(buf);
            main();
            fputs(str, stdout);
            free(str);
        }
        return 0;
    }
    
    #包括
    #包括
    #包括
    内部主(空){
    静态字符buf[10000];
    if(fgets(buf、sizeof(buf)、stdin)){
    char*str=strdup(buf);
    main();
    fput(str、stdout);
    自由基(str);
    }
    返回0;
    }
    
    这是一个非常简单的过滤器:它从标准输入读取文件,并将行以相反的顺序写入标准输出

    现在,由于您没有进行任何编码,您的任务将是识别这种方法的潜在问题。

    • 将文件读入内存(如果适合…)
    • 反转整个文件(按字符)
    • 反转结果行中的字符
    • 写文件
    • 请不要重新格式化。我有权使用不同的缩进样式,我也不喜欢你的

    #包括
    #包括
    #包括
    int main(int argc,字符**argv)
    {
    大小\u t大小、beg、end、this、used;
    char*all=NULL;
    int-ch;
    文件*fp;
    fp=fopen(argv[1],“rb+”);
    如果(!fp){
    perror(“开放式失败”);
    退出(退出失败);
    }
    fprintf(stderr,“读取文件…\n”);
    用于(大小=已使用=0;1;已使用++){
    ch=getc(fp);
    如果(使用+1>=大小){
    大小和新闻大小;
    新闻大小=(大小==0)?1024:大小*2;
    
    fprintf(stderr,“Realloc%zu这里有一种使用
    mmap
    访问文件进行行反转的方法。对于较大的文件应该更快

    我已经测试过了,它似乎可以处理大多数边缘情况

    为了进一步提高速度,可以添加
    madvise
    调用

    旁注:关于
    \u GNU\u源代码
    ,很抱歉。这是为了获得
    memrchr
    的定义。如果您的系统没有该定义,那么创建一个就足够简单了

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    
    #define sysfault(_fmt...) \
        do { \
            fprintf(stderr,_fmt); \
            exit(1); \
        } while (0)
    
    #ifdef DEBUG
    #define dbgprt(_fmt...)     fprintf(stderr,_fmt)
    #else
    #define dbgprt(_fmt...)     /**/
    #endif
    
    typedef unsigned char byte;
    
    typedef struct {
        const char *map_file;               // filename
        int map_fd;                         // file descriptor
        size_t map_siz;                     // file size
        byte *map_base;                     // base of map area
        byte *map_ptr;                      // current map pointer
        size_t map_off;                     // current file offset
        struct stat map_st;                 // stat syscall
    } filemap;
    
    // mapopen -- open the file
    void
    mapopen(filemap *map,const char *file,int mode,filemap *mapfm)
    {
        int prot;
        int err;
    
        memset(map,0,sizeof(filemap));
    
        map->map_file = file;
        map->map_fd = open(map->map_file,mode,0644);
        if (map->map_fd < 0)
            sysfault("mapopen: unable to open '%s' -- %s\n",
                map->map_file,strerror(errno));
    
        // create new file
        if (mode & O_CREAT) {
            map->map_siz = mapfm->map_siz;
            err = ftruncate(map->map_fd,map->map_siz);
            if (err < 0)
                sysfault("mapopen: unable to ftruncate -- %s\n",strerror(errno));
            map->map_off = 0;
        }
    
        // process existing file
        else {
            fstat(map->map_fd,&map->map_st);
            map->map_siz = map->map_st.st_size;
            map->map_off = map->map_siz - 1;
            lseek(map->map_fd,map->map_off,0);
        }
    
        prot = 0;
        if (mode & O_CREAT)
            prot |= PROT_WRITE;
        else
            prot |= PROT_READ;
    
        do {
            if (map->map_siz == 0)
                break;
    
            map->map_base = mmap(NULL,map->map_siz,prot,MAP_SHARED,map->map_fd,0);
            if (map->map_base == MAP_FAILED)
                sysfault("mapopen: unable to map map_file='%s' map_siz=%ld -- %s\n",
                    map->map_file,map->map_siz,strerror(errno));
    
            // get starting offset for file
            map->map_ptr = map->map_base + map->map_off;
        } while (0);
    }
    
    // mapclose -- close the file
    void
    mapclose(filemap *map)
    {
    
        if (map->map_base != NULL)
            munmap(map->map_base,map->map_siz);
        map->map_base = NULL;
    
        if (map->map_fd >= 0)
            close(map->map_fd);
        map->map_fd = -1;
    }
    
    // mapreverse -- reverse copy lines in file
    void
    mapreverse(const char *srcfile,const char *dstfile)
    {
        filemap src;
        filemap dst;
        byte *base;
        byte *prev;
        byte *cur;
        ssize_t lhslen;
        ssize_t rawlen;
        ssize_t curlen;
    
        mapopen(&src,srcfile,O_RDONLY,NULL);
        mapopen(&dst,dstfile,O_RDWR | O_CREAT,&src);
    
        base = src.map_base;
    
        // point past last char in file
        lhslen = src.map_siz;
        prev = base + lhslen;
    
        do {
            // empty file
            if (lhslen <= 0)
                break;
    
            // assume file with last line that has _no_ newline
    
            // bug out if short file
            cur = prev - 1;
            if (cur < base) {
                dbgprt("mapreverse: SHORT\n");
                break;
            }
    
            // well behaved file with newline as last char
            if (*cur == '\n') {
                dbgprt("mapreverse: NICE\n");
                lhslen -= 1;
            }
        } while (0);
    
        // copy over the bulk of the file
        while (lhslen > 0) {
            dbgprt("mapreverse: LOOP lhslen=%ld prev=%ld\n",lhslen,prev - base);
    
            // locate next (i.e. "previous") line
            cur = memrchr(base,'\n',lhslen);
    
            // copy over final part
            if (cur == NULL) {
                dbgprt("mapreverse: FINAL\n");
                break;
            }
    
            // get length of current line (including newline on left)
            rawlen = prev - cur;
            dbgprt("mapreverse: CURLEN cur=%ld prev=%ld rawlen=%ld\n",
                cur - base,prev - base,rawlen);
    
            // remove newline on left from copy buffer and length
            curlen = rawlen - 1;
    
            // copy current line
            dbgprt("mapreverse: COPY\n");
            memcpy(dst.map_ptr,cur + 1,curlen);
            dst.map_ptr += curlen;
            dst.map_siz -= curlen;
    
            // cut back on the length we scan
            lhslen = cur - base;
    
            // point one past the newline we just found
            prev = cur + 1;
        }
    
        // copy over final part
        if (dst.map_siz > 0) {
            dbgprt("mapreverse: FINAL map_siz=%ld\n",dst.map_siz);
            memcpy(dst.map_ptr,base,dst.map_siz);
        }
    
        mapclose(&src);
        mapclose(&dst);
    }
    
    // main -- main program
    int
    main(int argc,char **argv)
    {
        char *cp;
    
        --argc;
        ++argv;
    
        for (;  argc > 0;  --argc, ++argv) {
            cp = *argv;
            if (*cp != '-')
                break;
    
            switch (cp[1]) {
            default:
                break;
            }
        }
    
        setlinebuf(stderr);
    
        if (argc != 2)
            sysfault("main: must have exactly two arguments\n");
    
        mapreverse(argv[0],argv[1]);
    
        return 0;
    }
    
    定义GNU源
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义系统故障(_fmt…)\
    做{\
    fprintf(标准,fmt)\
    出口(1)\
    }而(0)
    #ifdef调试
    #定义dbgprt(_fmt…)fprintf(stderr,_fmt)
    #否则
    #定义dbgprt(_fmt…)/**/
    #恩迪夫
    typedef无符号字符字节;
    类型定义结构{
    const char*map_file;//文件名
    int map_fd;//文件描述符
    size\u t map\u siz;//文件大小
    byte*map_base;//映射区域的底部
    byte*map_ptr;//当前映射指针
    size\u t map\u off;//当前文件偏移量
    struct stat map_st;//stat syscall
    }文件映射;
    //mapopen——打开文件
    无效的
    mapopen(文件映射*映射,常量字符*文件,int模式,文件映射*映射FM)
    {
    int-prot;
    INTERR;
    memset(map,0,sizeof(filemap));
    映射->映射文件=文件;
    map->map\u fd=open(map->map\u文件,模式,0644);
    如果(映射->映射\u fd<0)
    sysfault(“mapopen:无法打开'%s'--%s\n”,
    map->map_文件,strerror(errno));
    //创建新文件
    if(模式和O_创建){
    地图->地图大小=地图大小->地图大小;
    err=ftruncate(映射->映射\u fd,映射->映射大小);
    如果(误差<0)
    sysfault(“mapopen:无法ftruncate--%s\n”,strerror(errno));
    map->map\u off=0;
    }
    //处理现有文件
    否则{
    fstat(地图->地图fd和地图->地图st);
    地图->地图大小=地图->地图大小;
    地图->地图关闭=地图->地图大小-1;
    lseek(map->map\u fd,map->map\u off,0);
    }
    prot=0;
    if(模式和O_创建)
    prot |=prot|u WRITE;
    其他的
    prot |=prot|u READ;
    做{
    如果(映射->映射大小==0)
    打破
    map->map\u base=mmap(NULL,map->map\u size,prot,map\u SHARED,map->map\u fd,0);
    如果(地图->地图基础==M
    
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    
    #define sysfault(_fmt...) \
        do { \
            fprintf(stderr,_fmt); \
            exit(1); \
        } while (0)
    
    #ifdef DEBUG
    #define dbgprt(_fmt...)     fprintf(stderr,_fmt)
    #else
    #define dbgprt(_fmt...)     /**/
    #endif
    
    typedef unsigned char byte;
    
    typedef struct {
        const char *map_file;               // filename
        int map_fd;                         // file descriptor
        size_t map_siz;                     // file size
        byte *map_base;                     // base of map area
        byte *map_ptr;                      // current map pointer
        size_t map_off;                     // current file offset
        struct stat map_st;                 // stat syscall
    } filemap;
    
    // mapopen -- open the file
    void
    mapopen(filemap *map,const char *file,int mode,filemap *mapfm)
    {
        int prot;
        int err;
    
        memset(map,0,sizeof(filemap));
    
        map->map_file = file;
        map->map_fd = open(map->map_file,mode,0644);
        if (map->map_fd < 0)
            sysfault("mapopen: unable to open '%s' -- %s\n",
                map->map_file,strerror(errno));
    
        // create new file
        if (mode & O_CREAT) {
            map->map_siz = mapfm->map_siz;
            err = ftruncate(map->map_fd,map->map_siz);
            if (err < 0)
                sysfault("mapopen: unable to ftruncate -- %s\n",strerror(errno));
            map->map_off = 0;
        }
    
        // process existing file
        else {
            fstat(map->map_fd,&map->map_st);
            map->map_siz = map->map_st.st_size;
            map->map_off = map->map_siz - 1;
            lseek(map->map_fd,map->map_off,0);
        }
    
        prot = 0;
        if (mode & O_CREAT)
            prot |= PROT_WRITE;
        else
            prot |= PROT_READ;
    
        do {
            if (map->map_siz == 0)
                break;
    
            map->map_base = mmap(NULL,map->map_siz,prot,MAP_SHARED,map->map_fd,0);
            if (map->map_base == MAP_FAILED)
                sysfault("mapopen: unable to map map_file='%s' map_siz=%ld -- %s\n",
                    map->map_file,map->map_siz,strerror(errno));
    
            // get starting offset for file
            map->map_ptr = map->map_base + map->map_off;
        } while (0);
    }
    
    // mapclose -- close the file
    void
    mapclose(filemap *map)
    {
    
        if (map->map_base != NULL)
            munmap(map->map_base,map->map_siz);
        map->map_base = NULL;
    
        if (map->map_fd >= 0)
            close(map->map_fd);
        map->map_fd = -1;
    }
    
    // mapreverse -- reverse copy lines in file
    void
    mapreverse(const char *srcfile,const char *dstfile)
    {
        filemap src;
        filemap dst;
        byte *base;
        byte *prev;
        byte *cur;
        ssize_t lhslen;
        ssize_t rawlen;
        ssize_t curlen;
    
        mapopen(&src,srcfile,O_RDONLY,NULL);
        mapopen(&dst,dstfile,O_RDWR | O_CREAT,&src);
    
        base = src.map_base;
    
        // point past last char in file
        lhslen = src.map_siz;
        prev = base + lhslen;
    
        do {
            // empty file
            if (lhslen <= 0)
                break;
    
            // assume file with last line that has _no_ newline
    
            // bug out if short file
            cur = prev - 1;
            if (cur < base) {
                dbgprt("mapreverse: SHORT\n");
                break;
            }
    
            // well behaved file with newline as last char
            if (*cur == '\n') {
                dbgprt("mapreverse: NICE\n");
                lhslen -= 1;
            }
        } while (0);
    
        // copy over the bulk of the file
        while (lhslen > 0) {
            dbgprt("mapreverse: LOOP lhslen=%ld prev=%ld\n",lhslen,prev - base);
    
            // locate next (i.e. "previous") line
            cur = memrchr(base,'\n',lhslen);
    
            // copy over final part
            if (cur == NULL) {
                dbgprt("mapreverse: FINAL\n");
                break;
            }
    
            // get length of current line (including newline on left)
            rawlen = prev - cur;
            dbgprt("mapreverse: CURLEN cur=%ld prev=%ld rawlen=%ld\n",
                cur - base,prev - base,rawlen);
    
            // remove newline on left from copy buffer and length
            curlen = rawlen - 1;
    
            // copy current line
            dbgprt("mapreverse: COPY\n");
            memcpy(dst.map_ptr,cur + 1,curlen);
            dst.map_ptr += curlen;
            dst.map_siz -= curlen;
    
            // cut back on the length we scan
            lhslen = cur - base;
    
            // point one past the newline we just found
            prev = cur + 1;
        }
    
        // copy over final part
        if (dst.map_siz > 0) {
            dbgprt("mapreverse: FINAL map_siz=%ld\n",dst.map_siz);
            memcpy(dst.map_ptr,base,dst.map_siz);
        }
    
        mapclose(&src);
        mapclose(&dst);
    }
    
    // main -- main program
    int
    main(int argc,char **argv)
    {
        char *cp;
    
        --argc;
        ++argv;
    
        for (;  argc > 0;  --argc, ++argv) {
            cp = *argv;
            if (*cp != '-')
                break;
    
            switch (cp[1]) {
            default:
                break;
            }
        }
    
        setlinebuf(stderr);
    
        if (argc != 2)
            sysfault("main: must have exactly two arguments\n");
    
        mapreverse(argv[0],argv[1]);
    
        return 0;
    }