簡體   English   中英

動態分配結構C的數組

[英]Dynamically allocating array of structs C

我正在嘗試在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

代碼忽略了products價值。

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'; 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM