【问题标题】:Printing a dynamic array in C在 C 中打印动态数组
【发布时间】:2011-04-29 00:39:00
【问题描述】:

我正在用 C 编写一个程序。我在我的程序中使用了一个动态数组,并且正在使用一个 for 循环来循环遍历数组中的项目。我遇到的问题是,当我将列表打印到屏幕上时(在 for 循环中),列表中的所有先前项目都更改为最近创建的项目。我不知道这是什么原因造成的。我在 GDB 中查看了很多次代码,但仍然找不到问题所在。

/* For Loop, Displays Weapon List */
for (i = 1; i < num_places; i++)
{
    printf("%d. \n",i);
    printf("Des: %s \n\n",weap_List[i].description);
}

/* Add function, adds a weapon to the list */
int Add_weap(weapon new_weap) 
{
    if (num_places == num_allocated) 
    {
        if (num_allocated == 0)
                num_allocated = 3;
        else 
            num_allocated *= 2;
        void *_tmp = realloc(weap_List, (num_allocated * sizeof(weapon)));
        weap_List = (weapon*)_tmp;
    }
    num_places++;
    weap_List[num_places] = new_weap;
    return num_places;
}

/* Code that invokes the function, adding the weapon to the list */
printf("Adding new weapon \n");
weapon temp;
printf("Please enter the description of this new weapon. \n");
scanf("%s",weap.description);
Add_weap(temp);

/* Weapon structure */
typedef struct {
    char* description;
} weapon;

如果您能指出我正确的方向,那将不胜感激。

【问题讨论】:

  • 那么,当您打印武器列表时,它打印的所有内容都一样吗?
  • 查看weapon 的构造函数也会很有帮助。那,您将跳过数组的第 0 个插槽。
  • 嗯,这是 C,所以没有构造函数。但重点是正确的——你能告诉我们你是如何分配/初始化你的 weapon 结构的吗?

标签: c arrays list dynamic


【解决方案1】:

您在错误的时间增加了 num_places。

改变

  num_places++;
  weap_List[num_places] = new_weap;

  weap_List[num_places++] = new_weap;

【讨论】:

  • D'oh :) 错过了这个。不错的收获。
  • 是的,但这并不能解决 OP 的抱怨,即当他打印出来时,所有以前的元素都被更改为最近输入的 weapon。 sarnold——你能发布weapon结构的定义吗?我提到这一点是因为当我使用简单的struct weapon { char description[40]; }; 时,我没有遇到 OP 的问题。我确实遇到了你提到的第一个被跳过的问题,但我没有遇到 OP 的问题,即所有打印都是最新的。
  • 是的,如果我将其武器设为普通字符串,它就可以工作。如果我这样做是行不通的: char* description;我认为我在使用指针方面犯了一个基本错误,但我不确定。
  • 如果您的 description 字段是 char* description,您在哪里/如何为描述分配实际内存?
【解决方案2】:

一些快速的想法:

for (i = 1; i < num_places; i++)
{

num_places,作为一个数组索引,将从0开始。如果您的列表中只有零个或一个武器,此循环将严重失败。 (条件i &lt; num_places循环体的第一次迭代之后被检查。如果weap_List有一个元素(在索引0处),这个循环将访问未分配的内存并且不打印武器。在 0 开始数组处理循环。你应该容忍单索引数组的唯一时间是在将大量 FORTRAN 代码移动到 C 时; 从头开始​​时,按照 K&R 的意图使用零索引数组。:)

   void *_tmp = realloc(weap_List, (num_allocated * sizeof(weapon)));
   weap_List = (weapon*)_tmp;

如果_tmp 被声明为(weapon *) tmp = realloc(...),那么您就不需要在下一行使用(weapon *)

微小的挑剔:在添加第 196609 种武器时,将尺寸翻倍是相当昂贵的方法。考虑每次只增长八倍。 (我从你的名字猜测你可能不会连续几周每秒添加一项。)

小问题:避免使用_prefix 变量名,它们是为 C 运行时环境保留的。是的,几乎每个程序都使用它们,是的,我已经使用了它们,是的,这个可能是安全的 :) 但它们在技术上是保留的。一个普通的tmp 就足够了。

更大的挑剔:您没有检查来自realloc(3) 的返回值。它可能失败。您的应用程序应尽可能优雅地处理故障。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 2019-12-17
    相关资源
    最近更新 更多