C++ c++;存储字符串的链表
我正在创建一个自定义链表类来存储我为作业创建的程序中的字符串。我们收到了一份适用于ints的链表讲义,并被告知要将其重新设置为字符串存储,但我在尝试运行它时遇到了一个错误 我在抛出“std::logic\u error”实例后调用了错误“terminate” what()我四处搜索,仔细查看了类似的问题,但没有找到任何有帮助的C++ c++;存储字符串的链表,c++,string,linked-list,C++,String,Linked List,我正在创建一个自定义链表类来存储我为作业创建的程序中的字符串。我们收到了一份适用于ints的链表讲义,并被告知要将其重新设置为字符串存储,但我在尝试运行它时遇到了一个错误 我在抛出“std::logic\u error”实例后调用了错误“terminate” what()我四处搜索,仔细查看了类似的问题,但没有找到任何有帮助的 #include <cstdlib> #include <iostream> #include <string>
#include <cstdlib>
#include <iostream>
#include <string>
#include <cstdio>
#include <iomanip>
using namespace std;
struct node {
node(string current) { data=current; next=NULL; }
string data;
node *next;
};
class list {
public:
list(int N=0, string current);
~list();
bool empty() const { return N == 0; }
void clear();
void insert(int, const string &);
void push_front(const string ¤t);
friend ostream & operator<<(ostream &out, const list ¤t);
private:
int N;
node *head;
node *findnode(int);
};
list::list(int M, string current) {
N = M;
head = new node;
for (int i=0; i<N; i++)
insert(0, current);
}
list::~list() {
clear();
delete head;
}
void list::clear() {
while (!empty()) remove(0);
}
void list::insert(int i, const string &din) {
node *p = new node(din);
node *pp = findnode(i-1);
p->next = pp->next;
pp->next = p;
N++;
}
inline
node *list::findnode(int i) {
if (i == -1)
return head;
node *p = head->next;
while (i--)
p = p->next;
return p;
}
void list::push_front(const string ¤t) {
head = new node;
head->next;
}
ostream& operator<<(ostream& out, const list& current)
{
out << current;
return out;
}
const string rank[] = { "Ace", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "Jack", "Queen", "King" };
const string suit[] = { "Clubs", "Diamonds", "Hearts", "Spades" };
string random_card(bool verbose=false) {
string card;
card = rank[ rand()%13 ];
card += " of ";
card += suit[ rand()%4 ];
if (verbose)
cout << card << "\n";
return card;
}
int main(int argc, char *argv[])
{
bool verbose = false;
int seedvalue = 0;
string stop_card = "Queen of Hearts";
for (int i=1; i<argc; i++) {
string option = argv[i];
if (option.compare(0,6,"-seed=") == 0) {
seedvalue = atoi(&argv[i][6]);
} else if (option.compare(0,6,"-stop=") == 0) {
stop_card = &argv[i][6];
} else if (option.compare("-verbose") == 0) {
verbose = true;
} else
cout << "option " << argv[i] << " ignored\n";
}
srand(seedvalue);
list deck[4];
while (1) {
string card = random_card(verbose);
char first[10];
char second[10];
sscanf(card.c_str(), "%s of %s", first,second);
// reverse engineer card suit and rank
int index2;
//suit index
for(int i=0; i<4; i++){
if(suit[i]==second){
index2=i;
break;
}
}
deck[index2].push_front(first);
if (card.compare(stop_card)==0){
break;
}
}
// print formatted table contents to stdout
cout << "Clubs : ";
cout << setw(3) << deck[0];
cout << endl;
cout << "Diamonds : ";
cout << setw(3) << deck[1];
cout << endl;
cout << "Hearts : ";
cout << setw(3) << deck[2];
cout << endl;
cout << "Spades : ";
cout << setw(3) << deck[3];
cout << endl;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
结构节点{
节点(字符串当前){data=current;next=NULL;}
字符串数据;
节点*下一步;
};
班级名单{
公众:
列表(int N=0,字符串当前);
~list();
bool empty()常量{return N==0;}
无效清除();
空插入(int,常量字符串&);
无效前推(常量字符串和当前);
friend ostream&operatornext=p;
N++;
}
内联
节点*列表::findnode(int i){
如果(i==-1)
回流头;
节点*p=头部->下一步;
而(我--)
p=p->next;
返回p;
}
无效列表::推前(常量字符串和当前){
头=新节点;
头->下一步;
}
ostream&operator以下是阻碍构建(读取:编译时错误)或实际运行的重要问题。这并不意味着这些都是bug,但它确实值得考虑。我应该马上注意到,“哨兵”头节点分配的概念在链表管理中几乎从来都不需要,这段代码也不例外。如果列表为“空”头
应为空。如果它不是空的,head
不应为空。它就是这么简单,如果遵循这一点,这段代码将大大简化
说到这里,请继续读下去
无效代码:
list(int N=0, string current);
原因:C++需要所有参数<强>跟随< /强>第一个参数,它提供默认值也有默认值。如果N是第二个参数,或者
current
也有一个默认值(或者当然,如果两者都没有默认值),则这是有效的。以下各项均有效:
list(int N, string current);
list(int N, string current = "");
list(int N=0, string current = "");
正如所写的,它将无法编译
无效代码:没有匹配的构造函数可用
head = new node;
原因:结构节点
未定义符合默认值的构造函数(没有参数或所有参数都具有默认值规定的构造函数),但指定了非默认构造函数(至少需要一个参数的构造函数)。因此,语言提供的默认构造函数不是自动生成的,并且找不到node::node()
构造函数
错误代码:表达式结果未使用
void list::push_front(const string ¤t) {
head = new node;
head->next; // THIS LINE
}
原因:此代码使用新的(无效,请参见上文了解原因)节点分配盲目地覆盖头
指针中当前占用的内容。以前head
中的任何内容都将永远泄漏,而当前中的任何内容都是未使用的。通过将current
作为值分配一个新节点,将其next
指针设置为head
并将head
设置为新节点来解决此问题:
void list::push_front(const string ¤t)
{
node *p = new node(current);
p->next = head;
head = p;
}
无限递归
ostream& operator<<(ostream& out, const list& current)
{
out << current;
return out;
}
原因:这将通过对i
迭代的有效性检查来不受限制地遍历列表。现在想象一下,当传递除-1
之外的任何内容时,它在一个空列表(在您的例子中,这意味着head
是非null的,但是head->next
是null的)上做了什么:对于i=0
,它将返回null,对于其他所有内容来说都是完全未定义的行为
空指针取消引用
inline node *list::findnode(int i)
{
if (i == -1)
return head;
node *p = head->next;
while (i--)
p = p->next;
return p;
}
void list::insert(int i, const string &din)
{
node *p = new node(din);
node *pp = findnode(i-1);
p->next = pp->next;
pp->next = p;
N++;
}
list deck[4];
这假设pp
在返回时永远不会为空,并且正如我们已经在前面的项目中讨论过的,当head
是列表中的唯一节点时,它肯定会为空。这不会在使用pp
进行解引用之前尝试检查NULL。这种轻率的处理和必须考虑的例外情况与维护“哨兵”头部节点直接相关。最简单的修复方法是(a)不使用哨兵节点;使用通用sentinel值nullptr
,并且(b)在使用返回值之前检查返回值
模棱两可的引用:排名
card = rank[ rand()%13 ];
原因:标准库定义了一个名为的特殊结构,用于确定多维数组中的维数。使用名称空间std代码>在代码的顶部,编译器现在被迫选择哪一个(命名空间std
中的一个或在此代码之前定义的数组),但它不能明确地这样做。因此它不会编译。注意:这是通过隐式包含引入的,可能包含在
、
、
或许多其他嵌套包含中。您可以通过多种方式解决它,包括(但不限于)使用
子句创建一个,将秩
数组重命名为不冲突的数组,在函数中使用局部静态秩
的函数包装器等
从有符号类型到无符号类型的隐式转换(次要)
原因:接受一个无符号int
参数;您正在传递一个有符号整数。static cast
转换为unsigned int
或将seedValue
的类型更改为unsigned int
无效代码
inline node *list::findnode(int i)
{
if (i == -1)
return head;
node *p = head->next;
while (i--)
p = p->next;
return p;
}
void list::insert(int i, const string &din)
{
node *p = new node(din);
node *pp = findnode(i-1);
p->next = pp->next;
pp->next = p;
N++;
}
list deck[4];
雷亚斯