c++ - 从链表中的 getNext()、getPrev() 或 getData() 函数返回 NULL
问题描述
我正在尝试创建一个链接列表,并且目前正在测试一个打印功能,但是为了打印列表中的所有节点,我需要知道长度。
为了找到长度,我需要使用 for 循环从头部循环到当前为 NULL(又名尾部)的时间。
问题是每当列表中的节点设置为 NULL 时,当我使用 getNext() 或任何其他旨在返回 NULL 的函数时,它会导致错误或没有任何反应。
我已经尝试了很长时间来解决这个问题,但我根本找不到我做错了什么。这可能是一个愚蠢的错误,但我找不到它。
创建一个新的空白列表:
LL::LL()
{
// These are all protected variables
head = NULL;
tail = NULL;
current = NULL;
}
创建一个新的空白节点:
Node::Node()
{
// These are all protected variables
data = v_t(); // Value_Type
prev = NULL;
next = NULL;
}
使用参数创建一个新节点:
Node::Node(const v_t& d, Node* n, Node* p)
{
data = d;
prev = p;
next = n;
}
长度函数:
int LL::length()
{
int answer = 0;
for (current = head; current != NULL; current = current->getNext())
{
answer++;
}
return answer;
}
将新节点添加到列表的尾部:
void LL::addToTail(const v_t& item)
{
// ------------(data, next, prev)
tail = new Node(item, NULL, tail);
if (tail -> getPrev() != NULL)
{
tail -> getPrev() -> setNext(tail);
}
if (head == NULL)
{
head = tail;
}
}
下一个返回函数:
Node* Node::getNext() const
{
return next;
}
其他两个吸气剂的格式相同。
以下是完整的课程:
节点.h
#ifndef CHRIS_NODE
#define CHRIS_NODE
#include "account.h"
class Node
{
public: // Members that are externally visible
typedef Account v_t;
// Default Constructor
Node();
Node(const v_t& d, Node* n, Node* p);
// Destructor
~Node();
// Pointer Getters and Setters
void setNext(Node* n);
void setPrev(Node* p);
Node* getNext() const;
Node* getPrev() const;
// Data Getters and Setters
void setData(v_t& d);
v_t getData() const;
private: // Members that are internally visible
Node* next;
Node* prev;
v_t data;
};
#endif
节点.cpp
#include"node.h"
Node::Node()
{
data = v_t();
prev = NULL;
next = NULL;
}
Node::Node(const v_t& d, Node* n, Node* p)
{
data = d;
prev = p;
next = n;
}
Node::~Node(){};
void Node::setNext(Node* n)
{
next = n;
}
void Node::setPrev(Node* p)
{
prev = p;
}
Node* Node::getNext() const
{
return next;
}
Node* Node::getPrev() const
{
return prev;
}
void Node::setData(v_t& d)
{
data = d;
}
Node::v_t Node::getData() const
{
return data;
}
链接列表.h
#ifndef CHRIS_LIST
#define CHRIS_LIST
#include "node.h"
class LL
{
public: // Members that are externally visible
typedef Node::v_t v_t;
LL();
LL(Node* h, Node* t, Node* c);
~LL();
int length();
void addToHead(const v_t& item);
void addToCurrent(const v_t& item);
void addToTail(const v_t& item);
bool search(const v_t& target);
void removeHead();
void removeCurrent();
void removeTail();
void clear();
void printList();
protected: // Members that are internally visible
Node* head;
Node* tail;
Node* current;
};
#endif
链接列表.cpp
#include "linklist.h"
#include <iostream>
using namespace std;
LL::LL()
{
head = NULL;
tail = NULL;
current = NULL;
}
LL::LL(Node* h, Node* t, Node* c)
{
head = h;
tail = t;
current = c;
}
LL::~LL()
{
clear();
}
int LL::length()
{
int answer = 0;
for (current = head; current != NULL; current = current->getNext())
{
answer++;
}
return answer;
}
void LL::addToHead(const v_t& item)
{
head = new Node(item, head, NULL);
if (head -> getNext() != NULL)
{
head -> getNext() -> setPrev(head);
}
if (tail == NULL)
{
tail = head;
}
}
void LL::addToCurrent(const v_t& item)
{
Node* newNode = new Node(item, current, current->getPrev());
current->setPrev(newNode);
newNode->getPrev()->setNext(newNode);
current = head;
}
void LL::addToTail(const v_t& item)
{
tail = new Node(item, NULL, tail);
if (tail -> getPrev() != NULL)
{
tail -> getPrev() -> setNext(tail);
}
if (head == NULL)
{
head = tail;
}
}
bool LL::search(const v_t& target)
{
for (current = head; current != NULL; current = current -> getNext())
{
if (target == (current -> getData()))
{
cout << "The data is stored in " << current << "." << endl;
return true;
}
}
return false;
}
void LL::removeHead()
{
Node* temp = head;
head = head -> getNext();
if (head != NULL)
{
head -> setPrev(NULL);
}
else
{
tail = NULL;
}
delete temp;
}
void LL::removeCurrent()
{
if (current == head)
{
removeHead();
}
else if (current == tail)
{
removeTail();
}
current -> getNext() -> setPrev(current -> getPrev());
current -> getPrev() -> setNext(current -> getNext());
delete current;
current = head;
}
void LL::removeTail()
{
Node* temp = tail;
tail = tail -> getPrev();
if (tail != NULL)
{
tail -> setNext(NULL);
}
else
{
head = NULL;
}
delete temp;
}
void LL::clear()
{
while (head != NULL)
{
removeHead();
}
}
void LL::printList()
{
if (LL::length() == 0)
{
cout << "List Empty.\n";
}
else
{
current = head;
for (int i = 1; i <= LL::length(); i++)
{
if (current != NULL)
{
cout << "Node " << i << ": " << current -> getData() << endl;
current = current -> getNext();
}
}
}
}
帐户.h
#ifndef CHRIS_ACCOUNT
#define CHRIS_ACCOUNT
#include <string>
#include <iostream>
using namespace std;
class Account
{
public:
// Members that are externally visible
// These are member functions
// Constructor
// Precondition: none
// Postcondition: A new instance of account is created and its
// instance data initialsed to either zero or a
// parameter-provided value
Account(const string nm = "", const double initialValue = 0.0);
// Members that mutate data
// Precondition: acct_balance has been initialised
// Postcondition: amount is added to the acct_balance
void deposit(const double amount);
// Precondition: acct_balance has been initialised
// Postcondition: amount is subtracted from the acct_balance
void withdraw(const double amount);
void setName(const string nm);
// Members that query data
// Precondition: acct_balance has been initialised
// Postcondition: The value of acct_balance is returned
double balance() const;
// Precondition: acct_balance has been initialised
// Postcondition: Returns true if acct_balance is greater
// than zero, false otherwise
bool has_funds() const;
string getName() const;
private:
double acc_balance;
string name;
};
bool operator == (Account acc1, Account acc2);
ostream& operator << (ostream& out, const Account acc);
// close the macroguard
#endif
帐号.cpp
#include "Account.h"
Account::Account(string nm, double initialValue)
{
acc_balance = initialValue;
name = nm;
}
void Account::deposit(double amount)
{
acc_balance += amount;
}
void Account::withdraw(double amount)
{
acc_balance -= amount;
}
double Account::balance() const
{
return acc_balance;
}
bool Account::has_funds() const
{
if (acc_balance > 0.0)
{
return true;
}
else
{
return false;
}
}
string Account::getName() const
{
return name;
}
void Account::setName(string nm)
{
name = nm;
}
bool operator == (Account acc1, Account acc2)
{
if (acc1.getName() == acc2.getName() && acc1.balance() == acc2.balance())
{
return true;
}
else
{
return false;
}
}
ostream& operator << (ostream& out, const Account acc)
{
out << "(" << acc.getName() << ", " << acc.balance() << ")\n";
return out;
}
银行.cpp
#include <iostream>
#include <cstdlib>
#include <string>
#include "Account.h"
#include "node.h"
#include "linklist.h"
using namespace std;
int main()
{
int amount = 0;
cout << "How many accounts?\n";
cin >> amount;
LL* LL1 = new LL();
for (int i = 1; i <= amount; i++)
{
string nm;
double iv;
cout << "What is the name for account " << i << "?\n";
cin >> nm;
cout << "What is the initial value for account " << i << "?\n";
cin >> iv;
Account newAcc(nm, iv);
LL1 -> addToTail(newAcc);
}
LL1 -> printList();
return EXIT_SUCCESS;
}
如果您需要更多信息或代码,请告诉我:)
解决方案
当我使用
getNext()
或任何其他旨在返回 NULL 的函数时,什么都没有发生。
那是因为您没有在方法中使用结果。您的循环永远不会为. 改变这个:getNext()
length
current
for (current = head; current != NULL; current->getNext())
至:
for (current = head; current != NULL; current = current->getNext())
定义current
为LL
类的实例成员是一种反模式。这样的引用应该是一个局部变量,在需要它的函数中定义。它不应该是您的链表状态的一部分。
因此,无论您在哪里使用current
,都将其定义为局部变量:
Node * current = head;
为了打印列表中的所有节点,我需要知道长度。
不必要。您可以在没有以下情况下更改您的printList
功能length
:
void LL::printList()
{
Node * current = head;
if (current == NULL)
{
cout << "List Empty.\n";
}
else
{
for (int i = 1; current != NULL; i++, current = current -> getNext())
{
cout << "Node " << i << ": " << current -> getData() << endl;
}
}
}
如果您保留调用的版本length
并继续使用实例变量current
,则循环将不会循环,因为调用length()
将改变current
(在您初始化之后),并将其设置为NULL
.
如果你真的想要实例变量current
,那么只在真正需要设置的地方改变它,比如在search
. 但它不应该被length()
or改变printList()
,这不应该改变你的实例的状态。因此,length()
您printList()
应该使用局部变量,而不是实例变量。
推荐阅读
- python - 如何在一行中编写嵌套的 if-elif-else 条件?
- git - Git - 从提交到主文件中永久排除文件(删除)
- symfony - 如何在我的项目 symfony 4 中卸载包 lexik / jwt-authentication-bundle
- reactjs - 如何在 React + Typescript 中为延迟加载创建 hoc
- bash - bash 星号转义在 echo 中打印 \*
- c# - .NET Core Fakes 和 VS 2019 Preview 6.9.0 Preview 2.0 找不到类型或命名空间名称
- docker - Docker 将文件从主机复制到映像
- swift - SecKeyCreateSignature 在哪里获取钥匙串签名授权对话框的密钥名称?
- python - 乌龟显示错误,以前可以正常工作
- java - 当我按下“新项目”时,如何在 Intellij Idea 的开始菜单中配置技术列表