Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 向后读取文件(最后一行在前)_C_File - Fatal编程技术网

C 向后读取文件(最后一行在前)

C 向后读取文件(最后一行在前),c,file,C,File,文件如下所示: #include <stdio.h> #include <String.h> int main(){ FILE *file; char all[1000]; // give any name to read in reverse order file = fopen("anyFile.txt","r"); // gets all the content and stores in variable all

文件如下所示:

#include <stdio.h>
#include <String.h>

int main(){
    FILE *file;
    char all[1000];

    // give any name to read in reverse order
    file = fopen("anyFile.txt","r");

    // gets all the content and stores in variable all
    fscanf(file,"%[]",all);

    // Content of the file 
    printf("Content Of the file %s",all);

    // reverse the string 
    printf("%s",strrev(all));
    fclose(file);
    return 0;
}
abcd
efgh
ijkl

我想使用
C
读取文件,以便它首先读取最后一行:

ijkl
efgh
abcd

我似乎找不到不使用
阵列
存储的解决方案。请帮忙

edit0: 谢谢你的回答。只是想让你知道,我是创建这个文件的人。那么,我可以按相反的顺序创建它吗?这可能吗?

它是这样的:

#include <stdio.h>
#include <String.h>

int main(){
    FILE *file;
    char all[1000];

    // give any name to read in reverse order
    file = fopen("anyFile.txt","r");

    // gets all the content and stores in variable all
    fscanf(file,"%[]",all);

    // Content of the file 
    printf("Content Of the file %s",all);

    // reverse the string 
    printf("%s",strrev(all));
    fclose(file);
    return 0;
}
  • 使用查找文件结尾前的一个字节。不能保证最后一行会有一个EOL,所以最后一个字节并不重要
  • 使用读取一个字节
  • 如果该字节是一个下线,那么最后一行是一个空行,您拥有它
  • 再次使用
    fseek
    向后返回两个字节,并使用
    fgetc
    检查该字节
  • 重复上述步骤,直到找到下线。当您有一个下线时,文件指针将位于下一行(从末尾开始)的开头
  • 利润
  • 基本上,你必须继续做(4)和(5),同时跟踪你发现一行开头时的位置,以便在开始扫描下一行开头之前可以在那里查找

    只要以文本模式打开文件,就不必担心Windows上的多字节EOL(感谢Lutz先生的提醒)

    如果您碰巧得到了一个不可查找的输入(例如管道),那么您就不走运了,除非您想先将输入转储到一个临时文件中

    所以你可以这样做,但它是相当丑陋的

    如果您有
    mmap
    可用,并且您正在使用的“文件”是可映射的,那么您可以使用和指针做几乎相同的事情。其技巧大致相同:从末尾开始,然后向后查找前一行的结尾


    Re:“我是创建此文件的人。那么,我可以按相反顺序创建它吗?可能吗?”

    你会遇到同样的问题,但情况会更糟。C语言中的文件本质上是从开始到结束的连续字节列表;你试图违背这个基本属性,违背基本属性从来都不是一件有趣的事

    您真的需要纯文本文件中的数据吗?也许您需要文本/纯文本作为最终输出,但始终如此?您可以将数据存储在索引的二进制文件(甚至可能是SQLite数据库)中,然后只需担心将索引保留(或窗口化)在内存中,这不太可能是一个问题(如果是,请使用“真实”数据库);然后,当您拥有所有行时,只需反转索引并离开即可。

    在伪代码中:

    open input file
    while (fgets () != NULL)
    {
       push line to stack
    }
    open output file
    while (stack no empty)
    {
       pop stack
       write popped line to file
    }
    
    上述方法是有效的,没有寻道(一种缓慢的操作),文件是按顺序读取的。然而,上述问题存在两个陷阱

    第一个是
    fgets
    调用。提供给
    fgets
    的缓冲区可能不够大,无法容纳来自输入的整行数据,在这种情况下,您可以执行以下操作之一:再次读取并连接;推送部分行并向后半部分添加逻辑,以修复部分行或将该行包装到链接列表中,并且仅在遇到换行/eof时推送链接列表


    第二个陷阱发生在文件大于可用ram以容纳堆栈时,在这种情况下,每当达到某个阈值内存使用量时,您需要将堆栈结构写入临时文件。

    以下内容适用于Linux,其中文本文件行分隔符为“\n”

    #包括
    #包括
    #包括
    void readfileinreverse(文件*fp)
    {
    int i、大小、开始、循环、计数器;
    字符*缓冲区;
    字符行[256];
    开始=0;
    fseek(fp,0,SEEK_END);
    尺寸=ftell(fp);
    缓冲区=malloc((大小+1)*sizeof(字符));
    对于(i=0;i开始;循环--)
    {
    如果((计数器==0)&&(缓冲区[循环]==10))
    {
    继续;
    }               
    行[计数器]=缓冲区[循环];
    计数器++;
    }
    行[计数器]=0;
    开始=i;
    printf(“%s\n”,第行);
    }
    }
    }
    如果(i>开始)
    {    
    计数器=0;
    对于(循环=i;循环>开始;循环--)
    {       
    如果((计数器==0)和((缓冲区[循环]==10)| |(缓冲区[循环]==0)))
    {
    继续;
    }               
    行[计数器]=缓冲区[循环];
    计数器++;
    }
    行[计数器]=0;
    printf(“%s\n”,第行);
    返回;
    }
    }
    int main()
    {
    文件*fp=fopen(“./1.txt”,“r”);
    readfileinreverse(fp);
    返回0;
    }
    
    以下代码应执行必要的反转:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[])
    {
            FILE *fd;
            char len[400];
            int i;
    
            char *filename = argv[1];
            int ch;
            int count;
    
            fd = fopen(filename, "r");
            fseek(fd, 0, SEEK_END);
            while (ftell(fd) > 1 ){
                    fseek(fd, -2, SEEK_CUR);
                    if(ftell(fd) <= 2)
                            break;
                    ch =fgetc(fd);
                    count = 0;
                    while(ch != '\n'){
                            len[count++] = ch;
                            if(ftell(fd) < 2)
                                    break;
                            fseek(fd, -2, SEEK_CUR);
                            ch =fgetc(fd);
                    }
                    for (i =count -1 ; i >= 0 && count > 0  ; i--)
                            printf("%c", len[i]);
                    printf("\n");
            }
            fclose(fd);
    }
    
    #包括
    #包括
    int main(int argc,char*argv[])
    {
    文件*fd;
    charlen[400];
    int i;
    char*filename=argv[1];
    int-ch;
    整数计数;
    fd=fopen(文件名,“r”);
    fseek(fd,0,SEEK_END);
    而(ftell(fd)>1){
    fseek(fd,-2,SEEK_CUR);
    如果(ftell(fd)=0&&count>0;i--)
    printf(“%c”,len[i]);
    printf(“\n”);
    }
    fclose(fd);
    }
    
    也许,这个方法可以使文件的内容全部反转 就像一根绳子

  • 根据文件大小定义字符串类型的变量
  • 获取文件内容并存储在变量中
  • 使用strrev()反转字符串
  • 您可以稍后显示输出,甚至写入输出