我正在尝试在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
答案 0 :(得分:4)
代码忽略products
的值。
readList()
来自products
的{{1}}收到的内容会被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';