【问题标题】:Have One Struct Point To Another有一个结构指向另一个
【发布时间】:2017-11-09 00:29:07
【问题描述】:

我在创建两个结构时遇到问题,一个称为 Bag,另一个是 Card。这是我目前所拥有的:

struct Card 
{
   char suit;
   int value;

};

struct BagNode
{
   Card* Card;
   BagNode* next;
};

void fillWithCards(BagNode *&head, BagNode *&tail, BagNode *&temp) 
{
char suits [] = {'s', 'h', 'd', 'c'};
int val [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

for (int x = 0; x < 4 ; x++)
{
    for (int y =1 ; y <= 13 ; y++)
    {
        BagNode *now = new BagNode;
        now -> Card -> suit = suits [x];
        now -> Card -> value = val [y]; 

        if (*&head == NULL && *&tail == NULL && *&temp == NULL)
        {               
            head = now;
            tail = now;
            temp = now;
        }
        else if (*&tail != NULL && *&temp != NULL)
        {
            tail -> next = now;
            temp -> next = now;
            tail = now;
            temp = now;
        }
        else 
        {
            tail -> next = NULL;
        }
    }
  }
}

问题是当我编译和运行程序时它会崩溃。我感觉这个问题与Card* Card;有关

是的,我知道我可以在 Card 中拥有所有内容,即*next,我不需要BagNode。然而,在询问我的教授时,他说我们需要有两个结构,一个用于Bag,另一个用于Card

【问题讨论】:

  • 这是learn how to debug your programs的最佳时机。
  • 为什么会有多个 Bags 的链表,每个 Bag 只有一张卡片?那个包应该代表什么?一个包含多张卡片的包对我来说更有意义。

标签: c++ struct linked-list


【解决方案1】:
BagNode *now = new BagNode;

这会在动态范围内构造BagNode 的新实例。这个类没有构造函数。此类的所有成员都没有默认构造函数。因此,此类的新实例完全未初始化。紧接着:

now -> Card -> suit = suits [x];
now -> Card -> value = val [y]; 

由于类的新实例完全未初始化,这会尝试取消引用其完全未初始化的Card 成员、指针,从而导致未定义的行为、未初始化的指针取消引用和明显的崩溃。

显示的代码中可能存在其他问题,但无法最终分析它们,因为未提供Minimum, Complete, and Verifiable Example。唯一可以发表的其他评论:

if (*&head == NULL && *&tail == NULL && *&temp == NULL)

*&amp; 部分完全没有任何用处。这在逻辑上等价于:

if (head == NULL && tail == NULL && temp == NULL)

当然,这更具可读性和清晰性。

【讨论】:

    【解决方案2】:

    在使用 operator-&gt; 取消引用 Card* 指针之前,您没有初始化 now-&gt;Card 以指向有效的 Card 实例。 now-&gt;Card 是一个未初始化的指针,所以 Card-&gt; 正在访问无效的内存。

    您也没有初始化now-&gt;next。对于尚未插入列表的新节点,应将其初始化为 NULL,因为还没有节点跟随它。

    我建议将Card* Card; 更改为Card card;,然后使用operator. 而不是operator-&gt; 来访问Card 字段:

    struct BagNode
    {
       Card card; // <-- no '*' !
       BagNode* next;
    };
    
    ...
    
    BagNode *now = new BagNode;
    now->Card.suit = suits [x];
    now->Card.value = val [y]; 
    now->next = NULL; // <-- don't forget this!
    

    现在,话虽如此,您的其余代码没有意义。这不是一个好的链表插入,而且您对temp 参数的使用只会使其更加混乱。 temp 应该代表什么?如果head/tail 为 NULL 但temp 不为 NULL,则代码将崩溃。 temp 不属于这种代码。

    您也超出了val[] 数组的范围。数组是 0 索引的,而不是 1 索引的。 val[] 有 13 个元素,因此有效索引是 0-12,而不是 1-13。

    尝试类似的方法:

    struct Card 
    {
       char suit;
       int value;
    };
    
    struct Bag
    {
       Card card;
       Bag* next;
    };
    
    void fillWithCards(Bag* &head, Bag* &tail) 
    {
        const char suits[] = {'s', 'h', 'd', 'c'};
        const int val[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
    
        for (int x = 0; x < 4 ; x++)
        {
            for (int y = 0; y < 13; y++)
            {
                Bag *b = new Bag;
                b->card.suit = suits[x];
                b->card.value = val[y]; 
                b->next = NULL;
    
                if (!head)
                    head = b;
    
                if (tail)
                    tail->next = b;
                tail = b;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-26
      • 1970-01-01
      • 2017-07-13
      • 2018-04-25
      • 1970-01-01
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多