c - 动态分配结构体数组 C

标签 c arrays pointers struct malloc

我正在尝试用 c 语言创建一个结构数组,但无法使其工作。当我尝试运行它时,程序崩溃了。

typedef struct{
    char name[20];
    char manufacturer[20];
    unsigned int price;
} product;

unsigned int stringToNr(char *numbers){
   unsigned int nr = 0; 
   unsigned int i; 
   for (i = 0; i < strlen(numbers); i ++)
   {
       nr  *= 10; nr += numbers[i] - '0'; 
   }
   return nr; 
} 

我有一个函数可以将列表打印到文件中,有时它会到达这个函数,有时它会崩溃。

void printList(product *products, unsigned int nr){
    unsigned int i;
    FILE *f;
    f = fopen("output.txt", "w");
    for (i = 0; i < nr; i ++){
        fprintf(f, "%s ", products[i].name);
        fprintf(f, "%s ", products[i].manufacturer);
        fprintf(f, "%d\n", products[i].price);
    }
    fclose(f);
}

我必须使用单独的函数从文件中读取列表。

void readList(product **products, unsigned int *nr){
    FILE *f;
    f = fopen("input.txt", "r");
    char *row;
    row = malloc(sizeof(char) * 45);
    unsigned int rowLength;
    fgets(row, 45, f);
    rowLength = strlen(row);
    if (row[rowLength - 1] == '\n'){
        rowLength--;
        row[rowLength ] = '\0';
    }
    *nr = stringToNr(row);
    products = malloc((*nr) * sizeof(product*));
    unsigned int i;
    char *rowElement;
    for (i = 0; i < *nr; i ++){
        fgets(row, 45, f);
        rowElement = strtok(row, " ");
        strcpy((*products)[i].name, rowElement);
        rowElement = strtok(NULL, " ");
        strcpy((*products)[i].manufacturer, rowElement);
        rowElement = strtok(NULL, " ");
        rowLength = strlen(row);
        if (row[rowLength- 1] == '\n'){
            rowLength--;
            row[rowLength] = '\0';
        }
        (*products)[i].price = stringToNr(rowElement);
    }
    free(row);
    fclose(f);
}

显然该程序有更多功能,但这些功能运行良好。

int main(){
    product *products;
    unsigned int nr;
    readList(&products, &nr);
    printList(products, nr);
    free(products);
    return 0;
}

我的输入文件如下所示:

   3
   AAA FactoryA 300
   BBB FactoryC 550
   ZZZ Factory5 100

最佳答案

代码忽略产品的值。

readList()products 中接收到的内容都会被 malloc() 调用覆盖。

void readList(product **products, unsigned int *nr){
    ...
    // bad
    products = malloc((*nr) * sizeof(product*));

相反,请使用*products。还按引用变量的大小分配,而不是按类型的大小分配。更容易编码、审查和维护。

    *products = malloc(sizeof *(*products) * (*nr));
    if (*products == NULL) Handle_OOM();

次要:在 fgets(row, ..., ...); 之后,以下内容不安全,不会被黑客利用读取初始空字符。

    rowLength = strlen(row);
    // What happens when rowLength == 0
    if (row[rowLength- 1] == '\n'){
      ...

相反,代码可以使用下面的代码来删除可选的尾随'\n'

    row[strcspn(row, "\n")] = '\0'; 

关于c - 动态分配结构体数组 C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41495434/

相关文章:

c - 从具有意外长度的函数返回字符串?

c++ - 使用 C/C++ 设置 Linux IP

javascript - 为什么创建数组时需要 "new"关键字?

javascript - 使用点表示法中的路径数组动态创建对象

c - 如何在 C 中使用 malloc() 分配结构数组?

c - 用于支持和不支持 VARIADIC 的编译器的 printf 宏

c - 段错误,分配给c中的双指针

python - 如何在 python 中平滑具有不同高斯函数的二维数组的元素?

c++返回自定义结构类型-错误

c - 何时将指针参数传递给函数