从文件动态分配2d字符串数组

时间:2014-04-04 13:18:51

标签: c string dynamic-arrays

这个问题可能很常见,但我没有找到任何接近这个确切问题的内容,所以我会问。我有一个看起来像这样的文件。

ABCSTRX
ABCST
ABCS
ABCSTRXY

我的任务是创建二维字符串数组。对于每个字符串,它只分配所需的空间(字符串的长度),因此它看起来像这样。

the red area is for '\0'

  

到目前为止,在我的代码中,我扫描了文件并获得了代表文件中字符串数量的数字。

void function(FILE *txt){
    char arr[50];
    int counter=0;
    char **array;

    do {                                    
       fgets(arr,MAX,txt);
       counter++;
    } while(fgets(arr,MAX,txt)!=NULL);

    rewind(txt);
    array = malloc(counter * sizeof(char*));


    //FROM NOW ON THE CODE IS NOT CORRECT
    do {                                    
        fgets(arr,MAX,txt);
        counter++;

        for(int j=0;j<strlen(arr); j++){
            array[i]= malloc(strlen(arr) * sizeof(char));
            array[i]= arr;
        }
        i++;
    } while(fgets(arr,MAX,txt)!=NULL);

}

问题是我无法找到一个解决方案如何使用大小不匹配的字符串填充动态分配的数组。这是我提出的代码,我感到困惑。在数组填充字符串后,它将被打印(我猜想有两个循环)。感谢您的评论

2 个答案:

答案 0 :(得分:2)

您可能需要考虑以下注释的可编译C代码 我没有在这里写一些笔记,而是在代码中内嵌了几条注释,试图清楚地解释代码在做什么。

#include <stdio.h>      /* For printf and file management */
#include <stdlib.h>     /* For dynamic memory allocation */
#include <string.h>     /* For string functions */

/* 
 * Read all lines from text file, and store them in a dynamically 
 * allocated array. 
 * The count of lines is stored in the 'count' output parameter
 * The caller is responsible for freeing the allocated memory.
 */
char** read_lines(FILE* txt, int* count) {
    char** array = NULL;        /* Array of lines */
    int    i;                   /* Loop counter */
    char   line[100];           /* Buffer to read each line */
    int    line_count;          /* Total number of lines */
    int    line_length;         /* Length of a single line */

    /* Clear output parameter. */
    *count = 0;

    /* Get the count of lines in the file */
    line_count = 0;
    while (fgets(line, sizeof(line), txt) != NULL) {                                      
       line_count++;
    }

    /* Move to the beginning of file. */
    rewind(txt);

    /* Allocate an array of pointers to strings 
     * (one item per line). */
    array = malloc(line_count * sizeof(char *));
    if (array == NULL) {
        return NULL; /* Error */
    }

    /* Read each line from file and deep-copy in the array. */
    for (i = 0; i < line_count; i++) {    
        /* Read the current line. */
        fgets(line, sizeof(line), txt);

        /* Remove the ending '\n' from the read line. */
        line_length = strlen(line);        
        line[line_length - 1] = '\0';
        line_length--; /* update line length */

        /* Allocate space to store a copy of the line. +1 for NUL terminator */
        array[i] = malloc(line_length + 1);

        /* Copy the line into the newly allocated space. */
        strcpy(array[i], line);
    }

    /* Write output param */
    *count = line_count;

    /* Return the array of lines */
    return array;
}

int main(int argc, char * argv[]) {
    char**      array    = NULL;    /* Array of read lines */
    FILE*       file     = NULL;    /* File to read lines from */
    const char* filename = NULL;    /* Name of the input file */
    int         i;                  /* Loop index */
    int         line_count;         /* Total number of read lines *7

    /* Get filename from the command line. */
    if (argc != 2) {
        printf("Specify the input file from the command line.\n");
        return 1;
    }    
    filename = argv[1];

    /* Try opening the file. */
    file = fopen(filename, "rt");
    if (file == NULL) {
        printf("Can't open file %s.\n", filename);
        return 1;
    }

    /* Read lines from file. */
    array = read_lines(file, &line_count);

    /* Just for test, print out the read lines. */
    for (i = 0; i < line_count; i++) {
        printf("[%d]: %s\n", (i+1), array[i]);
    }

    /* Cleanup. */
    fclose(file);
    for (i = 0; i < line_count; i++) {
        free(array[i]);
    }
    free(array);
    array = NULL;

    /* All right */
    return 0;
}

使用如下输入文件:

ABCSTRX
ABCST
ABCS
ABCSTRXY

输出结果为:

C:\Temp>test.exe testfile.txt
[1]: ABCSTRX
[2]: ABCST
[3]: ABCS
[4]: ABCSTRX

答案 1 :(得分:0)

你的do while循环计算文件中的行数不会起作用,因为你在每次迭代中调用fgets两次 - 一次在循环体中和下一次检查条件 - 只更新计数器一次。

此外,strlen不计算终止空字节,但您必须为其分配空间。这是我对你的功能的更新。

void function(FILE *txt) {
    char arr[50];
    int counter = 0;
    char **array;

    while(fgets(arr, sizeof arr, txt)!=NULL)                                          
       counter++;

    rewind(txt);
    array = malloc(counter * sizeof *array);

    for(int i = 0; i < counter; i++) {
        fgets(arr, sizeof arr, txt);
        array[i] = malloc(strlen(a) + 1); // +1 for the terminating null byte
        strcpy(array[i], arr);  // copy the string to the buffer
    }
}