存储文本文件的每一行到一个数组 [英] Storing each line of a text file into an array

查看:124
本文介绍了存储文本文件的每一行到一个数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想一个文本文件中的每一行保存到一个数组。
他们的方式我做它,工作至今罚款是这样的:

I am trying to save each line of a text file into an array. They way I am doing it and works fine so far is this :

char *lines[40];
char line[50];
int i = 0 ;
char* eof ;
while( (eof = fgets(line, 50, in)) != NULL )
{
    lines[i] = strdup(eof); /*Fills the array with line of the txt file one by one*/
    i++;
}

我的文本文件有40行,这我有访问循环

My text file has 40 lines , which I am accessing with a for loop

for( j = 0; j <= 39 ; j++)
{ /*Do something to each line*/}.

到目前为止好。我的问题是我定义数组的大小
对于具有40行的文本文件。我试图计算的线条,然后定义大小,但我得到的分段故障

我的方法:

int count=1 ; char c ;
for (c = getc(in); c != EOF; c = getc(in))
    if (c == '\n') // Increment count if this character is newline
        count = count + 1;
printf("\nNUMBER OF LINES = %d \n",count); 

char* lines[count];

任何想法?

推荐答案

有很多方法可以解决这个问题。无论是声明静态二维数组或字符(如字符线[40] [50] = {{}}; )或指针申报的数组类型char [50] 的,这可能是最简单的动态分配。有了这种方法,你只需要一个单一的分配。随着不断的 MAXL = 40 MAXC = 50 ,你只需要:

There are many ways to approach this problem. Either declare a static 2D array or char (e.g. char lines[40][50] = {{""}};) or declare a pointer to array of type char [50], which is probably the easiest for dynamic allocation. With that approach you only need a single allocation. With constant MAXL = 40 and MAXC = 50, you simply need:

char (*lines)[MAXC] = NULL;
...
lines = malloc (MAXL * sizeof *lines);

阅读每一行与fgets 是一个简单的任务:

while (i < MAXL && fgets (lines[i], MAXC, fp)) {...

当你完成,你需要做的就是免费(系); 把拼在一起,你可以这样做:

When you are done, all you need to do is free (lines); Putting the pieces together, you can do something like:

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

enum { MAXL = 40, MAXC = 50 };

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

    char (*lines)[MAXC] = NULL; /* pointer to array of type char [MAXC] */
    int i, n = 0;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* valdiate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    if (!(lines = malloc (MAXL * sizeof *lines))) { /* allocate MAXL arrays */
        fprintf (stderr, "error: virtual memory exhausted 'lines'.\n");
        return 1;
    }

    while (n < MAXL && fgets (lines[n], MAXC, fp)) { /* read each line */
        char *p = lines[n];                  /* assign pointer */
        for (; *p && *p != '\n'; p++) {}     /* find 1st '\n'  */
        *p = 0, n++;                         /* nul-termiante  */
    }
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    /* print lines */
    for (i = 0; i < n; i++) printf (" line[%2d] : '%s'\n", i + 1, lines[i]);

    free (lines);   /* free allocated memory */

    return 0;
}

注:的你还需要检查,看看是否整条生产线是由与fgets 每次读取。 (说你有超过38个字符的文件中长线)。您可以通过检查这样做是否 * P 的'\\ n' NUL终止的覆盖前的角色。 (例如:如果(* p ='\\ n'){诠释三;而((C =的getchar())='\\ n'和;!&安培;!C = EOF){}}! )。这保证了和与fgets下一个读将与下一行开始,而不是在当前行剩余的字符。

note: you will also want to check to see if the whole line was read by fgets each time. (say you had a long line of more than 38 chars in the file). You do this by checking whether *p is '\n' before overwriting with the nul-terminating character. (e.g. if (*p != '\n') { int c; while ((c = getchar()) != '\n' && c != EOF) {} }). That insures the next read with fgets will begin with the next line, instead of the remaining characters in the current line.

要包括你可以做类似于以下(记的东西检查:的我从 I 到<$ C改读循环计数器$ C> N 来消除分配的需要 N =; 继读循环)

