[英]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.