BerthaDusStuf Ответов: 4

Может ли кто-нибудь сказать мне, почему этот код ведет себя именно так?


#include <iostream>
#include <cstddef>
using namespace std;

struct cards
{
    int num;
    string suit;
    cards * next_card;
};

cards get_card(int num, string suit, cards *previous_card)
{
    cards card;
    card.num = num;
    card.suit = suit;
    card.next_card = previous_card;
    return card;
}

int main()
{
    cards *temp_card = NULL;
    string suit;

    for (int i = 0; i<4; i++)
    {
        if (i == 0){suit = "hearts";}
        if (i == 1){suit = "diamonds";}
        if (i == 2){suit = "clubs";}
        if (i == 3){suit = "spades";}
        for (int j = 0; j<13; j++)
        {
            cards sum_card = get_card(j+1, suit, temp_card);
            temp_card = &sum_card;
        }
    }
    while ((*temp_card).next_card != NULL)
    {
        cout <<(*temp_card).num <<" of ";
        cout <<(*temp_card).suit <<"\n";
        temp_card = (*temp_card).next_card;
    }
    cout <<"yis it work";
}


Это предназначено для печати всех карт в колоде карт, но он просто печатает одну и ту же карту снова и снова бесконечно. Может ли кто-нибудь заметить проблему?

Что я уже пробовал:

печенье сумму.......................................................................

Kornfeld Eliyahu Peter

Вы использовали отладчик для пошагового выполнения кода?

BerthaDusStuf

Нет я действительно не знаю как использовать отладчик

Kornfeld Eliyahu Peter

Как разработчик это должно быть знание - вы не можете начать слишком рано...

BerthaDusStuf

хорошо я постараюсь этому научиться

4 Ответов

Рейтинг:
8

Richard MacCutchan

Попробовать это:

#include <iostream>
#include <string>
using namespace std;

struct cards
{
    int num;
    string suit;
    cards * next_card;
};

cards* get_card(int num, string suit, cards *previous_card)
{
    cards* card = new cards;;
    card->num = num;
    card->suit = suit;
    card->next_card = previous_card;
    return card;
}

int main()
{
    cards *temp_card = NULL;
    string suit;

    for (int i = 0; i<4; i++)
    {
        if (i == 0){suit = "hearts";}
        if (i == 1){suit = "diamonds";}
        if (i == 2){suit = "clubs";}
        if (i == 3){suit = "spades";}
        for (int j = 0; j<13; j++)
        {
            cards* sum_card = get_card(j+1, suit, temp_card);
//            cout << sum_card->num << " of " << sum_card->suit << ", next: " << sum_card->next_card << endl;
            temp_card = sum_card;
        }
    }
    while (temp_card != NULL)
    {
        cout <<temp_card->num <<" of ";
        cout <<temp_card->suit <<"\n";
//        cout <<temp_card->next_card <<"\n";
        temp_card = temp_card->next_card;
    }
//    cout <<"yis it work";
}

Это могло бы сделать больше уборки, но это устраняет проблему использования одного и того же адреса временной структуры для каждой ссылки. Он также приводит в порядок разыменование элементов структуры и правильно перечисляет все карты.


BerthaDusStuf

Хорошо, спасибо, кто-то ранее предложил мне использовать новый, и теперь я вижу, как это сделать.

Рейтинг:
34

OriginalGriff

Потому что существует только одна карта, и вы продолжаете ее переписывать.
Для этого не имеет значения, объявляете ли вы переменную внутри или вне цикла: создается только одна переменная, вы не получаете "совершенно новую" каждый раз, когда обходите цикл.
Чтобы доказать это, посмотрите на адрес, который вы берете каждый раз и сохраняете в temp_card с отладчиком - это всегда будет один и тот же адрес.

Чтобы использовать новую карту каждый раз, вам нужно использовать либо массив (вероятно, лучший для колоды карт), либо malloc чтобы дать вам новую область памяти для хранения информации о вашей карте.


BerthaDusStuf

