使用char **数组作为结构成员加载/填充结构,c

时间:2016-05-22 14:21:06

标签: c arrays struct

在过去的两天里,我问了一个question to load struct,但是我有一个问题是我的循环访问我的结构(一个循环来加载我的结构)。我已经用这种方式编辑了我的问题/代码:

myfile.txt的

Biology,chemistry,maths,music
Mechanics,IT,Geology,music,Astronomy
football,vollyball,baseball

的main.c

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

#define path "myfile.txt"

typedef struct student_info 
{
    char **cources_as_list;
} std_info;

std_info *myinfo; //a global var that will conatain student info
int line_count = 0, cource_count = 0;

char** load_file() 
{
    char *line = NULL;
    size_t len = 0;
    FILE *fp;
    int indexq=0;
    fp = fopen(path, "r");
    if (fp == NULL) 
    {
        perror("FILE OPEN ERROR[IN load_file]: ");
        exit(1);
    }
    char **mydata = malloc (sizeof (char *) * 4);//aup to four elements
    while (getline(&line, &len, fp) != -1) 
    {
        strtok(line, "\n");
        mydata[indexq]= strdup(line);
        indexq++;
    }
    line_count = indexq;
   return mydata;
}

char **return_cource_list(char *cources_string) {
    char *token;
    char **cource_list = malloc(sizeof(char *) * 10);
    int index = 0;
    //course_string is delimited by ",": (eg. Biology,chemistry,maths,music). parse this and add to my char ** variable.
    token = strtok(cources_string, ",");
    while (token != NULL) 
    {
        cource_list[index] = strdup(token);
        token = strtok(NULL, ",");
        index++;
    }
    cource_count = index;
    return cource_list;
}
int main() 
{
    int i, j;
    char** mydata = load_file(); //returns lines as a list/char ** array from file
    for (i = 0; i < line_count; i++) //line_count is the number of elements/lines in "mydata"
    {
        printf("line_data: %s\n",mydata[i]);//i can see all my lines!
        char **std_cource_list = return_cource_list(mydata[i]);
        for (j = 0; j < cource_count; j++) 
        {
            printf("\tcourse[%d]: %s\n",j,std_cource_list[j]);//i have all my courses as a list from each line
        }
        //can i load my struct like this? or any option to load my struct?
        myinfo[i].cources_as_list = std_cource_list;
    }

    // i want to see my structure elements here, (nested for loop required).
}

