Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.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_Arrays_File_Text - Fatal编程技术网

在C语言中将文本文件读入行数组

在C语言中将文本文件读入行数组,c,arrays,file,text,C,Arrays,File,Text,使用C,我希望以这样一种方式读入一个文本文件的内容,即当所有内容都说了和做了时,有一个字符串数组,其中第n个字符串表示文本文件的第n行。文件的行可以任意长 实现这一点的优雅方式是什么?我知道一些巧妙的技巧,可以将文本文件直接读入一个大小合适的缓冲区,但将其分解成几行会使它更复杂(至少就我所知) 非常感谢 对于C(与C++相反),您可能会使用。但是,由于行的长度任意,您可能会遇到问题。将其分解为行意味着解析文本并将所有EOL(我指的是EOL)字符替换为0。 通过这种方式,您实际上可以重用缓冲区,并

使用C,我希望以这样一种方式读入一个文本文件的内容,即当所有内容都说了和做了时,有一个字符串数组,其中第n个字符串表示文本文件的第n行。文件的行可以任意长

实现这一点的优雅方式是什么?我知道一些巧妙的技巧,可以将文本文件直接读入一个大小合适的缓冲区,但将其分解成几行会使它更复杂(至少就我所知)


非常感谢

对于C(与C++相反),您可能会使用。但是,由于行的长度任意,您可能会遇到问题。

将其分解为行意味着解析文本并将所有EOL(我指的是EOL)字符替换为0。 通过这种方式,您实际上可以重用缓冲区,并将每行的开头存储到一个单独的char*数组中(所有操作只需执行2次)


通过这种方式,您可以对整个文件大小执行一次读取+2次解析,这可能会提高性能。

也许链接列表是最好的方法? 编译器不会喜欢一个数组不知道它有多大。使用链表,您可以拥有一个非常大的文本文件,而不用担心为数组分配足够的内存


不幸的是,我还没有学会如何制作链表,但也许其他人可以帮助你。

如果你有一个很好的方法将整个文件读入内存,你就差不多做到了。完成后,您可以扫描文件两次。一次用于计算行数,一次用于设置行指针并将“\n”和(如果文件是在Windows二进制模式下读取的,则可能是“\r”)替换为“\0”。在两次扫描之间分配一个指针数组,现在您知道需要多少指针了。

可以读取文件中的行数(循环fgets),然后创建一个二维数组,第一个维度是行数+1。然后,只需将文件重新读取到数组中

不过,您需要定义元素的长度。或者,计算最长的行大小

示例代码:

inFile = fopen(FILENAME, "r");
lineCount = 0;
while(inputError != EOF) {
    inputError = fscanf(inFile, "%s\n", word);
    lineCount++;
}
fclose(inFile);
  // Above iterates lineCount++ after the EOF to allow for an array
  // that matches the line numbers

char names[lineCount][MAX_LINE];

fopen(FILENAME, "r");
for(i = 1; i < lineCount; i++)
    fscanf(inFile, "%s", names[i]);
