2014-12-06 3 views
0

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

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

  • возможность добавить продукт (любым способом будет делать) в список
  • умелым, чтобы получить продукт в списке при токе position (next, prev, moveToStart, moveToEnd ... здесь есть указатель курсора, называемый «актуальный»)
  • любые изменения, которые я делаю для полученного продукта, должны обновляться в структуре данных (например, list :: retrieve (* 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 («печать»), в первый раз. Вставка работает без ошибок (но там тоже что-то не так).

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

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

Спасибо!

ОБНОВЛЕНИЕHere's a compilable example.

+0

Рассмотрите 'main()' и некоторый исполняемый пример, который использует ваш код в качестве * необходимого * кода. Тем не менее, в 'lista :: imprimir', код' if (this-> leer (p) == 0) ', я спрашиваю вас: Каково значение' p' в этом вызове? – WhozCraig

+0

@WhozCraig: хм. Хороший вопрос. Я просто хочу, чтобы функция «leer» сохраняла результат в «p», чтобы впоследствии использовать «p». Каков наилучший способ сделать это? Я делаю это так, так как я также хочу иметь коды ошибок, unix-style. Но, может быть, это не очень хорошая идея ... –

+0

@WhozCraig: я обновил сообщение ссылкой на образец программы http://pastie.org/private/lpnhowywj7mxyzfa385kog –

ответ

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

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

Смежные вопросы