将我的char数组加载到我的struct时遇到seg_fault错误。 (即:这一行:myinfo[i].cources_as_list = std_cource_list;

3 个答案:

答案 0 :(得分:0)

您需要为结构分配内存。

std_info *myinfo = malloc(sizeof(std_info));

另外,不要将其设为全局,因为此任务中确实不需要全局变量。

答案 1 :(得分:0)

尝试

std_info * myinfo = malloc(line_count * sizeof *myinfo);

这会分配内存来保存line_count的{​​{1}}个对象,std_info指向第一个。

答案 2 :(得分:-1)

您永远不会为myinfo分配空间,我建议将其作为局部变量。除非在非常具体的情况下,几乎不需要全局变量。

此外,您正在使用malloc()几乎仅用于固定大小的分配,如果您可以使用数组进行静态处理,那么这将更容易管理并且效率更高。

这可能是您对

感兴趣的内容
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>

struct student_info 
{
    char **courses;
    size_t size;
};

char **
load_file(const char *const path)
{
    char *line;
    FILE *file;
    char **data;
    size_t row;
    size_t length;
    size_t count;

    file = fopen(path, "r");
    if (file == NULL) 
    {
        perror("FILE OPEN ERROR[IN load_file]: ");
        return NULL; // Notify the caller that there was a problem
                     // but do not necessarily quit as you might
                     // retry with another path.
    }

    count = 0;
    for (int chr = fgetc(file) ; chr != EOF ; chr = fgetc(file))
        count += (chr == '\n') ? 1 : 0;
    rewind(file);

    data = malloc((count + 1) * sizeof(*data));
    if (data == NULL)
    {
        // Perhaps notify the error
        fclose(file);
        return NULL;
    }
    data[count] = NULL; // Use as end of array delimiter

    row = 0;
    line = NULL;
    length = 0;
    while ((length = getline(&line, &length, file)) != -1) 
    {
        // The last character is always `\n' so remove it
        data[row] = malloc(length);
        if (data == NULL)
        {
            fclose(file);
            for (size_t i = row ; i >= 0 ; --i)
            {
                free(data[i]);
                free(data);

                return NULL;
            }
        }
        data[row][length - 1] = '\0';
        memcpy(data[row], line, length - 1);

        ++row;
    }

    fclose(file);
    // You need to `free' this, read the documentation
    free(line);

    return data;
}

char **
extract_courses_as_list(const char *const input) 
{
    char **courses;
    size_t index;
    const char *tail;
    const char *head;
    size_t count;

    head = input;
    count = 0;
    /* Count the number of fields to allocate memory */
    while (head != NULL)
    {
        tail = strchr(head, ',');
        if (tail != NULL)
            head = tail + 1;
        else
            head = NULL;
        count += 1;
    }

    index = 0;
    /* Allocate memory for the list, and the sentinel */
    courses = malloc((count + 1) * sizeof(*courses));
    head = input;
    while (head != NULL)
    {
        ptrdiff_t length;
        /* find the next `,' in the input string */
        tail = strchr(head, ',');
        if (tail == NULL) /* if it's not there, it's the last one */
            tail = strchr(head, '\0');
        /* compute the number of characters of the field */
        length = (ptrdiff_t) (tail - head);
        /* allocate space to copy the string */         
        courses[index] = malloc(length + 1);
        if (courses == NULL) /* always be safe and check */
        {
            for (size_t i = index ; i >= 0 ; --i)
                free(courses[index]);
            free(courses);
            return NULL;
        }
        /* always remember to `null' terminate */
        courses[index][length] = '\0';
        /* finally, copy the string */
        memcpy(courses[index], head, length);
        /* check whehter it was the last field and
         * update the pointer to the next one accordingly             
         */
        if ((tail != NULL) && (*tail != '\0'))
            head = tail + 1;
        else
            head = NULL;
        /* Don't forget the fields counter */
        index++;
    }
    courses[count] = NULL;

    return courses;
}

void
concatenate_lists(struct student_info *info, char **source)
{
    char **temporary;
    size_t length;
    length = info->size;
    for (size_t i = 0 ; source[i] != NULL ; ++i)
        length++;
    temporary = realloc(info->courses, length * sizeof(*temporary));
    if (temporary == NULL)
        return;
    for (size_t i = 0 ; source[i] != NULL ; ++i)
        temporary[i + info->size] = strdup(source[i]);
    info->courses = temporary;
    info->size = length;
}


void
free_list(char **lines)
{
    if (lines == NULL)
        return;
    for (size_t i = 0 ; lines[i] != '\0' ; ++i)
        free(lines[i]);
    free(lines);
}

int 
main() 
{
    struct student_info info;
    char **lines;
    lines = load_file("data.tx");
    if (lines == NULL)
        return -1;
    info.courses = NULL;
    info.size = 0;
    for (size_t i = 0 ; lines[i] != NULL ; ++i)
    {
        char **courses;
        courses = extract_courses_as_list(lines[i]);
        if (courses == NULL)
            continue;
        concatenate_lists(&info, courses);
        free_list(courses);
    }

    for (size_t i = 0 ; i < info.size ; ++i)
    {
        fprintf(stderr, "%s\n", info.courses[i]);
        free(info.courses[i]);
    }
    free(info.courses);
    free_list(lines);

    return 0;
}

您会注意到我从未使用strdup(),原因是我们要复制的字符串的长度 始终已知。