О, я думаю, что видел другие примеры использования цикла для создания нескольких элементов в связанном списке, используя одно и то же имя переменной в каждом цикле, но я думаю, что этот пример использовал new Для получения памяти из свободного хранилища. Может быть, тот факт, что я не использую бесплатный магазин, означает, что я не могу каждый раз называть переменную одним и тем же именем?

OriginalGriff

"новый" будет работать нормально - GB o back и следуйте этому примеру.

BerthaDusStuf

Итак, то, что вы говорите, используя new, позволяет вам называть несколько переменных одним и тем же? И какой пример?

OriginalGriff

Нет. Это сложно, и вам нужно узнать об указателях, ссылках и памяти, прежде чем вы собираетесь понять это правильно - вы не можете "изменить имя" переменной, но вы можете изменить то, к какой памяти она относится.

BerthaDusStuf

хорошо спасибо

Рейтинг:
24

Patrice T

cards это связанный список, вы должны выделить каждый узел вручную с помощью malloc().

cards get_card(int num, string suit, cards *previous_card)
{
    cards card; // here is the memory problem
    card.num = num;
    card.suit = suit;
    card.next_card = previous_card;
    return card;
}

Этот код динамически выделяет узел карт, проблема заключается в том, что узел освобождается кодом возврата из функции.
Иначе говоря, код просто возится с памятью.
ссылка на malloc - C++ [^]
-----
Ваш код ведет себя не так, как вы ожидаете, и вы не понимаете, почему !

Существует почти универсальное решение: запускайте свой код на отладчике шаг за шагом, проверяйте переменные.
Отладчик здесь, чтобы показать вам, что делает ваш код, и ваша задача-сравнить с тем, что он должен делать.
В отладчике нет никакой магии, он не знает, что вы должны делать, он не находит ошибок, он просто помогает вам, показывая, что происходит. Когда код не делает того, что ожидается, вы близки к ошибке.
Чтобы увидеть, что делает ваш код: просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.
Отладчик - Википедия, свободная энциклопедия[^]

Освоение отладки в Visual Studio 2010 - руководство для начинающих[^]
Базовая отладка с помощью Visual Studio 2010 - YouTube[^]
Отладчик здесь только для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.


BerthaDusStuf

Хорошо спасибо я не знаю как использовать отладчик но я посмотрю в него

Рейтинг:
20

CPallini

Если это подразумевается как упражнение в связанном списке, то вы, как уже отмечают другие, должны больше упражняться в списке linekd.
С другой стороны, если вам действительно нужно справиться с колодой карт в C++ программа, то связанный список, возможно, не лучший выбор. Попробуйте например

#include <vector>
#include <array>
#include <iostream>
using namespace std;

constexpr int VALUES = 13;
constexpr int SEEDS = 4;
constexpr int CARDS = VALUES * SEEDS;


class Card
{
  int v;

public:
  Card(int v):v(v){}
  int getValue() const { return (v % VALUES);}
  int getSeed() const { return (v / VALUES);}
  string getSeedDesc() const;
};

ostream & operator << ( ostream & os, const Card & card);


int main()
{
  vector <Card > card;

  for ( int n = 0; n < CARDS; ++n) card.emplace_back(Card(n));

  for (const auto & c : card) cout << c << endl;
}


ostream & operator << ( ostream & os, const Card & card)
{
  os << card.getValue() << " of " << card.getSeedDesc();
  return os;
}

string Card::getSeedDesc() const
{
  static array<string, SEEDS> desc = { "hearts", "diamonds", "clubs", "spades" };
  return desc[getSeed()];
}


BerthaDusStuf

О, Спасибо за решение, но я действительно не знаю, как использовать классы очень хорошо и некоторые другие вещи, которые вы использовали в своем коде, я делаю это только для того, чтобы практиковать использование связанных списков, но спасибо, извините, я должен был дать понять, что мне нужно было сделать это с помощью связанных списков

CPallini

Если вы не знаете, как использовать классы, то пришло время учиться.
В любом случае, попытка реализовать связанный список-это хорошее упражнение.

BerthaDusStuf

Да, я просматриваю книгу в порядке глав, и у меня есть представление о том, что такое классы, но у меня нет большого знания о синтаксисе их и о том, как их реализовать.