我的代码中有一个函数,它逐行读取一些文件并从中创建结构。一位教授对我说,可能有问题,并提到了幻影线。有人可以看到我的功能并向我解释问题出在哪里吗?
这是我的代码:
void readComponentList(ComponentList *cl, char *fileName)
{
FILE *file = fopen(fileName, "r");
if (file == NULL) { perror(fileName); exit(1); } // If the file doesn't exist, the program termitates with exit code 1
int r;
Component *c = newComponent(cl);
// Creates useful component c by inserting line informations as arguments in the structure
r = fscanf(file, "%24s %24s %24s %d %lf", c->type, c->model, c->unit, &(c->weight), &(c->price));
while (r != EOF) // Doing the same thing for the rest of the lines
{
c = newComponent(cl);
r = fscanf(file, "%24s %24s %24s %d %lf", c->type, c->model, c->unit, &(c->weight), &(c->price);
// Since EOF only occurs after an unsuccessful read attempt, an additional "phantom line" with undefined content is read in here, which could lead to crashes.
}
fclose(file);
}
这是我正在阅读的文件示例:
Motor M5x40 Stk 5 0.05
Elevator M5x60 Stk 6 0.05
ACM L-H-100 Stk 1250 530
SSM L-100 Stk 0 0
ElevatorW W3 Stk 0 0
Metal- kg 1000 344200
Component和ComponentList结构:
typedef struct
{
char type[25];
char model[25];
char unit[25];
int weight;
double price;
StepList *construction_steps;
} Component;
typedef struct
{
Component **components;
int count;
int allocated;
} ComponentList;
从发布的代码尚不清楚,但我认为这行
Component *c = newComponent(cl);
将1)创建一个新的Component元素,并将其2)插入到列表cl
因此,当您执行此操作之前调用fscanf
时,即使fscanf
失败,元素也已插入**。因此,您将在列表中得到一个“空”元素(又称为幻影元素)。
[为避免需要移动以下行:Component *c = newComponent(cl);
,以便仅在成功scanf
之后才调用它。
也许像:
Component tmp; // Scan into a local tmp variable
while (1)
{
r = fscanf(file, "%24s %24s %24s %d %lf",
tmp.type, tmp.model, tmp.unit, &tmp.weight, &tmp.price;
if (r == EOF) break;
if (r == 5)
{
// A complete struct was read so put it into the list
c = newComponent(cl);
*c = tmp; // Copy the tmp struct into the new element in the list
}
else
{
// Didn't get the expected number of vars scanned.
// Add error handling ....
}
}
编辑
由于OP关注第Component tmp;
行,因此这是另一种方法:
char type[25];
char model[25];
char unit[25];
int weight;
double price;
while (1)
{
r = fscanf(file, "%24s %24s %24s %d %lf",
type, model, unit, &weight, &price;
if (r == EOF) break;
if (r == 5)
{
// A complete struct was read so put it into the list
c = newComponent(cl);
strcpy(c->type, type);
strcpy(c->model, model);
strcpy(c->unit, unit);
c->weight = weight;
c->price = price;
}
else
{
// Didn't get the expected number of vars scanned.
// Add error handling ....
}
}