我正在尝试将模板链接列表实现到我正在使用很多类的项目中。它的工作方式有点像地图或集合,其中有键数据和值数据。我创建它并使用整数和字符串值在一个单独的项目中对其进行了测试,并且它内部的所有函数都可以工作,我什至使用 BOOST 库让它与序列化一起工作。
这是我列表的整个类文件:
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include <boost\serialization\access.hpp>
#include <iostream>
#include <string>
using namespace std;
template<typename Tkey, typename Tvalue>
class Node
{
public:
Tkey keyData;
Tvalue valueData;
Node * next;
Node()
{
next = NULL;
}
Node(Tkey x, Tvalue y)
{
keyData = x;
valueData = y;
next = NULL;
}
Node(Tkey x, Tvalue y, Node * z)
{
keyData = x;
valueData = y;
next = z;
}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & keyData;
ar & valueData;
ar & next;
}
};
template<typename Tkey, typename Tvalue>
class LinkedList
{
Node<Tkey, Tvalue> *head;
int count;
public:
LinkedList()
{
head = NULL;
count = 0;
}
~LinkedList()
{
Clear();
}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & head;
ar & count;
}
int Size()
{
return count;
}
bool Empty()
{
return (count == 0);
}
bool Add(Tkey key, Tvalue value)
{
Node<Tkey, Tvalue> *p;
if(head == NULL)
{
head = new Node<Tkey, Tvalue> (key, value, NULL);
count++;
return true;
}
else
{
p = head;
while(p->next !=NULL)
p=p->next;
p->next = new Node<Tkey, Tvalue> (key, value, NULL);
count++;
return true;
}
return false;
}
bool Remove(Tkey key)
{
Node<Tkey, Tvalue> *p;
if (head->keyData == key)
{
head = head->next;
return true;
}
p=head;
while (p->next->keyData != key && p->next->next != NULL)
{
p = p->next;
}
if (p->next->keyData == key && p->next != NULL)
{
Node<Tkey, Tvalue> *temp;
temp = p->next;
p->next = temp->next;
count--;
delete temp;
return true;
}
return false;
}
Tvalue Get(Tkey key)
{
Node<Tkey, Tvalue> *p;
p = head;
while (p->next != NULL)
{
if (p->keyData == key)
{
return p->valueData;
}
p = p->next;
}
return NULL;
}
Tvalue Find(int i)
{
int selection = 0;
Node<Tkey, Tvalue> *p;
p = head;
while (selection != i && p->next != NULL)
{
p = p->next;
selection++;
}
if (p->next == NULL)
{
return 0;
}
return p->valueData;
}
Tkey Exists (Tvalue value)
{
Node<Tkey, Tvalue> *p;
p = head;
while (p->next != NULL)
{
if (p->valueData == value)
{
return p->keyData;
}
}
return NULL;
}
void Clear()
{
Node<Tkey,Tvalue> * temp;
while (head != 0)
{
temp = head;
head = head->next;
count--;
delete temp;
}
}
void Print(Tkey key)
{
Node<Tkey, Tvalue> * p;
p = head;
while(p->keyData != key && p->next != NULL)
{
p = p->next;
}
if (p->keyData == key && p->next != NULL)
{
cout << p->keyData << " " << p->valueData << endl;
}
else
{
cout << "Data not found" << endl;
}
}
void PrintAll()
{
Node<Tkey, Tvalue> * p;
p = head;
while(p != NULL)
{
cout << p->keyData << " " << p->valueData << "\n";
p = p->next;
}
}
};
#endif
为了在我的项目中测试它,我创建了一个带有 int 和我的一个类的 Linked List 变量,然后尝试添加和获取值数据以修改值。
LinkedList<int,Customer *> customerList;
customerList.Add(1, new Customer("Jack Smith", "1 Adelade Road", "5678", "Male", 4,8,1999));
customerList.Get(1)->AddAccount("9081", new JuniorCurrentAccount("100126764", 50, 25,12,2010));
但是,当我运行它时,我在指向 if(head == NULL) 的 Add 方法处得到一个未处理的异常
异常显示“访问冲突读取位置”
到目前为止,我已经尝试在列表检查节点时将 NULL 更改为 0,但这并没有阻止异常,我还尝试包含类文件的标头,但这导致了很多涉及访问这些类中的变量的错误.
我相信班级本身有问题,但我找不到导致它的原因。正如我所说,这个类适用于基本数据类型(整数、字符串等),但类是导致错误的原因。任何帮助都会很棒!
编辑:这是客户类 .cpp 文件的代码
#include "Customer.h" #include "Account.h" #include "CorportateSavings.h" #include "CurrentAccount.h" #include "JuniorCurrentAccount.h" #include "StudentSavings.h" #include "Mortgage.h" #include "BuyToLetMortgage.h" #include "DiscountMortgage.h" #include "FixedRateMortgage.h" #include #include #include #include #include
using namespace std;
Customer::Customer(string Name, string Address, string TelephoneNo, string Gender, int DOBday, int DOBmonth, int DOByear) : name(Name), address(Address), telephoneNo(TelephoneNo), gender(Gender), DOB(DOBday,DOBmonth,DOByear)
{
parent = 0;
}
Customer::Customer(string Name, string Address, string TelephoneNo, string Gender, int DOBday, int DOBmonth, int DOByear, Customer *c) : name(Name), address(Address), telephoneNo(TelephoneNo), gender(Gender), DOB(DOBday,DOBmonth,DOByear)
{
parent = c;
}
Customer::~Customer(void)
{
}
void Customer::printDetails()
{
//Prints out details of customer
cout << "Name : " << name << endl;
cout << "Address : " << address << endl;
cout << "Telephone No : " << telephoneNo << endl;
cout << "Gender : " << gender << endl;
cout << "Date of Birth : ";
printStringDOB();
//If customer has a registered parent/guardian
if (parent != 0)
cout << "Parent/Guardian Name: " << parent->getName() << endl;
cout << endl;
}
string Customer::getName()
{
return name;
}
void Customer::setName(string Name)
{
name = Name;
}
string Customer::getAddress()
{
return address;
}
void Customer::setAddress(string Address)
{
address = Address;
}
string Customer::getTelephoneNo()
{
return telephoneNo;
}
void Customer::setTelephoneNo(string TelephoneNo)
{
telephoneNo = TelephoneNo;
}
string Customer::getGender()
{
return gender;
}
void Customer::setGender(string Gender)
{
gender = Gender;
}
void Customer::printStringDOB()
{
DOB.printString();
}
double Customer::getDOB()
{
return DOB.juldays();
}
void Customer::setDOB(int day, int month, int year)
{
DOB.setDay(day);
DOB.setMonth(month);
DOB.setYear(year);
}
int Customer::getAge(int Day, int Month, int Year)
{
return DOB.DifferenceYear(Day, Month, Year);
}
void Customer::setParent(Customer * c)
{
parent = c;
}
Customer * Customer::getParent()
{
if (parent = 0)
{
return NULL;
}
else
{
return parent;
}
}
void Customer::AccountManager()
{
int choice = AccountManagerChooser();
cout << endl;
while (choice != 9)
{
switch (choice)
{
case 1:
//Create a bank acount
CreateAccountManager();
choice = AccountManagerChooser();
break;
case 2:
{
//Use a bank account
string pin;
cout << "Enter PIN: ";
cin >> pin;
UseAccount(pin);
choice = AccountManagerChooser();
break;
}
case 3:
{
//Remove a bank account
char yn;
cout << "Enter PIN: ";
string pin;
cin >> pin;
if (accountList.Get(pin) != NULL)
{
cout << "Are you sure? (Y/N) ";
cin >> yn;
if (yn == 'y' || yn == 'Y')
{
accountList.Remove(pin);
cout << "Account Removed Successfully" << endl;
}
}
else
{
cout << "Invalid PIN or Account does not exist" << endl;
}
choice = AccountManagerChooser();
break;
}
case 4:
//Print Customer Details
printDetails();
choice = 0;
break;
case 5:
{
//Change Customer Details
int detailChange = 0;
while (detailChange != -1)
{
cout << "1 Name" << endl;
cout << "2 Address" << endl;
cout << "3 Telephone No" << endl;
cout << "4 Gender" << endl;
cout << "5 Date of Birth" << endl;
cout << "Which piece of detail do you want to change? ";
cin >> detailChange;
string str;
getline(cin, str);
cout << endl;
switch (detailChange)
{
case 1:
{
string newName;
cout << "Enter new name: ";
getline(cin, newName);
setName(newName);
break;
}
case 2:
{
string newAddress;
cout << "Enter new Address: ";
getline (cin,newAddress);
setAddress(newAddress);
break;
}
case 3:
{
string newTelephone;
cout << "Enter new Telephone Number: ";
getline (cin,newTelephone);
setTelephoneNo(newTelephone);
break;
}
case 4:
{
string newGender;
cout << "Enter Gender" << endl;
getline (cin,newGender);
gender = newGender;
break;
}
case 5:
int newDay = 0;
int newMonth = 0;
int newYear = 0;
cout << "Enter Day: ";
cin >> newDay;
cout << "Enter Month: ";
cin >> newMonth;
cout << "Enter Year: ";
cin >> newYear;
setDOB(newDay,newMonth,newYear);
break;
}
char yn = 0;
cout << "Would you like to change anything else? (Y/N) ";
cin >> yn;
if (yn == 'Y' || yn == 'y')
{
detailChange = 0;
cout << endl;
}
else
{
detailChange = -1;
cout << endl;
}
}
choice = AccountManagerChooser();
cout << endl;
}
break;
case 6:
//Create a mortgage
{
time_t t = time(0);
struct tm * now = localtime( & t );
CreateMortgageManager();
choice = AccountManagerChooser();
cout << endl;
}
break;
case 7:
//Use a mortgage
{
string str;
string pin;
getline(cin,str);
cout << "Enter PIN: ";
getline(cin,pin);
UseMortgage(pin);
choice = AccountManagerChooser();
cout << endl;
}
break;
case 8:
//Remove a mortgage
{
string str;
string pin;
getline(cin,str);
cout << "Enter PIN: ";
getline(cin,pin);
RemoveMortgage(pin);
choice = AccountManagerChooser();
cout << endl;
}
break;
case 9:
break;
default:
cout << endl;
choice = AccountManagerChooser();
break;
}
if (choice == 9)
{
cout << "Thank you for your time!\n\n" << endl;
}
else if (choice == 0)
{
choice = AccountManagerChooser();
}
}
}
int Customer::AccountManagerChooser()
{
cout << "What would you like to do?" << endl;
cout << "1: Create a new account" << endl;
cout << "2: Use an account" << endl;
cout << "3: Close an account" << endl;
cout << "4: Show Personal Details" << endl;
cout << "5: Update Personal Details" << endl;
cout << "6: Create a Mortgage" << endl;
cout << "7: Use a Mortgage" << endl;
cout << "8: Remove a Mortgage" << endl;
cout << "9: Exit" << endl;
cout << "Enter Choice: ";
int choice;
cin >> choice;
cout << endl;
return choice;
}
void Customer::CreateAccountManager()
{
int choice = 0;
while (choice != -1)
{
time_t t = time(0);
struct tm * now = localtime( & t );
cout << "What account do you wish to create?" << endl;
cout << "1: Corporate Savings" << endl;
cout << "2: Current Account" << endl;
cout << "3: Junior Account" << endl;
cout << "4: Student Savings Account" << endl;
cout << "5: Cancel" << endl;
cout << "Enter Choice: ";
cin >> choice;
cout << endl;
switch (choice)
{
case 1:
//Corporate Savings Account Made
//Grabs age from current date
if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) >= 16)
{
cout << "Please enter how much you wish to deposit: ";
double initDeposit;
cin >> initDeposit;
cout << "Please enter a four digit number to set as the PIN: ";
string PIN;
cin >> PIN;
cout << "Please enter a 9 digit number to set as the account number: ";
string AccountNo;
cin >> AccountNo;
AddAccount(PIN, new CorporateSavings(AccountNo, initDeposit, now->tm_mday, now->tm_mon + 1, now->tm_year + 1900));
cout << "Corporate Savings Account Created" << endl;
choice = -1;
}
else if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) < 16)
{
cout << "Corportate Savings Account is only available to customers over the age of 16" << endl;
}
break;
case 2:
//Current Account Made
//Grabs age from current date
if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) >= 16)
{
cout << "Please enter how much you wish to deposit: ";
double initDeposit;
cin >> initDeposit;
cout << "Please enter a four digit number to set as the PIN: ";
string PIN;
cin >> PIN;
cout << "Please enter a 9 digit number to set as the account number: ";
string AccountNo;
cin >> AccountNo;
AddAccount(PIN, new CurrentAccount(AccountNo, initDeposit, now->tm_mday, now->tm_mon + 1, now->tm_year + 1900));
cout << "Current Account Created" << endl;
choice = -1;
}
else if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) < 16)
{
cout << "Current Account is only available to customers over the age of 16" << endl;
}
break;
case 3:
//Junior Current Account Made
//Grabs age from current date
if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) <= 16)
{
cout << "Please enter how much you wish to deposit: ";
double initDeposit;
cin >> initDeposit;
cout << "Please enter a four digit number to set as the PIN: ";
string PIN;
cin >> PIN;
cout << "Please enter a 9 digit number to set as the account number: ";
string AccountNo;
cin >> AccountNo;
AddAccount(PIN, new JuniorCurrentAccount(AccountNo, initDeposit, now->tm_mday, now->tm_mon + 1, now->tm_year + 1900));
cout << "Junior Account Created" << endl;
choice = -1;
}
else if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) > 16)
{
cout << "Junior Account is only available to customers under the age of 16" << endl;
}
else if (parent != 0)
{
cout << "Customers applying for Junior Account must have an adult registered as a guardian" << endl;
}
break;
case 4:
//Student Savings Account Made
//Grabs age from current date
if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) >= 18)
{
cout << "Please enter how much you wish to deposit: ";
double initDeposit;
cin >> initDeposit;
cout << "Please enter a four digit number to set as the PIN: ";
string PIN;
cin >> PIN;
cout << "Please enter a 9 digit number to set as the account number: ";
string AccountNo;
cin >> AccountNo;
AddAccount(PIN, new StudentSavings(AccountNo, initDeposit, now->tm_mday, now->tm_mon + 1, now->tm_year + 1900));
cout << "Student Account Created" << endl;
choice = -1;
}
else if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) < 18)
{
cout << "Student Account is only available to customers over the age of 18" << endl;
}
break;
case 5:
choice = -1;
break;
default:
cout << "Not a valid choice" << endl;
break;
}
}
}
void Customer::AddAccount(string PIN, Account * a)
{
accountList.Add(PIN, a);
}
bool Customer::UseAccount(string PIN)
{
if (accountList.Get(PIN) != NULL)
{
int choice = 0;
while (choice != -1)
{
cout << "What would you like to do?" << endl;
cout << "1: Deposit Cash" << endl;
cout << "2: Deposit Cheque" << endl;
cout << "3: Withdraw Cash" << endl;
cout << "4: Show Balance" << endl;
cout << "5: Exit" << endl;
cout << "Enter Choice: ";
cin >> choice;
cout << endl;
switch (choice)
{
case 1:
{
cout << "Enter Deposit Amount: ";
double amount;
cin >> amount;
if (accountList.Get(PIN)->depositAmount(amount))
{
time_t t = time(0);
struct tm * now = localtime( & t );
ofstream output;
output.open("Transactions.txt", ios::app);
output << "Name: " << name << " - Account Number: " << accountList.Get(PIN)->AccountNumber() << " - Deposit: £" <<
amount << " - Date: " << now->tm_mday << "/" << now->tm_mon + 1 << "/" << now->tm_year + 1900 << endl;
output.close();
cout << "Amount Deposited Successfully" << endl;
}
else
cout << "Deposit Invalid" << endl;
choice = 0;
}
break;
case 2:
{
time_t t = time(0);
struct tm * now = localtime( & t );
ofstream output;
output.open("Transactions.txt", ios::app);
output << "Name: " << name << " - Account Number: " << accountList.Get(PIN)->AccountNumber() << " - Cheque Deposit: £"
<< " - Date: " << now->tm_mday << "/" << now->tm_mon + 1 << "/" << now->tm_year + 1900 << endl;
output.close();
cout << "Amount Deposited Successfully" << endl;
}
break;
case 3:
{
cout << "Enter Withdraw Amount: ";
double amount;
cin >> amount;
if (accountList.Get(PIN)->widthdrawAmount(amount))
{
time_t t = time(0);
struct tm * now = localtime( & t );
ofstream output;
output.open("Transactions.txt", ios::app);
output << "Name: " << name << " - Account Number: " << accountList.Get(PIN)->AccountNumber() << " - Withdrawal: £" <<
amount << " - Date: " << now->tm_mday << "/" << now->tm_mon + 1 << "/" << now->tm_year + 1900 << endl;
output.close();
cout << "Amount Withdrawn Successfully" << endl;
}
else
cout << "Withdraw Invalid" << endl;
choice = 0;
}
break;
case 4:
{
time_t t = time(0);
struct tm * now = localtime( & t );
accountList.Get(PIN)->addInterest(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900);
cout << "Balance: £" << accountList.Get(PIN)->Amount() << endl;
choice = 0;
}
break;
case 5:
choice = -1;
break;
default:
choice = 0;
break;
}
char yn;
cout << "Do you want to use another service? (Y/N) ";
cin >> yn;
if ((yn == 'y' || yn == 'Y') && choice != -1)
{
choice = 0;
}
else
{
choice = -1;
}
}
return true;
}
return false;
}
void Customer::RemoveAccount(string PIN)
{
char choice;
cout << "Are you sure? (Y/N): ";
cin >> choice;
cout << endl;
while (choice != 'y' || choice != 'Y' || choice != 'n' || choice != 'N')
{
cout << "Are you sure? (Y/N): ";
cin >> choice;
cout << endl;
}
accountList.Remove(PIN);
}
void Customer::CreateMortgageManager()
{
//Grabs age from current date
time_t t = time(0);
struct tm * now = localtime( & t );
if (getAge(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900) >= 18)
{
int choice = 0;
cout << "Please enter the value of your House/Apartment: ";
double value;
cin >> value;
cout << "Please enter the length of the payment (years) : 1, 2 or 4" << endl;
int length;
cin >> length;
cout << "Please enter the PIN number of the bank account you wish to pay installments to: ";
string accountPIN;
cin >> accountPIN;
if (accountList.Get(accountPIN) == NULL)
{
while (accountList.Get(accountPIN) == NULL)
{
cout << "Account PIN not valid or Account doesn't exist\n" << endl;
cout << "Please enter the PIN number of the bank account you wish to pay installments to: ";
cin >> accountPIN;
}
}
while (choice != -1)
{
cout << "What kind of Mortgage do you wish to create?" << endl;
cout << "1: Fixed Rate Mortgage : " << ((value*0.8)+50)/(length * 12) << " per month with 5% Interest" << endl;
cout << "2: Discount Mortgage : " << ((value*0.8)+80)/(length * 12) << " per month with 3.8% Interest (5% Interest after 2 years)" << endl;
cout << "3: Buy to Let Mortgage : " << ((value*0.8)+120)/(length * 12) << " per month with 7.35% Interest" << endl;
cout << "4: Cancel" << endl;
cout << "Enter Choice: ";
cin >> choice;
cout << endl;
string str;
getline(cin,str);
switch (choice)
{
case 1:
{
cout << "Please enter a PIN, so you can access your mortgage securely: ";
string PIN;
getline(cin,PIN);
AddMortgage(PIN, new FixedRateMortgage(value, 50.0, accountList.Get(accountPIN), length, now->tm_mday, now->tm_mon + 1, now->tm_year + 1900));
cout << "Fixed Rate Mortgage Created" << endl;
choice = -1;
}
break;
case 2:
{
cout << "Please enter a PIN, so you can access your mortgage securely: ";
string PIN;
getline(cin,PIN);
AddMortgage(PIN, new DiscountMortgage(value, 45.0, accountList.Get(accountPIN), length, now->tm_mday, now->tm_mon + 1, now->tm_year + 1900));
cout << "Discount Mortgage Created" << endl;
choice = -1;
}
break;
case 3:
{
cout << "Please enter a PIN, so you can access your mortgage securely: ";
string PIN;
getline(cin,PIN);
AddMortgage(PIN, new BuyToLetMortgage(value, 70.0, accountList.Get(accountPIN), length, now->tm_mday, now->tm_mon + 1, now->tm_year + 1900));
cout << "Buy To Let Mortgage Created" << endl;
choice = -1;
}
break;
case 4:
choice = -1;
break;
default:
cout << "Not a valid choice" << endl;
break;
}
}
}
else
{
cout << "Mortgages are only available to customers over the age of 18" << endl;
}
}
void Customer::AddMortgage(string PIN, Mortgage * m)
{
mortgageList.Add(PIN, m);
}
void Customer::UseMortgage(string PIN)
{
if (mortgageList.Get(PIN) != NULL)
{
int choice = 0;
while (choice != -1)
{
cout << "What would you like to do?" << endl;
cout << "1: Pay Installment" << endl;
cout << "2: Print Payment List" << endl;
cout << "3: Exit" << endl;
cout << "Enter Choice: ";
cin >> choice;
cout << endl;
switch (choice)
{
case 1:
{
time_t t = time(0);
struct tm * now = localtime( & t );
mortgageList.Get(PIN)->PayInstallment(now->tm_mday, now->tm_mon + 1, now->tm_year + 1900);
choice = 0;
}
break;
case 2:
{
mortgageList.Get(PIN)->PrintPaymentLog();
}
break;
case 3:
choice = -1;
break;
default:
choice = 0;
break;
}
char yn;
cout << "Do you want to use another service? (Y/N) ";
cin >> yn;
if ((yn == 'y' || yn == 'Y') && choice != -1)
{
choice = 0;
}
else
{
choice = -1;
}
}
}
}
void Customer::RemoveMortgage(string PIN)
{
char choice;
cout << "Are you sure? (Y/N): ";
cin >> choice;
cout << endl;
while (choice != 'y' || choice != 'Y' || choice != 'n' || choice != 'N')
{
cout << "Are you sure? (Y/N): ";
cin >> choice;
cout << endl;
}
mortgageList.Remove(PIN);
}