c++ - C++ 茎叶图。我不明白如何制作链表的链表
问题描述
我有一个项目使用链表制作茎叶图,但我不断收到我什至不理解的错误。如何制作链表的链表?我必须以这种方式完成作业,所以我不能以其他方式完成,我必须从下面的文件开始工作。我的顶部茎链表有效,但它似乎没有访问叶子部分,我收到以下错误:
“0x0000000000404050 处的指令在 0x000000000000001E 处引用。无法读取内存。”
这是我的代码:
* Driver.cpp
*/
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
#include "StemAndLeaf2.h"
int main()
{
ifstream fin("input.txt");
int x;
unsigned short leafunit, stemunit;
fin >> leafunit >> stemunit;
StemAndLeaf one;
one.setLeafUnit(leafunit);
one.setStemUnit(stemunit);
while (fin >> x)
{
one.addTerm(x);
cout << "Insert: " << x << endl;
cout << "StemAndLeafPlot: " << endl;
cout << one << endl;
}
cout << "The smallest term: " << one.getSmallestTerm() << endl;
cout << "The largest term: " << one.getLargestTerm() << endl;
return 0;
}
/*
* SteamAndLeaf2.h
*/
#ifndef STEAMANDLEAF2_H_
#define STEAMANDLEAF2_H_
#include <math.h>
#include <list>
#include <ostream>
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_TEST_INCLUDES */
#include "Stem2.h"
class StemAndLeaf
{
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_FRIEND_CLASSES */
public:
StemAndLeaf(){FRONT_ptr = NULL; REAR_ptr = NULL;};
~StemAndLeaf()
{
while(FRONT_ptr != NULL)
{
Cursor = FRONT_ptr;
FRONT_ptr = Cursor->getNext();
delete Cursor;
}
}
unsigned short getLeafUnit() const { return leafUnit; }
void setLeafUnit(unsigned short leafUnit) { this->leafUnit = leafUnit; }
unsigned short getStemUnit() const { return stemUnit; }
void setStemUnit(unsigned short stemUnit) { this->stemUnit = stemUnit; }
/**
* @brief Get the smallest term in the datastructure. The term MUST be reconstructed
*
* @return unsigned short
*/
unsigned short getSmallestTerm() const
{
return ((FRONT_ptr->getValue()*10))+(FRONT_ptr->findSmallestValue()));
}
/**
* @brief Get the largest term in the datastructure. The term MUST be reconstructed
*
* @return unsigned short
*/
unsigned short getLargestTerm() const
{
return ((REAR_ptr->getValue()*10))+(REAR_ptr->findLargestValue()));
}
/**
* @brief Adds the term to the data structure. Insertion MUST be ordered, both for Stem and the Leaf
*
* @param term the value to add
*/
void addTerm(unsigned short term)
{
Insert = new Stem();
Insert->setValue(term/10);
Insert->setLeafList(Insert->getLeafLink());
if(isEmpty())
{
Insert->setLeafCount(1);
Insert->insert(term%10);
FRONT_ptr = Insert;
REAR_ptr = Insert;
}
else
{
for(Cursor = FRONT_ptr; Cursor != NULL; Prev = Cursor, Cursor = Cursor->getNext())
{
Insert->setLeafCount(1);
Insert->insert(term%10);
if((Cursor == FRONT_ptr) && (Cursor->getValue() > Insert->getValue()))
{
Insert->setNext(Cursor);
FRONT_ptr = Insert;
}
else if((Cursor == REAR_ptr) && (Cursor->getValue() < Insert->getValue()))
{
Cursor->setNext(Insert);
REAR_ptr = Insert;
}
else if((Prev->getValue() < Insert->getValue()) && (Cursor->getValue() > Insert->getValue()))
{
Prev->setNext(Insert);
Insert->setNext(Cursor);
}
else if(Insert->getValue() == Cursor->getValue())
{
if(!Cursor->insert(term%10))
{
Cursor->incrementLeafCount();
}
}
break;
}
}
}
/*
* Used to display/debug the StemAndLeaf diagram
* will look exactly like this (using example in project):
*
* 0 | 0:1
* ...
* 2 |
* 3 | 6:2 9:1
*
* You will not be given too much data to overrun 80 characters
*/
friend std::ostream &operator<<(std::ostream &out, const StemAndLeaf &x)//;
{
out << x.FRONT_ptr->getValue() << " | ";
return out;
}
private:
unsigned short leafUnit; // increment of each leaf in this particular structure
unsigned short stemUnit; // increment of each stem in this particular structure
Stem *FRONT_ptr, *REAR_ptr, *Insert, *Prev, *Cursor;
inline bool isEmpty() const { return FRONT_ptr == nullptr; }
};
#endif /* STEAMANDLEAF2_H_ */
/*
* Steam2.h
*/
#ifndef STEM2_H_
#define STEM2_H_
#include <ostream>
#include <list>
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_TEST_INCLUDES */
#include "Leaf2.h"
class Stem
{
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_FRIEND_CLASSES */
public:
Stem(){FRONT_ptr = NULL; REAR_ptr = NULL;}
virtual ~Stem(){};
unsigned short getLeafCount() const { return m_LeafCount; }
void setLeafCount(unsigned short LeafCount) { m_LeafCount = LeafCount; }
void incrementLeafCount() { m_LeafCount++; }
void decrementLeafCount() { m_LeafCount--; }
Leaf *getLeafLink() const {return FRONT_ptr;}
void setLeafList(Leaf *LeafList) { FRONT_ptr = LeafList; }
unsigned short getValue() const { return m_Value; }
void setValue(unsigned short value) { m_Value = value; }
Stem *getNext() const { return m_Next; }
void setNext(Stem *next) { m_Next = next; }
/**
* @brief Add the value to the stem. Returns trues if a new lef was created
*
* @param value The number to insert
* @return true if a new leaf was created
* @return false if we've seen the value before
*/
bool insert(unsigned short value)
{
Insert = new Leaf();
Insert->setValue(value);
if(FRONT_ptr = NULL)
{
FRONT_ptr = Insert;
REAR_ptr = Insert;
return true;
}
else
{
for(Cursor = FRONT_ptr; Cursor != NULL; Prev = Cursor, Cursor = Cursor->getNext())
{
if(Cursor->getValue() == Insert->getValue())
{
Cursor->incrementCount();
return false;
}
else
{
if((Cursor == FRONT_ptr) && (Cursor->getValue() > Insert->getValue()))
{
Insert->setNext(Cursor);
FRONT_ptr = Insert;
}
else if((Cursor == REAR_ptr) && (Cursor->getValue() < Insert->getValue()))
{
Cursor->setNext(Insert);
REAR_ptr = Insert;
}
else if((Prev->getValue() < Insert->getValue()) && (Cursor->getValue() > Insert->getValue()))
{
Prev->setNext(Insert);
Insert->setNext(Cursor);
}
return true;
}
}
}
}
unsigned short findSmallestValue()
{
if(FRONT_ptr != NULL){
return FRONT_ptr->getValue();}
else {return 0;}
}
unsigned short findLargestValue()
{
if(REAR_ptr != NULL){
return REAR_ptr->getValue();}
else {return 0;}
}
private:
// they are given the code for a L.L.
Leaf *FRONT_ptr, *REAR_ptr, *Insert, *Prev, *Cursor;
/**
* Stem Value
*/
unsigned short m_Value;
/**
* How many leaves in this stem
*/
unsigned short m_LeafCount;
/**
* Pointer to the next stem
*/
Stem *m_Next;
};
#endif /* STEM2_H_ */
/*
*Leaf2.h
*/
#ifndef LEAF2_H_
#define LEAF2_H_
#include <ostream>
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_TEST_INCLUDES */
struct Leaf
{
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_FRIEND_CLASSES */
Leaf()
: m_Count(1)
{
}
unsigned short getValue() const { return m_Value; }
void setValue(unsigned short value) { m_Value = value; }
unsigned short getCount() const { return m_Count; }
void setCount(unsigned short count) { m_Count = count; }
void incrementCount() { m_Count++; }
void decrementCount() { m_Count--; }
Leaf *getNext() const { return m_Next; }
void setNext(Leaf *next) { m_Next = next; }
/**
* @brief Operator overload to print the Leaf in a nice format According to
* the project description the format should be "value:count"
*
* @param out
* @param leaf
* @return std::ostream&
*/
friend std::ostream &operator<<(std::ostream &out, const Leaf &leaf)
{
out << leaf.m_Value << ":" << leaf.m_Count;
return out;
}
private:
unsigned short m_Value;
unsigned short m_Count;
Leaf *m_Next;
};
#endif /* LEAF2_H_ */
输入文件是具有以下值的 .txt 文件:
1
10
22
13
8
23
即使我将“添加术语”调用之后的所有内容都转换为注释,我也会收到错误消息,并且我知道叶子部分不起作用,因为当我运行“findSmallestTerm”和“findLargestTerm”时,它只会给我词干值。除了叶子值的错误之外,我的代码还有很多问题,但我并不是在要求整个项目的答案,我只需要帮助来连接茎和叶列表,如果这有意义的话。很抱歉在这里转储所有代码,但我不知道问题的哪一部分,所以我不知道什么是相关的。
更新:我删除了一些不必要的代码并添加了输入文件的信息。
解决方案
崩溃是由未初始化的数据成员和错误的检查语句引起的:
if(FRONT_ptr = NULL)
这应该是:
if(FRONT_ptr == NULL)
Stem::m_Next 应该被初始化:
Stem *m_Next=NULL;
Stem::m_Next 应该被初始化:
Leaf *m_Next=NULL;
Prev
进入for循环后应该初始化变量:
void addTerm(unsigned short term) {
// Prev should be inited or the crash happens
for (Prev = Cursor, Cursor = FRONT_ptr; Cursor != NULL;
Prev = Cursor, Cursor = Cursor->getNext()) {
}
}
Stem 类应该有析构函数以避免内存泄漏:
virtual ~Stem() {
while (FRONT_ptr != NULL) {
Cursor = FRONT_ptr;
FRONT_ptr = Cursor->getNext();
delete Cursor;
}
};
该代码还有其他一些难闻的气味和错误:
- 临时变量不应该是数据成员:INsert、Prev、Cursor
Stem::Insert
,StemAndLeaf::Insert
当数据已经存在于列表中时内存泄漏,新元素尚未插入列表中,应该删除指针- 忘记在访问指针之前检查指针是否为 NULL:
getSmallestTerm
,getLargestTerm
推荐阅读
- jmeter - 获取 onRun 单元格文本并用作过滤器中的参数
- java - 如何根据从第一个选择标签中选择的值填充第二个 struts2 选择标签?
- git - 在 Git OverWrite master 分支与另一个分支之后,master 分支的所有历史记录都被删除了吗?
- abap - 查找支付 VIM 发票的付款日期和用户
- sql-server - 可以缓存多少数据以获得更好的性能
- c++ - pegtl - 如何跳过整个语法的空格
- java - 在多个步骤定义类之间传递场景上下文
- java - Spring Boot 中的所有资源都需要这个可能的 set defual 角色吗?
- android - 超过 26 岁的 Android 文件提供程序问题
- angular - 在扩展面板中突出显示扩展面板的单选按钮