2016-05-01 20 views
1

Lassen Sie mich zuerst sagen, ich habe keinen Zugriff auf Debugger und ich bin mit Nano als meinen EditorC++ Hexadezimal Multiplikation Segmentation Fault

Derzeit mit meinem Rechner, ich schlage den Kopf gegen einen Ziegel Wand (Segmentierungsfehler). Ich habe versucht, durch meine Hinweise herauszufinden, was mein Problem ist, aber mein Mangel an Erfahrung/Wissen hat mich nur so weit gebracht. Lassen Sie mich erklären, was bisher in meinem Programm funktioniert. Momentan kann ich hexadezimale Zahlen in einer verketteten Liste speichern und sie addieren. Das Problem kommt von meiner Multiplikationsmethode. Irgendwie wird leftNode mitten in der Multiplikationsmethode NULL, was zu einem Segmentierungsfehler führt. Ich frage mich, an welchem ​​Punkt wird leftNode NULL?

Multiplikationsverfahren:

LList Calculator::multiply(LList& left, LList& right) { 
    LList prodSum; 
    listnode *leftNode = (left.next()); 
    int zeros = 0; 
    for(;;) { 
     if(leftNode == NULL) break; 
     int lval = leftNode->data; 
     LList curList; 
     for(int i = 0; i < zeros; i++) { 
      curList.insertTail(0); 
     } 
     right.reset(); 
     listnode *rightNode = (right.next()); 
     int carry = 0; 
     while(rightNode != NULL) { 
      int rval = rightNode->data; 
      int product = lval * rval + carry; 
      carry = product/16; 
      product %= 16; 
      curList.insertTail(product); 
      rightNode = (right.next()); 
     } 
     while(carry) { 
      curList.insertTail(carry % 16); 
      carry /= 16; 
     } 
     prodSum = *add(prodSum, curList); 
     leftNode = (left.next()); // eventually causes a segmentation fault 
     leftNode->data << endl; 
     ++zeros; 
    } 

    return prodSum; 
} 

Klassen zur Multiplikation bezogen werden:

class listnode { 
    public: 
     element data; 
     listnode * next; 
}; 

class LList { 
    private: 
     listnode * head; 
     listnode * tail; 
     listnode * view; 

    public: 
     LList(); 
     ~LList(); 
     void read(); 
     listnode* next(); 
     void reset(); 
     void print(); 
     void insertTail(element val); 
     void clean(); 

     element deleteHead(); 
}; 

class Calculator { 
    public: 
     Calculator(); 
     //inline LList* add(LList& left, LList& right); works 
     inline LList multiply(LList& left, LList& right); 
}; 

Calculator::Calculator() { 

}; 

Andere Verfahren zum Durchqueren Knoten verbunden:

listnode* LList::next() { 
    listnode* temp = view; 
    if(temp != NULL) 
     view = view->next; 

    if(view == NULL) { 
    } 
    return temp; 
}; 

void LList::reset() { 
    view = head; 
} 


LList::LList(){ 
    head = NULL; 
    view = NULL; 
}; 

void LList::insertTail(element val) { 
    listnode * temp; 
    temp = new listnode; 
    temp -> data = val; 
    temp -> next = NULL; 

    if(head == NULL) { 
     head = temp; 
     view = head; 
    } 
    else 
     tail -> next = temp; 
    tail = temp; 
}; 

void LList::clean() { 
    while(head != NULL) 
     deleteHead(); 
}; 

element LList::deleteHead() { 
    listnode * temp; 
    temp = head; 
    head = head -> next; 
    delete temp; 
    return temp -> data; 
}; 

LList::~LList(){ 
    delete head; 
}; 
+1

Welches Problem? Was ist deine Frage? –

+0

Warum erhalte ich einen Segmentierungsfehler in meiner Multiplikationsfunktion? – Aaron

+3

* Ich habe keinen Zugriff auf Debugger * - Also, wie willst du alles nicht-trivial schreiben? Wirst du das Programm "in deinem Kopf" ausführen, um nach Fehlern zu suchen?Oder erwarten Sie, Programme beim ersten Mal perfekt zu schreiben und brauchen sie nie zu debuggen? Holen Sie sich einen Debugger. – PaulMcKenzie

Antwort

1

ich bin es wieder.

Eine Ausnahme tritt nach der Zeile, die Sie markiert: // eventually causes a segmentation fault, scheint es eine teilweise gebildete Linie zu sein für leftNode->data-cout senden, aber auf der letzte Iteration durch die Knoten der linken, wird leftNode = (left.next());leftNode auf NULL gesetzt, so dass ein dereferenzieren hier könnte den Fehler verursachen.

Ein anderes Problem ist, dass kein Kopierkonstruktor oder kein Zuweisungsoperator für LList definiert ist, daher gibt diese Zeile: prodSum = *add(prodSum, curList); prodSum einen Satz von Listenknoten, die gleich danach gelöscht werden.

Der Destruktor von LList scheint jedoch nur den Kopfknoten zu löschen, nicht die ganze Liste, also gibt es einen Sammelbehälter mit ungültigem und gültigem Inhalt.

Multiplizieren Sie auch prodSum, so dass das Fehlen eines Kopierkonstruktors etwas ähnliches passieren lässt.

Ich schließe eine Version Ihres Codes ein, die zu funktionieren scheint. Ich musste meine eigene add Funktion machen, nur weil ich es hier nicht sehe.

Ich machte den Destruktor alle Llist-Knoten zu löschen.