fclose(inFile);
infle=fopen(文件名,“r”);
行数=0;
while(输入错误!=EOF){
inputError=fscanf(填充,“%s\n”,字);
lineCount++;
}
fclose(infle);
//上面在EOF之后迭代lineCount++以允许使用数组
//与行号匹配
字符名称[行数][最大行];
fopen(文件名,“r”);
对于(i=1;i
您可以这样使用

#include <stdlib.h> /* exit, malloc, realloc, free */
#include <stdio.h>  /* fopen, fgetc, fputs, fwrite */

struct line_reader {
    /* All members are private. */
    FILE    *f;
    char    *buf;
    size_t   siz;
};

/*
 * Initializes a line reader _lr_ for the stream _f_.
 */
void
lr_init(struct line_reader *lr, FILE *f)
{
    lr->f = f;
    lr->buf = NULL;
    lr->siz = 0;
}

/*
 * Reads the next line. If successful, returns a pointer to the line,
 * and sets *len to the number of characters, at least 1. The result is
 * _not_ a C string; it has no terminating '\0'. The returned pointer
 * remains valid until the next call to next_line() or lr_free() with
 * the same _lr_.
 *
 * next_line() returns NULL at end of file, or if there is an error (on
 * the stream, or with memory allocation).
 */
char *
next_line(struct line_reader *lr, size_t *len)
{
    size_t newsiz;
    int c;
    char *newbuf;

    *len = 0;           /* Start with empty line. */
    for (;;) {
        c = fgetc(lr->f);   /* Read next character. */
        if (ferror(lr->f))
            return NULL;

        if (c == EOF) {
            /*
             * End of file is also end of last line,
        `    * unless this last line would be empty.
             */
            if (*len == 0)
                return NULL;
            else
                return lr->buf;
        } else {
            /* Append c to the buffer. */
            if (*len == lr->siz) {
                /* Need a bigger buffer! */
                newsiz = lr->siz + 4096;
                newbuf = realloc(lr->buf, newsiz);
                if (newbuf == NULL)
                    return NULL;
                lr->buf = newbuf;
                lr->siz = newsiz;
            }
            lr->buf[(*len)++] = c;

            /* '\n' is end of line. */
            if (c == '\n')
                return lr->buf;
        }
    }
}

/*
 * Frees internal memory used by _lr_.
 */
void
lr_free(struct line_reader *lr)
{
    free(lr->buf);
    lr->buf = NULL;
    lr->siz = 0;
}

/*
 * Read a file line by line.
 * http://rosettacode.org/wiki/Read_a_file_line_by_line
 */
int
main()
{
    struct line_reader lr;
    FILE *f;
    size_t len;
    char *line;

    f = fopen("foobar.txt", "r");
    if (f == NULL) {
        perror("foobar.txt");
        exit(1);
    }

    /*
     * This loop reads each line.
     * Remember that line is not a C string.
     * There is no terminating '\0'.
     */
    lr_init(&lr, f);
    while (line = next_line(&lr, &len)) {
        /*
         * Do something with line.
         */
        fputs("LINE: ", stdout);
        fwrite(line, len, 1, stdout);
    }
    if (!feof(f)) {
        perror("next_line");
        exit(1);
    }
    lr_free(&lr);

    return 0;
}
#包括/*exit、malloc、realloc、free*/
#包括/*fopen、fgetc、FPUT、fwrite*/
结构行读卡器{
/*所有成员都是非公开的*/
文件*f;
char*buf;
大小;
};
/*
*初始化流的行读取器。
*/
无效的
lr_init(结构行读取器*lr,文件*f)
{
lr->f=f;
lr->buf=NULL;
lr->siz=0;
}
/*
*读下一行。如果成功,则返回一个指向该行的指针,
*并将*len设置为字符数,至少为1。结果是
*不是一个C字符串;它没有终止“\0”。返回的指针
*在下次使用调用next_line()或lr_free()之前保持有效
*同样的。
*
*next_line()在文件末尾返回NULL,或者如果有错误(在
*流,或使用内存分配)。
*/
煤焦*
下一行(结构行读卡器*lr,大小*len)
{
大小新闻;
INTC;
char*newbuf;
*len=0;/*以空行开始*/
对于(;;){
c=fgetc(lr->f);/*读取下一个字符*/
中频(铁磁(lr->f))
返回NULL;
如果(c==EOF){
/*
*文件结尾也是最后一行的结尾,
`*除非最后一行为空。
*/
如果(*len==0)
返回NULL;
其他的
返回lr->buf;
}否则{
/*将c附加到缓冲区*/
如果(*len==lr->siz){
/*需要更大的缓冲*/
newsiz=lr->siz+4096;
newbuf=realloc(lr->buf,newsiz);
如果(newbuf==NULL)
返回NULL;
lr->buf=newbuf;
lr->siz=newsiz;
}
lr->buf[(*len)+]=c;
/*“\n”是行的结尾*/
如果(c=='\n')
返回lr->buf;
}
}
}
/*
*释放_lr_2;使用的内部内存。
*/
无效的
lr_空闲(结构行_读取器*lr)
{
免费(lr->buf);
lr->buf=NULL;
lr->siz=0;
}
/*
*逐行读取文件。
* http://rosettacode.org/wiki/Read_a_file_line_by_line
*/
int
main()
{
结构行\读卡器lr;
文件*f;
尺寸透镜;
字符*行;
f=fopen(“foobar.txt”,“r”);
如果(f==NULL){
perror(“foobar.txt”);
出口(1);
}
/*
*这个循环读取每一行。
*请记住,行不是C字符串。
*没有终止“\0”的命令。
*/
lr_init(&lr,f);
while(行=下一行(&lr,&len)){
/*
*用绳子做点什么。
*/
FPUT(“行:”,标准输出);
写入(行、列、1、标准输出);
}
如果(!feof(f)){
perror(“下一条线”);
出口(1);
}
无lr_(&lr);
返回0;
}

这无疑是最好的方法,尽管它可能需要对整个文件进行多次传递。您需要计算行数(以便可以分配正确大小的数组),将\n替换为0,然后将每行的开头指定给数组中的正确位置。当然,你可以分两次完成。这是一个非常好的主意。我要试一试。+1不计算从文件到缓冲区的初始副本,您可以使用
realloc()
strtok()
进行一次传递。同意这需要两次传递。至少我现在连一个通行证都不知道怎么走。相应地更新了帖子。为什么需要两个通行证?为a分配空间