链表C++赛格错误

Linked List C++ Seg fault

本文关键字:错误 C++ 链表      更新时间:2023-10-16

我正在尝试从头开始制作一个简单的链表,供另一个类使用。错误似乎是有时头部未设置为 NULL。我说有时之前它不会一直出错。它没有出错的时候,它会转到 else 语句。注意我只添加 1 个字符串。也许你们能发现一些我没有看到的东西,干杯!

LinkedList.h:

#include <string>
#include "Link.h"
using namespace std;
class LinkedList {
  Link *head;
public:
  LinkedList();
  void addFront(string key);
  void printList();
  //void addBack(string *);     
};

链接列表.cpp:

#include <cstring>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include "LinkedList.h"
using namespace std;
LinkedList::LinkedList() {
   head = NULL;
}
void LinkedList::addFront(string key) {
  //creates the new list segment                                                
  Link *l = new Link(key);
  cout << "Made new Link " << key << endl;
  // if the list is empty                                                 
  if (head == NULL){
    cout << "Going to set Head " << key << endl;
    head = l;
    cout << "Set Head to new link " << key << endl;
 }                                            
  else {             
     cout << "Else statement " << key << endl;                  
    l->setNext(head);
    head = l;
  }
}
void LinkedList::printList() {
 //Check if list is empty
  if(head == NULL)
   cout << "NULL" << endl;
  else {
   Link *l = head; 
   for(;l != NULL; l=l->getNext())
     cout << l->getValue() << endl;
  }

}
// void LinkedList::addBack(string *f) {
//   Link *l = new Link(f);
// }

链接.h

#include <cstdlib>
#include <cstring>
#include <string>
using namespace std;
class Link {
string key;
Link *next;
public:
    Link(string key);
    void setValue(char);
    void setNext(Link *next);
    string getValue();
    Link *getNext();
    void printList();
};

链接.cpp

#include <cstdlib>
#include <string>
#include <iostream>
#include "Link.h"
using namespace std;
Link::Link(string key) {
    this->key = key;
next = NULL;
}
void Link::setNext(Link *l) {
cout << "setting new link "<<endl;
next = l;
cout<< "New link was set" << endl;
}
string Link::getValue() {
return key;
}
Link *Link::getNext() {
return next;
}

哈希.h

#include <iostream>
#include <cstring>
#include <string>
#include "LinkedList.h"
using namespace std;
class Hash{
    //100 slot array for hash function
    LinkedList *hashFN[100];
    //preset prime number                                                               
  int prime = 101;
    int key;
  unsigned int location;
public:
    //Note: Both the key & values are the same 
    void insert(string key, string value);
    // void deleteItem(int key);
    // char* find(int key);

};

哈希.cpp:

#include <iostream>
#include <cstring>
#include <string>
#include "Hash.h"
using namespace std;
void Hash::insert(string k, string v){
    //Get Hash for argv[2] aka value                                                  
  size_t key = std::hash<string>()(k);
   unsigned int location;
//check 1                                                                         
  cout << "Hash: " << key << endl;
  //Find location
  location = key % prime;
  //check 2                                                                         
  cout << "Mod 101 Hash: " << location << endl;
    hashFN[location]->addFront(k);
    cout << "Success!" << endl;
}
// void Hash::deleteItem(int key){
//  return;
// }
// char* Hash::find(int key){
//  return;
// }

主.cpp

#include <iostream>
#include <functional>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include "Hash.h"                                                                   
using namespace std;
int main(int argc, char *argv[]) {
  Hash HashTable;                                                                   

  string Insert = string("insert");
  string Delete = string("delete");
  string Find   = string("find");
  string Argv(argv[2]);  //Makes the argv[2] into string type
  // check for Request & string parameters                                            
  if(argc != 3) {
    cout << "Run program with 2 parameters. [Lower Case]" << endl;
    cout << "[1] insert, find, or delete" << endl;
    cout << "[2] string" << endl;
    exit(1);
  }
  //Check for "insert"                                                                
  if(strcmp(argv[1], "insert") == 0) {

  HashTable.insert(Argv, Argv);                                                
  }
  return 0;
}

您的直接问题:哈希表中的链表数组是一个指针数组。声明为:

LinkedList *hashFN[100];

您似乎从未分配过这些对象中的任何一个。 所以你只有一个由 100 个不确定的垃圾指针组成的指针数组。要么分配它们,要么更好的是,直接实例化它们:

LinkedList hashFn[100];

这将要求您更改对它们的引用,例如

hashFN[location]->addFront(k);

变成这样:

hashFN[location].addFront(k);

接下来,您将使用非常量成员变量prime作为哈希函数的模数。由于这是硬编码为101,因此您的表需要具有相同的大小。(事实上,我会完全丢失成员变量,只是您的 Hash.cpp 文件中的静态常量)。但除此之外,问题仍然存在。您的桌子太小了一个插槽。您的模数可以来自 0..100 ,这意味着您需要一个大小[101]的表来处理所有这些插槽。请记住,C/C++ 中的数组[0...(n-1)]针对大小为 n

所以至少像这样声明你的表:

LinkedList hashFN[101];

我要发布的最后一件事。您的链表像泰坦尼克号一样泄漏。销毁列表时,您需要清理所有这些节点。在类中声明析构函数:

virtual ~LinkedList();

并在您的.cpp文件中实现它:

LinkedList::LinkedList()
{
    while (head)
    {
        Link *victim = head;
        head = head->getNext();
        delete victim;
    }
}

好吧,我撒谎了。还有一件事,在你对阅读理解三法则感到满意之前,你应该让你的班级不可复制。将以下内容放在 LinkedList 类声明的私有部分中:

class LinkedList
{
   ... other code...
private:
    LinkedList(const LinkedList&);
    LinkedList& operator =(const LinkedList&);
};

这将隐藏可能导致重大问题的事情,直到您准备好正确实施它们。如果您发现自己有"无法访问私人会员LinkedList(const LinkedList&)的错误",那么您正在尝试制作副本,并且没有适当保护您的头部指针,这是不行的。阅读三法则

剩下的我留给你。

注意:有一些方法可以使用标准库(std::vector<>std::unordered_map<>等)更轻松地完成此操作。 事实上,std::unordered_map<>所有这些的直接替代品。但是,如果您只是对使用语言再次熟悉感兴趣,那么暂时开始裸机也不错。只需专注于重新学习,然后学习使用标准库必须提供的所有精美代码。