Ich markiert den Standard-Kopierkonstruktor und Zuweisungsoperator =delete, weil die Standardimplementierungen das Falsche tun.

Um LList-Objekte nach Wert zu übergeben, habe ich einen Move-Konstruktor und einen Move-Zuweisungsoperator hinzugefügt. Diese übergeben zugewiesene Knoten von einem Objekt zum anderen, und nur ein Objekt darf einen Knotensatz behalten, so dass Sie sich keine Gedanken über Doppelzerstörung machen müssen.

#include <iostream> 
#include <string> 

typedef int element; 

class listnode { 
    public: 
     element data; 
     listnode * next; 
}; 

class LList { 
     listnode *head, *tail, *view; 
    public: 
     LList() { head = view = tail = NULL; } 
     LList(LList&& src) : head(src.head), tail(src.tail), view(src.view) { src.head = src.tail = src.view = nullptr; } 
     LList(const LList&) = delete; 
     ~LList() { clean(); } 
     LList& operator = (LList&& src) { 
      clean(); 
      /* OK here */ 
      head = src.head; 
      tail = src.tail; 
      view = src.view; 
      src.head = src.tail = src.view = nullptr; 
      return *this; 
     } 
     LList& operator = (const LList&) = delete; 
     listnode* next() { 
      listnode* temp = view; 
      if(temp) view = view->next; 
      return temp; 
     } 
     void reset() { view = head; } 
     void print(); 
     void insertTail(element val) { 
      listnode* temp = new listnode; 
      temp->data = val; 
      temp->next = NULL; 

      if(!head) { view = head = temp; } 
      else  { tail->next = temp; } 
      tail = temp; 
     } 
     void clean() { while(head) deleteHead(); } 

     element deleteHead() { 
      listnode* temp = head; 
      head = head->next; 
      const element data = temp->data; 
      delete temp; 
      return data; 
     } 
}; 

LList add(LList& left, LList& right) { 
    LList sum; 
    int carry = 0; 
    left.reset(); 
    right.reset(); 
    for(;;) { 
     const listnode* leftNode = left.next(); 
     const listnode* rightNode = right.next(); 
     if(!leftNode && !rightNode) break; 
     if(leftNode) carry += leftNode->data; 
     if(rightNode) carry += rightNode->data; 
     sum.insertTail(carry % 16); 
     carry /= 16; 
    } 
    if(carry) sum.insertTail(carry); 
    return sum; 
} 

LList multiply(LList& left, LList& right) { 
    LList prodSum; 
    listnode *leftNode = left.next(); 
    int zeros = 0; 
    for(;;) { 
     if(!leftNode) break; 
     int lval = leftNode->data; 
     LList curList; 
     for(int i = 0; i < zeros; i++) { 
      curList.insertTail(0); 
     } 
     right.reset(); 
     listnode *rightNode = right.next(); 
     int carry = 0; 
     while(rightNode) { 
      int rval = rightNode->data; 
      int product = lval * rval + carry; 
      carry = product/16; 
      product %= 16; 
      curList.insertTail(product); 
      rightNode = right.next(); 
     } 
     while(carry) { 
      curList.insertTail(carry % 16); 
      carry /= 16; 
     } 
     prodSum = add(prodSum, curList); 
     leftNode = left.next(); // eventually causes a segmentation fault 
     //std::cout << leftNode->data << std::endl; 
     ++zeros; 
    } 
    return prodSum; 
} 

LList string_to_list(std::string hex_string) { 
    LList list; 
    for(size_t i=hex_string.length()-1; i+1; --i) { 
     char c = hex_string[i] | 0x20; 
     if  (c >= '0' && c <= '9') list.insertTail(c - '0'); 
     else if(c >= 'a' && c <= 'f') list.insertTail(c - 'a' + 10); 
    } 
    return list; 
} 

std::string list_to_string(LList& list) { 
    std::string hex_string; 
    list.reset(); 
    for(;;) { 
     listnode* node = list.next(); 
     if(!node) return hex_string; 
     static const char digits[] = "abcdef"; 
     hex_string = digits[node->data] + hex_string; 
    } 
} 

int main() { 
    //LList list = string_to_list("1234aBcd"); 
    //std::string s = list_to_string(list); 
    //std::cout << s << '\n'; 

    LList left = string_to_list("111"); 
    LList right = string_to_list("333"); 
    LList prod = multiply(left, right); 
    std::cout << list_to_string(prod) << '\n'; 
} 
+0

Mein Retter! Danke nochmal Freund. – Aaron

+0

* Ich habe den Standardkopiekonstruktor und den Zuweisungsoperator = delete markiert, weil die Standardimplementierungen das Falsche tun. * - Sie müssen nur den Kopierkonstruktor schreiben, und der Zuweisungsoperator kann mit Kopieren/Tauschen implementiert werden. Ich erwähnte das bereits im Kommentar [hier] (http://stackoverflow.com/questions/36961466/c-hexadecimal-calculator-multiplication) – PaulMcKenzie

+0

@Xarotic Ich vergaß etwas über diese Zeile zu erwähnen: 'prodSum = * add (prodSum , curList); 'Wenn' add' einen Zeigerwert zurückgibt, der gelöscht werden muss, werden Sie den Wert des Zeigers verlieren und Speicher verlieren. Außerdem ist der Wert eines Pointer-Objekts ein lvalue, also müssen Sie Pauls genialen Copy-Konstruktor hinzufügen, um das überhaupt funktionieren zu lassen, weil ich nur hinzugefügt habe, was nötig war, um mein Beispiel funktionieren zu lassen. –