0

我正在编写输入文件并将每个单词作为单独的 char* 读取的代码,如下所示:

char label[8];
char type[5];
char value[6];


while (!input.eof()) {
    input >> label;
    input >> type;
    input >> value;
    storeSymbols(label, type, value);
}

然后我将它设置为 char* 数组的一个元素,如下所示:

void storeSymbols(char* lab, char* type, char* val) {
    labels[symCount] = lab;
    types[symCount] = type;
    values[symCount] = val;
    symCount++;

}

但是,当我打印出 char* 数组的所有元素时,所有元素都与从文件中检索到的最后一个元素相同。例如,如果文档中有三个标签,分别定义为“一”、“二”和“三”,那么在第一次循环结束时,数组将包含“一”,第二次将包含“二”和“二”,第三次将包含“三”“三”和“三”。它还循环了一个额外的时间,将最后一个元素再次添加到数组中,使其成为数组中的四个“三”元素。有谁知道为什么会这样?

我还测试了这个,我将 value 转换为 int 并将其添加到 int 数组中,它工作正常。

4

2 回答 2

0

您显然使用的是 C++,而不是 C,所以使用std::string而不是char *存储标签,而vector不是数组来存储标签等。

所以:

std::vector<std::string> labels, types, values;

std::string label, type, value;
input >> label >> type >> value;

labels.push_back(label);
types.push_back(type);
values.push_back(value);

您重复看到相同输出的原因是因为您将指针推送到相同的固定全局数组,该数组被重复覆盖input >> labelstd::string通过复制和分配内部缓冲区(全部自动完成)来避免这种情况。

于 2013-03-11T02:09:40.300 回答
0

读取输入的循环只是将每个项目存储到之前使用的同一个缓冲区中。例如,每次input >> label将读取的项目存储到同一个缓冲区中。char label[8]因此,在任何时候,该label数组都只包含最近读取的项目。

然后,当您尝试保存该信息时,storeSymbols()您传入label数组的地址 - 每次都使用相同的地址。所以labels数组的每个元素(我假设它是一个数组char*)都得到相同的指针——它们每个都指向同一个正在更新的缓冲区。

可以让您存储指向不同项目的指针的简单更改可能是用于strdup()复制字符串。如果您不允许strdup()在作业中使用,则可以在不到 10 行代码中将等价物编写为函数。

如果您使用strdup(),您不存储指针的字符串将被动态分配,因此您需要在使用完它们后释放它们:

for (i = 0; i < symCount; ++i) {
    free(labels[i]);
    free(types[i]);
    free(values[i]);
}

对于您关于在从输入中读取最后一个项目后循环额外时间的问题,用于读取输入的循环使用EOF直接检查的反模式。EOF在输入流为“空”时实际尝试执行读取之前不会设置。请参阅为什么“while (!feof (file))”总是错误的?http://drpaulcarter.com/cs/common-c-errors.php#4.2

尝试:

while (input >> label >> type >> value) {
    storeSymbols(label, type, value);
}

此外,请确保您的输入缓冲区足够大以容纳您的数据(请记住空终止符)。理想情况下,您会使用在读取输入时会动态扩展的数据类型(如std::string)。

于 2013-03-11T14:12:51.020 回答