【问题标题】:Add node to front of linked_list is allowing or repeat nodes将节点添加到linked_list 的前面是允许或重复节点
【发布时间】:2019-08-05 15:49:43
【问题描述】:

在尝试将节点添加到链表的前面时,无法弄清楚我的逻辑哪里出错了。该程序允许双输入和重复节点。现在看看逻辑一段时间,并继续似乎确定我哪里出错了。问题一定很简单,我在看它。似乎继续将其添加到相同的linked_list而不是每个用户不同的列表 导致 are 的输入是 山姆 P丽莎 P 标记 帕米 F丽莎艾米 菲丽莎马克 F艾米山姆

执行后问题就很清楚了

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cstring>

using namespace std;
void menu_function(void);
void command_execute( string command, string name1, string name2);
int hash_function(string str);
void insert_into_hashtable( int ascii_total, string name);
void add_friendship( int ascii_key, string name );
void print_friendships( int aascii_key);
void check_friendship( int ascii_key, string name);
void remove_friendship( int ascii_key, string name );

#define SIZE 150

struct friend_list
{
    string name;
    struct friend_list* next;
};

typedef struct friend_list list;

struct user{
    string name;
    int key;
    friend_list* FriendList;
};

struct user* hashArray[SIZE];

int main(int argc, const char * argv[]) {
    menu_function();
    return 0;
}
void menu_function(){
    char user_input[100];//this could limit the size of input
    string command;
    string name1 = "\0";
    string name2 = "\0";;
    char* token;
    int inputsize = 100;
    int i = 0;
    char delimit[]=" \t\r\n\v\f";
    while( 1 )
    {
        printf("\nP <Name> to create a person\n");
        printf("F <Name> <Name> record friendship\n");
        printf("U <Name> <Name> terminate friendship\n");
        printf("L <Name> print out friends of a specified person\n");
        printf("Q <Name> <Name>  check friendship status of two people\n");
        printf("X - terminate the progarm\n");
        // Determine user input and
        fgets(user_input, inputsize, stdin);
        //getline(&input, &inputsize, stdin);//takes in user input;
        //parsing e string for the data within
        token = strtok( user_input, delimit);
        i = 0;
        while( token != NULL ){
            if(i == 0)
            {
                command = token;
                //cout<< command<<endl;
            }
            if(i == 1)
            {
                name1 = token;
                // cout<< name1<<":"<<endl;
            }
            if( i == 2 )
            {
                name2 =  token;
                //  cout<< name2<<":"<<endl;
                name1 = name1 + "\n";
            }
            token = strtok( NULL, " " );
            i++;
        }
        command_execute( command, name1, name2);
        command = '\0';
        name1 = '\0';
        name2 = '\0';
    }
}
void command_execute( string command, string name1, string name2)
{
    //cout<<"command is: "<<command<<endl;
    switch( command[0])
    {
        case 'P': //Create record of the person
            insert_into_hashtable( hash_function(name1), name1);
            break;
        case 'F': //Record friendship
            add_friendship(hash_function(name1), name2);
            add_friendship(hash_function(name2), name1);
            break;
        case 'U': //Terminate Friendship
            remove_friendship( hash_function(name1), name2);
            remove_friendship( hash_function(name2), name1);
            break;
        case 'L': //Print out the persons Friends
            print_friendships( hash_function(name1));
            break;
        case 'Q': //Check on friendship
            check_friendship( hash_function(name1), name2);
            break;
        case 'X': //Exit the program **** COMPLETED
            exit(1);
            break;
        default:
            cout<<"Error occured based on your command please try again"<<endl;
            break;
    }
}
int hash_function(string string){
    //going to use the ASCI value of the name with different weights per array position to hash the names
    int ascii_key = 0;
    int ascii_total = 0;
    // cout<< string.length()<< endl;
    //cout<< string<< endl;
    for( int i = 0; i < string.length()-1; i++)
    {
        ascii_total = (int) string[i] * (i*3+1);
        //   cout<< string[i]<< endl;
    }
    ascii_key = ascii_total % SIZE;
    //deals with colisions through open hashing
    /*
     while(hashArray[ascii_key] != NULL || hashArray[ascii_key]-> key != ascii_key) { //strcmp(hashArray[ascii_key]->name.c_str(), string.c_str())
     //hashArray[ascii_key] != NULL ||
     ascii_key++;
     }
     */
    // ****** decide size of the hash table and then finished hashing function. Usually hash time is gonna be half full
    cout<< ascii_key<<endl;
    return ascii_key;
}
void insert_into_hashtable( int ascii_key, string name)
{
    //get the hash key
    user *item =  new user;
    item->name= name;
    item->key = ascii_key;
    item->FriendList = NULL;
    //cout<< ascii_key<<endl;
    //store the user in the table
    hashArray[ascii_key] = item;
    delete(item);
}
void add_friendship( int ascii_key, string name )
{
    //gonna have to check for valid input on users
    list* add  = new friend_list;
    list** temp = &hashArray[ascii_key]->FriendList;
    add->name =  name;
    add->next = NULL;
    if( temp == NULL )
     {
     //cout<<hashArray[ascii_key]->FriendList<<endl;
     *temp = add;
     }
     else
    {
        add->next = *temp;
        *temp = add;
    }
    print_friendships(ascii_key);
}
void print_friendships( int ascii_key)
{
    friend_list* temp  = hashArray[ascii_key]->FriendList;
    while( temp != NULL )
    {
        cout<<temp->name<<endl;
        if( temp->next == NULL)
        {
            return;
        }
        temp = temp->next;
    }
}

