0

私はデータ構造の演習を行っていますが、昨日からバス エラーでブロックされています。これは、メモリで悪いことをしているためだと思います。しかし、私は正確に何を理解することはできません。

これらは、私が実践のために確立した要件です。

  • 製品をリストに追加できる (どのような方法でも構いません)
  • 現在の位置にあるリスト内の製品を取得できます (next、prev、moveToStart、moveToEnd... ここでは「実際」と呼ばれるカーソル ポインターがあります)
  • 取得した製品に加えた変更は、データ構造で更新する必要があります (つまり、list::retrieve(*product)、product->visits++)。

これは私が持っているコードです。変数名についてお詫び申し上げます。スペイン語で行う必要があるため、名前はスペイン語です。

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();

実行時に、最初に imprimir ("print") を実行したときに "Bus error: 10" だけが表示されます。挿入はエラーなしで機能します (ただし、何か問題がある可能性もあります)。

私の考えは、製品をノード内に保持し、それを返すときにその場所への参照を与えることです。これにより、変更もそこに反映されます(たとえば、取得した要素のビューまたは購入カウンターを増やし、読み取り時に変更を反映します)リストは後述)。

私がここでやっている間違いを誰かが指摘できれば、私は非常に感謝しています。

ありがとう!!

更新 これはコンパイル可能な例です。

4

1 に答える 1

1

ポインターを渡し、lista::leerそれに値を書き込みたいとします。未割り当てメモリに書き込みます。おそらく、あなたが欲しかったのはactual要素へのポインタでした。

まず、署名を変更する必要があります。

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

ポインター自体を記述するため、二重星に注意してください。

次に、次のようにポインターを割り当てる必要があります。actual->valorlista::leer

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

最後に、pinへのポインターを渡す必要がありlista::imprimirます。

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

lista::leerまたは、ポインターを返すように変更して、それがnullptr/かどうかを確認することもできNULLます。

于 2014-12-06T12:27:16.730 に答える