在 C++98 的双重链接列表中使用函数 bool deleteAcc(const string name1) 搜索字符串输入?

Searching for string input using a function bool deleteAcc(const string name1) in doubly linkedlist in C++98?

提问人:Jac Investigator 提问时间:4/15/2023 最后编辑:Jac Investigator 更新时间:4/16/2023 访问量:44

问:

除了最后一个函数外,我的双向链表的所有其他函数(包括 Account 类和 Node 类)都正常工作。

函数 bool deleteAcc(string name) 将采用字符串名称(用户输入)作为其参数并返回 bool 结果。然后,它将在列表中找到名称,并从列表中删除相应的 Account(和 Node),然后返回 True。如果帐户不在列表中,它将返回 False。

这是我的代码,如下所示:

#include <iostream>
#include "Account.h"
#include <string>
#include "Node.h"
using namespace std;

bool deleteAcc(const string name1);

int main(){

    string name;
    int k;
    cout << "How many accounts do you want to enter? ";
    cin >> k;

    Node* head = NULL;
    //Node* tail = NULL;

    for (int i = 0; i < k; i++) {
        string name;
        double balance;

        cout << "Enter account name: ";
        cin >> name;

        cout << "Enter account balance: ";
        cin >> balance;
    
        Account account(name, balance);

        Node* newNode = new Node(account);

        if (head == NULL) {
            // The list is empty, so set both head and tail to the       
            // new node
            head = newNode;
            // tail = newNode;
        } else {
            // The list is not empty, so add the new node to the  
            // tail
            newNode->setNext(head);
            //newNode->setPrevious(head); // Update previous pointer 
            // of newNode to point to the previous last node (i.e.,   
            // tail)
            head = newNode;
        }
    }

    // Print the list
    cout << "Account balances:" << endl;
    cout << endl;

    Node* currentNode = head;

    while (currentNode != NULL) {
        cout << currentNode->getData() << endl;
        currentNode = currentNode->getNext();
    }

    cout << "Enter the account name you want to delete: ";
    cin >> name;
    deleteAcc(name);



    // Deallocate memory
    currentNode = head;

    while (currentNode != NULL) {
        Node* nextNode = currentNode->getNext();
        delete currentNode;
        currentNode = nextNode;
    }

    return 0;
}

bool deleteAcc(const string name1)
{
    Node* currentNode = head;
    Node* previousNode = NULL;

    while (currentNode != NULL){
        if (currentNode->getData().getName() == name1) {
            if (previousNode == NULL) {
                // The node to be deleted is the head node
                head = currentNode->getNext();
            }   
            else {
            // The node to be deleted is in the middle of the list
            previousNode->setNext(currentNode->getNext());
            }  

        delete currentNode;
        return true;
        }

        // Update the previous node and move to the next node
        previousNode = currentNode;
        currentNode = currentNode->getNext();
    }

    // The account was not found in the list
    return false;
}

问题是 deleteAcc(name) 函数中的 head 超出了范围,因此是否可以仅使用 bool deleteAccount(string name) 中的单个参数字符串来回答这个问题????

请帮忙。谢谢

我已经尝试了很多次来寻找如何解决这个问题,比如在 int main() 之前在文件顶部声明 head,如下所示:

Node* head = NULL; 

int main(){
    // functions and variables here
}

但它不会产生显示输出的预期结果。

搜索 布尔 双链接列表 C++98

评论

0赞 trincot 4/16/2023
为什么要定义为全局变量?返回什么,是否可以打印?headcurrentNode->getData()
0赞 Jac Investigator 4/16/2023
@trincot,因为当我使用在 int main() 之外定义的函数 bool deleteAcc(const string name1) 时,编译器一直抱怨 head 是我们的范围。所以这就是为什么我把它定义为一个全局变量。但我认为这就是为什么它不会产生输出的原因。currentNode->getData() 返回存储在 Account 对象中的 (name, balance),是的,它是可打印的。

答:

0赞 fireshadow52 4/15/2023 #1

在大多数情况下,除了有一个类/结构之外,你还有另一个类/结构来表示双向链表,该类将保存节点以及与列表相关的任何其他函数。请参阅此示例:Nodehead

class Dllist {
    private:
        Node *head;
        int size;
    public:
        bool insertAcc(const string &name1);
        bool deleteAcc(const string &name1);
        Node *findAcc(const string &name1);
        // ...
};

然后,您的函数(以及定义为 一部分的任何其他函数)将有权访问 。deleteAccDllisthead

由于您现在已经编写了代码,我从此评论中推断出您已经完全在 : 中设置了列表。如果是这样的话,那么在不向函数添加额外参数的情况下,您可以访问的唯一方法是创建一个全局变量,我强烈建议不要这样做。main// other functions and variables written hereheaddeleteAcchead

在另一个节点上,您的标题包含短语“双链表”,但看起来您的函数只是在修改前向链接(即调用 .要使列表保持其作为双向链表的状态,需要确保正确设置了前向和后向链接。deleteAcc->setNext

更新:我在这里回复您的评论,因为格式更好:

@fireshawdow52,我已经编辑了我的代码,并将我所有的代码都放在了我的帖子中。此外,它是一个双链表,但在此之前的上一个问题,告诉我们对列表的打印输出进行反向排序,所以我得出的结论是不再需要尾部,因为它会导致编译错误。

要使结构进行双重链接,绝对需要您的成员。但是,将不起作用,因为这将导致两者并返回相同的 .在调用 .原因与你如何构建你的列表有关。tailnewNode->setPrevious(head)getNext()getPrevious()Nodehead->setPrevious(newNode)newNode->setNext(head)

假设我们要添加三个 s,它们将被命名为“帐户 1”、“帐户 2”和“帐户 3”。以下是添加每个帐户后列表的外观。Account

添加帐户 1 后

     head
      |
      v
|           |
| Account 1 |
|           |

添加账户 2 后

     head
      |
      v
|           |      |           |
| Account 2 | ---> | Account 1 |
|           |      |           |

添加账户 3 后

     head
      |
      v
|           |      |           |      |           |
| Account 3 | ---> | Account 2 | ---> | Account 1 |
|           |      |           |      |           |

鉴于上述情况,如果您取消注释该行,那么您的最终列表将如下所示,每个节点都有两个指向同一节点的指针,这不是设置双向链表的方式:newNode->setPrevious(head)

     head ____________     ____________________
      |   |           |    |                  |
      v   |           v    |                  v
|         | |      |       |   |      |           |
| Account 3 | ---> | Account 2 | ---> | Account 1 |
|           |      |           |      |           |

有了 ,那么你最终会得到:head->setPrevious(newNode)

     head
      |
      v
|           |      |           |      |           |
| Account 3 | ---> | Account 2 | ---> | Account 1 |
|           | <--- |           | <--- |           |

这是因为,例如,当您为“帐户 2”设置指针时,该指针仍然是“帐户 1”,并且添加指向该节点的指针是 的反之义。nextheadpreviousnewNode->setNext(head)

评论

0赞 Jac Investigator 4/16/2023
@fireshawdow52,我已经编辑了我的代码,并将我所有的代码都放在了我的帖子中。此外,它是一个双链表,但在此之前的上一个问题,告诉我们对列表的打印输出进行反向排序,所以我得出的结论是不再需要尾部,因为它会导致编译错误。