To include the check you could do something similar to the following (note: I changed the read loop counter from i to n to eliminate the need for assigning n = i; following the read loop).

    while (n < MAXL && fgets (lines[n], MAXC, fp)) { /* read each line */
        char *p = lines[n];                 /* assign pointer  */
        for (; *p && *p != '\n'; p++) {}    /* find 1st '\n'   */
        if (*p != '\n') {                   /* check line read */
            int c;  /* discard remainder of line with getchar  */
            while ((c = fgetc (fp)) != '\n' && c != EOF) {}
        }
        *p = 0, n++;                        /* nul-termiante   */
    }

它是由您是否放弃或保留超过您的数组的长度行的剩余部分。然而,这是一个好主意,经常检查。 (文本在我的例子中输入下面的线被限制到17个字符,所以没有长线的可能性,但一般不能保证线路长度。

It is up to you whether you discard or keep the remainder of lines that exceed the length of your array. However, it is a good idea to always check. (the lines of text in my example input below are limited to 17-chars so there was no possibility of a long line, but you generally cannot guarantee the line length.

例输入

$ cat dat/40lines.txt
line of text -  1
line of text -  2
line of text -  3
line of text -  4
line of text -  5
line of text -  6
...
line of text - 38
line of text - 39
line of text - 40

示例使用/输出

$ ./bin/fgets_ptr2array <dat/40lines.txt
 line[ 1] : 'line of text -  1'
 line[ 2] : 'line of text -  2'
 line[ 3] : 'line of text -  3'
 line[ 4] : 'line of text -  4'
 line[ 5] : 'line of text -  5'
 line[ 6] : 'line of text -  6'
...
 line[38] : 'line of text - 38'
 line[39] : 'line of text - 39'
 line[40] : 'line of text - 40'

现在包括code进行长度检查,长行添加到输入,例如:

Now include a the length check in code and add a long line to the input, e.g.:

$ cat dat/40lines+long.txt
line of text -  1
line of text -  2
line of text -  3 + 123456789 123456789 123456789 123456789 65->|
line of text -  4
...

重新运行该程序,并可以确认现在你已经对长行的文件保护文件打乱你的线条的顺序读取。

Rerun the program and you can confirm you have now protected against long lines in the file mucking up your sequential read of lines from the file.

动态再分配

Dynamically Reallocating lines

如果您有数目不详的在你的文件中的行,你在线到达你的 40 的初始分配 ,那么所有你需要做的,让阅读更多的线是 的realloc 存储产品线。例如:

If you have an unknown number of lines in your file and you reach your initial allocation of 40 in lines, then all you need do to keep reading additional lines is realloc storage for lines. For example:

    int i, n = 0, maxl = MAXL;
    ...
    while (fgets (lines[n], MAXC, fp)) {     /* read each line */
        char *p = lines[n];                  /* assign pointer */
        for (; *p && *p != '\n'; p++) {}     /* find 1st '\n'  */
        *p = 0;                              /* nul-termiante  */
        if (++n == maxl) { /* if limit reached, realloc lines  */
            void *tmp = realloc (lines, 2 * maxl * sizeof *lines);
            if (!tmp) {     /* validate realloc succeeded */
                fprintf (stderr, "error: realloc - virtual memory exhausted.\n");
                break;      /* on failure, exit with existing data */
            }
            lines = tmp;    /* assign reallocated block to lines */
            maxl *= 2;      /* update maxl to reflect new size */
        }
    }

现在不要紧多少行是在你的文件,你可以简单的重新分配保持,直到整个文件被读出,或者你耗尽内存。 (注:目前code重新分配两倍于当前的内存为每个再分配您可以自由添加尽可能多或尽可能少的,只要你喜欢。例如,。你可以分配 maxl + 40 只需每次分配 40 多行。

Now it doesn't matter how many lines are in your file, you will simply keep reallocating lines until your entire files is read, or you run out of memory. (note: currently the code reallocates twice the current memory for lines on each reallocation. You are free to add as much or as little as you like. For example, you could allocate maxl + 40 to simply allocate 40 more lines each time.

例输入

$ cat dat/80lines.txt
line of text -  1
line of text -  2
...
line of text - 79
line of text - 80

示例使用/输出

$ ./bin/fgets_ptr2array_realloc <dat/80lines.txt
 line[ 1] : 'line of text -  1'
 line[ 2] : 'line of text -  2'
...
 line[79] : 'line of text - 79'
 line[80] : 'line of text - 80'

看一下,然后告诉我知道,如果你有任何问题。

Look it over and let me know if you have any questions.

这篇关于存储文本文件的每一行到一个数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