【问题讨论】:

  • 我很确定我不需要阅读所有这些printf 语句来理解您的链表问题,而且我绝对确定我不会尝试。请发布minimal complete and verifiable example,而不是仅仅粘贴整个程序。
  • 那个编辑有帮助吗?
  • 建议:考虑将列表、哈希表和好友逻辑分离到各自的类中。现在你已经把你的方式耦合到了不必要的高复杂性中,为了调试程序的一个方面,你必须调试所有三个方面。这违反了封装和低耦合,这是面向对象编程的两个关键原则。
  • 不相关:如果您添加一个额外的间接层,将list* temp = hashArray[ascii_key]-&gt;FriendList; 更改为list** temp = &amp;hashArray[ascii_key]-&gt;FriendList;,您可以不必再次查找hashArray[ascii_key]add-&gt;next = hashArray[ascii_key]-&gt;FriendList; 变为 add-&gt;next = *temp;hashArray[ascii_key]-&gt;FriendList = add; 变为 *temp = add;
  • 我没有在给定的代码中看到您报告的错误。你删除的太多了。提供minimal reproducible example 时,不要忘记完成。 MCVE 的真正目标是让您将代码破解为一个更简单的程序,即 bug、整个 bug,除了 bug 什么都没有。您几乎不必一路走到真正的 MCVE,因为随着所涉及的代码量减少,该错误隐藏的空间越来越小,您可以自己找到并修复它。这就是分离职责派上用场的地方:删除不需要的东西以便正确调查问题更容易。

标签: c++ linked-list hashtable


【解决方案1】:
void insert_into_hashtable( int ascii_key, string name)
{
    //get the hash key
    user *item =  new user;
    item->name= name;
    item->key = ascii_key;
    item->FriendList = NULL;

    //store the user in the table
    hashArray[ascii_key] = item;
    delete(item);
}

您为什么要删除该项目?

在数组中存储指针只是存储指针。它不会复制指向的对象,也不会以某种方式保护它不被显式删除。

删除指向的对象后,解除对指针的引用是Undefined Behaviour

您的错误可能发生,因为下一个分配的项目重用了相同的内存(您明确表示它是免费的,通过使用 delete),但实施可能合法地将您的计算机变成土豆,所以你轻车熟路。

您可以确认 - 并且可能会发现其他类似的问题,当您可以编写一个固定的调用列表时,我仍然不会涉足所有无关的 I/O 代码 - 通过运行 valgrind 或地址清理程序.

在理想情况下,您实际上应该做的是完全停止使用低级原始指针和手动(取消)分配,而是使用智能指针和惯用的 C++。

【讨论】:

  • 很明显,自从我编写繁重的程序以来,已经有两年时间了。感谢你的帮助!我将花一些时间重新学习指针并再次访问内存。谢谢
猜你喜欢
  • 2019-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-31
  • 2013-12-08
  • 1970-01-01
相关资源
最近更新 更多