返回结构数组

时间:2018-02-09 21:20:01

标签: c pointers

我试图弄清楚如何修改我的代码以实际允许我在readFile中创建一个结构数组,然后将数组返回到main。

这是我的数据结构

struct data{

    char *model;
    float engineSize;
    int cost;
    char *color;
};

这是我当前设置的readFile函数,然后是我目前用于此函数的调用。

 struct data * readFile(){

    FILE *fp;
    int c;
    int count = 0;
    char *line = NULL;
    size_t len = 0;

    fp = fopen("hw3.data", "r");

    while ((c = fgetc(fp)) != EOF){

        count++;

    }

    if (feof(fp)){

        rewind(fp);

        struct data *vehicles = malloc((sizeof(struct data))* count);


        count = 0;
        char *token = NULL;
        while (getline(&line, &len, fp)!= -1){

            printf("%s", line);

            token = strtok(line,  " ");
            vehicles[count].model = token;

            token = strtok(NULL, " ");
            vehicles[count].engineSize = atof(token);

            token = strtok(NULL, " ");
            vehicles[count].cost = atoi(token);

            token = strtok(NULL, " ");
            vehicles[count].color = token;

        }

    }


}

这是我拥有菜单的主要地方,我将调用readFile函数。

int main(){

    int check = 1;
    int input;

    while (check == 1){

        printf("Enter a value corresponding to a option on the menu below\n\n");

        printf("1. Sort data by the float value & print high to low\n");
        printf("2. Sort data by the float value & print low to high\n");
        printf("3. Sort data by the int value & print high to low\n");
        printf("4. Sort data by the int value & print low to high\n");
        printf("5. Exit\n\n");

        printf("Enter a value corresponding to the above menu\n");
        scanf("%d", &input);

        //readFile()

        if(input == 1 || input == 2 || input == 3 || input == 4 || input == 5){

            if (input == 5){

                exit(0);

            }if (input == 1){

                //sort float high to low

            }if (input == 2){

                //sort float low to high

            }if (input == 3){

                //sort int value high to low

            }if (input == 4){

                //sort int value low to high

            }

        }else{

            printf("Enter a correct value for the menus above\n\n" );
        }

        readFile();

    }

}

由于

1 个答案:

答案 0 :(得分:2)

这几乎是正确的,这个想法还可以,但有一些问题:

while ((c = fgetc(fp)) != EOF){
        count++;
}

计算字节数,我想根据你想要的后面的代码 行数。

while ((c = fgetc(fp)) != EOF){
    if(c == '\n')
        count++;
}

会给你一些行数。

在那里

token = strtok(line,  " ");
vehicles[count].model = token;
...
token = strtok(NULL, " ");
vehicles[count].color = token;

是有效的,但也许不是你想要的。 strtok成功返回line + some_offset,因此如果您以后需要 您可以添加更多字符到vehicles[i].modevehicles[i].color 覆盖记忆。 vehicles[i].color只是偏移量 vehicles[i].model。如果您甚至想重新分配,realloc将失败, 因为你不会在请求的内存开头重新分配 块。通过这样做,你将失去所请求的内存的开始, 它会泄漏内存,因为你无法释放它(free(vehicles[i].color)是 无效) 1

另一个问题是只有初始线犯规才有正确数量 分配内存,如果你使用非getline指针调用NULL 非零长度,getline将在必要时重新分配内存并更新 指针和长度。如果重新分配返回相同的地址,那么你的 以前的值将被覆盖。如果重新分配返回a 不同的地址,你以前的指针将变为无效。

我建议(并且我认为这是唯一安全的方法)您使用strdup(如果可用,或malloc + strcpy执行令牌副本) 之后:

while (getline(&line, &len, fp)!= -1){
    // the strtok calls
    ...
    free(line);
    line = NULL;
    len = 0;
}

通过这种方式,您的代码不会泄漏内存,也不会覆盖内存。

修改

  

我应该改为使用strcpy设置模型和颜色的值

您可以使用strcpy,但您需要先分配内存,因为 modelcolor只是指针。 malloc只调用保留的内存, 它没有初始化它。所以只是做

strcpy(vehicles[count].model, token);

会出错,因为你会尝试复制未定义的东西 地点。这就是我的意思

  

我建议(并且我认为这是唯一安全的方法),您使用strdup(如果可用,或malloc + {{}执行令牌的副本1}})

strcpy

函数vehicles[count].model = malloc(strlen(token) + 1); if(vehicles[count].model == NULL) { // error handling // for example // free everything and return return NULL; } strcpy(vehicles[count].model, token); 基本上是这样做的:strdup + malloc,所以如果你的话 系统有strcpy你可以这样做:

strdup

另一个选择是改变你的结构,而不是指向 vehicles[count].model = strdup(token); if(vehicles[count].model == NULL) { // error handling // for example // free everything and return return NULL; } ,使用char数组:

char

现在你可以保存最大长度为99个字符的字符串(应该足够了) 对于模型名称和颜色而言,只需使用struct data{ char model[100]; float engineSize; int cost; char color[100]; }; ,而无需使用 额外的内存分配:

strncpy
  

此外,我还没有机会更改免费代码(line)line = null和len = 0

我不知道你的意思。只需在

之后添加行
strncpy(vehicles[count].model, token, sizeof vehicles[count].model);
// making sure to terminate the string
vehicles[count].model[sizeof(vehicles[count].model) - 1] = 0;
vehicles[count].color = token; 循环结束之前

  

那么我也应该像通过文件的第二次迭代一样使用get行,因为我目前正在分配?

第二个循环很好,问题是你被分配了相同的(+ 偏移)内存位置到不同的指针以及while何时重新分配 并获取一个不同的地址,前一个指针变为无效。这就是

的原因
getline

很重要,你肯定应该这样做。

总结一下:你的循环很好,但你需要做出这些改变:

  • 制作free(line); line = NULL; len = 0; 的副本或更改结构以使用token数组
  • 添加

    char
    循环结束时的

    行,你会没事的。

<强> fotenotes

1 free(line); line = NULL; len = 0; 只会指向内存的开头 阻止当且仅当该行不以空白空格开头时。就像你一样 阅读文件,你不能保证这是真的。即使它是 是的,我不会指望这一点。更好地做好安全的事情,做一个 复制。 vehicles[i].mode肯定是错的。