2014-12-06 31 views
0

我正在做一個數據結構的練習,並且自從昨天以來我一直被阻塞,總線錯誤,我認爲是因爲我用內存做壞事。但我無法弄清楚究竟是什麼。C++「總線錯誤:10」和使用指針

這些是我已經建立了實踐的要求:

  • 能產品(任何方式都行)添加到列表
  • 能夠在當前檢索列表中的產品位置(next,prev,moveToStart,moveToEnd ...這裏有光標指針,這裏稱爲「actual」)
  • 我對檢索到的產品所做的任何更改都應該在數據結構中更新(即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打印時(「打印」),第一次。插入工作沒有錯誤(但也有可能是錯誤的)。

我的想法是將產品放置在節點內,並在返回時給出其位置的參考,以便所有更改都反映在此處(例如,增加檢索元素的視圖或購買計數器,反映稍後閱讀列表時的更改)。

如果有人能指出我在這裏所犯的錯誤,我將非常感激。

謝謝!

UPDATEHere's a compilable example

+0

考慮'main()'和一些可執行的例子,它將你的代碼作爲*必需*代碼使用。這就是說,在'lista :: imprimir'中,代碼'if(this-> leer(p)== 0)',我問你:在那個調用中'p'的值是多少? – WhozCraig 2014-12-06 12:07:01

+0

@WhozCraig:嗯。好問題。我只是希望「leer」函數將結果存儲在「p」中,以便後面可以使用「p」。什麼是最好的方法來做到這一點?我這樣做,因爲我也希望能夠有錯誤代碼,unix風格。但也許這不是一個好主意...... – 2014-12-06 12:08:43

+0

@WhozCraig:我更新了一個鏈接到示例程序的帖子http://pastie.org/private/lpnhowywj7mxyzfa385kog – 2014-12-06 12:11:45

回答

1

你傳遞一個指針到lista::leer並且你想給它寫一個值。你將在未分配的內存中寫入。可能,你想要的是指向actual元素的指針。

首先,您需要修改簽名:

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

注意雙星,因爲我們會寫指針本身。

然後,你有一個指針分配給actual->valor它在lista::leer

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

最後,你必須在lista::imprimir指針傳遞給p

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

另外,您可能會修改lista::leer以返回一個指針並檢查它是否爲nullptr/NULL

+0

非常有用。我去了最後一個選項,它返回一個指針並檢查它是否爲null(如果它是我很感激你花時間仔細解釋兩個選項,謝謝你N! – 2014-12-06 13:23:39