【问题标题】:Assignment of specific char* array element setting all elements of array to that element - C++分配特定的 char* 数组元素,将数组的所有元素设置为该元素 - C++
【发布时间】:2013-03-11 01:54:49
【问题描述】:

我正在编写输入文件并将每个单词作为单独的 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 数组中,它工作正常。

【问题讨论】:

  • 第二位代码是否也在第一位代码的循环内?
  • 我认为我们需要更多代码。
  • 您需要复制/复制字符串,而不是一遍又一遍地分配指向同一个缓冲区的指针(这就是您现在正在做的事情)。
  • 不,第二位在单独的方法中,三个数组是全局变量。另外,你还想要什么代码?
  • 所显示的 sn-ps 给人的印象是您正在迭代 complete 输入,首先丢弃收集到的任何信息,然后只分配最后读取的值。跳过整个输入后,仅将 symCount 一次从 0 增加到 1。要准确了解发生了什么,需要更多代码。

标签: c++ arrays char


【解决方案1】:

读取输入的循环只是将每个项目存储到之前使用的同一个缓冲区中。例如,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 直到您在输入流为“空”时实际尝试执行读取时才设置。见Why is “while ( !feof (file) )” always wrong?http://drpaulcarter.com/cs/common-c-errors.php#4.2

试试:

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

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

【讨论】:

    【解决方案2】:

    您显然使用的是 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 &gt;&gt; label 反复覆盖。 std::string 通过复制和分配内部缓冲区来避免这种情况(全部自动完成)。

    【讨论】:

    • 问题是这是我正在上的一门课的可选练习,老师告诉我们我们只能使用 char*,因为她希望我们主要专注于 C 语言编码。不能告诉你为什么,但这就是她想要的。
    • 大错特错。只是……错了。你有 C++,但你被要求用 C 编写代码。这会让可怜的 C++ 程序员认为他们除了棍子和石头没有更好的东西可以使用。我声称你应该跳过作业并告诉老师,如果她想让你使用 C,她应该教 C 而不是 C++。
    • 这是班上每个人都在说的。我可能只使用 std::string 而不是冒着被扣分的风险。可能是最好的。
    • 在我看来,另一种选择是直接使用 C。抛弃 iostream 的东西,只写基本的 C。这也很有教育意义,以它自己的方式,你不会把两种语言搞得一团糟。
    • @PatrickHenry 如果你被要求用 C 编写代码,那么无论如何你都不应该对输入流使用&gt;&gt; 运算符,否则你会因此而失分。
    猜你喜欢
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多