C ++ «Ошибка шины: 10» и работа с указателями

0

Я выполняю упражнение Data Structures, и с вчерашнего дня я заблокирован ошибкой шины, что, по моему мнению, связано с тем, что я делаю плохие вещи с памятью. Но я не могу понять, что именно.

Это требования, которые я установил для практики:

  • возможность добавить продукт (любой способ будет делать) в список
  • способный получить продукт в списке в текущей позиции (next, prev, moveToStart, moveToEnd... там указатель курсора, называемый здесь "актуальным")
  • любые изменения, которые я делаю с извлеченным продуктом, должны обновляться в структуре данных (например, list :: retrieve (* product), product-> посещения ++)

Это код, который у меня есть. Извинения за имена var, я должен сделать это на испанском языке, и поэтому имена находятся на испанском языке.

class producto { // My product
public:
    string marca;
    double precio;
    int visitas;
    int compras;

    producto () {}
    producto (string M, double P, int V = 0, int C = 0) : marca(M), precio(P), visitas(V), compras(C) {}
};

class nodo {
public:
    producto valor; // value
    nodo *siguiente; // next
    nodo *anterior; // prev

    nodo (producto P, nodo *A = NULL, nodo *S = NULL) : valor(P), anterior(A), siguiente(S) {}
};

class lista { 
private: 
    nodo *inicio;
    nodo *final;
    nodo *actual;

public: 
    lista();
    bool esta_vacia(); // is empty?
    bool es_final(); // is the end?
    int insertar(producto p); // insert given p
    void moverPrincipio(); // "move to beginning"
    void siguiente(); // "next"
    void imprimir(); // "print"
    int leer(producto *p); // read, return 0 or 1 if successful, return product by ref
};

lista::lista() {
    this->inicio = NULL;
    this->final = NULL;
    this->actual = NULL;
}

bool lista::esta_vacia() {
    return (this->inicio == NULL);
}

bool lista::es_final() {
    return (this->actual == NULL);
}

void lista::moverPrincipio() {
    this->actual = this->inicio;
}

void lista::siguiente() {
    if(!this->es_final()) {
        this->actual = this->actual->siguiente;
    }
}

void lista::imprimir() {
    int i = 1;
    producto *p;
    this->moverPrincipio();

    while(!this->es_final()) {
        if(this->leer(p) == 0) {
            cout << i << ".- ##" << p->marca << "##, Views ##" << p->visitas << "##\n";
            p->visitas++;
            i++;
            this->siguiente();
        }
    }
}

int lista::leer(producto *p) {
    if(this->actual != NULL) {
        *p = this->actual->valor;

        return 0;
    } else {
        return 1;
    }
}

int lista::insertar(producto p) {
    if(this->esta_vacia()) {
        nodo *tmp = new nodo(p);
        this->inicio = tmp;
        this->final = this->inicio;
    } else {
        nodo *tmp = new nodo(p, this->final);
        this->final->siguiente = tmp;
        this->final = tmp;
    }

    return 0;
}

Я удалил ненужный код. Вот как я его использую (и терпеть неудачу):

lista *productos = new lista();

productos->insertar(producto("Shoes", 19.90));
productos->insertar(producto("Socks", 25.00));

// I should expect views = 0
productos->imprimir();

// But now, views = 1
productos->imprimir();

После выполнения единственное, что я получаю, это "Ошибка шины: 10" при первом запуске imprimir ("print"). Вставка работает без ошибок (но там тоже что-то не так).

Моя идея состоит в том, чтобы удерживать продукт внутри узла и давать ссылку на его местоположение при его возврате, так что любые изменения отражаются там тоже (например, увеличивать представление или счетчик покупки извлеченного элемента, отражает изменение при чтении список позже).

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

Благодарю!!

ОБНОВЛЕНИЕ Вот компилируемый пример.

  • 0
    Рассмотрим main() и некоторый исполняемый пример, который использует ваш код в качестве необходимого кода. Тем не менее, в lista::imprimir , код if(this->leer(p) == 0) , я спрашиваю вас: каково значение p в этом вызове?
  • 0
    @WhozCraig: хм. Хороший вопрос. Я просто хочу, чтобы функция «leer» сохраняла результат в «p», чтобы потом я мог использовать «p». Какой лучший способ сделать это? Я делаю это таким образом, так как я также хочу иметь возможность иметь коды ошибок в стиле Unix. Но, может быть, это не очень хорошая идея ...
Показать ещё 6 комментариев
Теги:
pointers

1 ответ

1
Лучший ответ

Вы передаете указатель на lista::leer и вы хотите записать ему значение. Вы будете писать в нераспределенной памяти. Наверное, то, что вы хотели, было указателем на actual элемент.

Прежде всего, вам нужно изменить подпись:

int lista::leer(producto **p);

обратите внимание на двойную звезду, так как мы будем писать сам указатель.

Затем вам нужно назначить указатель на actual->valor в lista::leer:

*p = &(this->actual->valor);

Наконец, вы должны передать указатель на p в lista::imprimir:

 if(this->leer(&p) == 0) {
     // ...
 }

Кроме того, вы можете изменить lista::leer чтобы вернуть указатель и проверить, является ли он nullptr/NULL.

  • 0
    Очень полезно. Я выбрал последний вариант, который возвращает указатель и проверяет, является ли он нулевым (если он не работает). Я ценю, что вы нашли время, чтобы тщательно объяснить оба варианта. Спасибо за тонну!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню