这门课有什么问题?

What's wrong with this class?

本文关键字:问题 什么      更新时间:2023-10-16

我认为问题是在main(),但这编译得很好,但我没有得到输出。我想可能是初始化不正确因为在调试模式下它写的是
" myCharQ {item=0x0018fa00 "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ̺yâpú" front=-858993460 rear=-858993460 ...} "

你如何重写它使它是正确的?我刚开始上课,所以任何帮助都会很有用。

下面是一个基于Array的Queue类

#include <iostream>
#include <cstdlib>
using namespace std;
const int MaxQueueSize = 10; // Queue Struct can hold up to 10 char.
typedef char ItemType; // the queue's data type is char
class CPPQueue
{
public:
    CPPQueue();
    ItemType item[MaxQueueSize];
    void initQueue(CPPQueue q);
    bool IsEmpty(CPPQueue q);
    bool IsFull(CPPQueue q);
    void Enqueue(CPPQueue q, ItemType newItem);
    void PrintQ(const CPPQueue q);
    void PrintQueueInfo(CPPQueue myQ);
    ItemType Dequeue(CPPQueue q);
private:
    int front, rear;
    int count;
};
CPPQueue::CPPQueue() 
{
    int front, rear, count = 0;
}
void CPPQueue::initQueue(CPPQueue q)
{
    q.front = q.rear = q.count = 0;
}
bool CPPQueue::IsEmpty(CPPQueue q)
{
    return (q.count == 0);
}
bool CPPQueue::IsFull(CPPQueue q)
{
    return (q.count == MaxQueueSize);
}
void CPPQueue::Enqueue(CPPQueue q, ItemType newItem)
{
    if(q.count == MaxQueueSize)
    {
        cerr << "Error! Queue is full, cannot enqueue item.n" << endl;
        exit(1);
    }
    q.item[q.rear] = newItem;
    q.rear++;
    if (q.rear == MaxQueueSize)
    {
        q.rear = 0; // adjustment for circular queue
    }
    q.count++;
}
ItemType CPPQueue::Dequeue(CPPQueue q)
{
    ItemType theItem;
    if(q.count == 0)
    {
        cerr << "Error! Queue is empty, cannot dequeue item.n" << endl;
        exit(1);
    }
    theItem = q.item[ q.front ];
    q.front++;
    if (q.front == MaxQueueSize)
    {
        q.front = 0; // adjustment for circular queue
    }
    q.count--;
    return theItem;
}
// Function PrintQ() prints the contents of the queue without changing
// the queue. Printing starts at the "front" index and stops before we
// get to the "rear" index. A decrementing counter controls the loop.
//
void CPPQueue::PrintQ(const CPPQueue q)
{
    int i;
    int qindex = q.front;
    for(i = q.count; i > 0; i--)
    {
        cout << q.item[qindex] ;
        qindex = (++qindex) % MaxQueueSize; // adjustment for circular queue
        if(i > 1)
            cout << ", ";
    }
}
// Helper function for the main program below.
void CPPQueue::PrintQueueInfo(CPPQueue myQ)
{
    cout << "The queue contains: ";
    PrintQ(myQ);
    cout << endl;
}
int main()
{
    CPPQueue myCharQ;// queue holds characters
    char ch; // char dequeued
    myCharQ.initQueue(myCharQ);
    myCharQ.Enqueue(myCharQ, 'a'); myCharQ.PrintQueueInfo(myCharQ);
    myCharQ.Enqueue(myCharQ, 'b'); myCharQ.PrintQueueInfo(myCharQ);
    myCharQ.Enqueue(myCharQ, 'c'); myCharQ.PrintQueueInfo(myCharQ);
    ch = myCharQ.Dequeue(myCharQ); myCharQ.PrintQueueInfo(myCharQ);
    ch = myCharQ.Dequeue(myCharQ); myCharQ.PrintQueueInfo(myCharQ);
    myCharQ.Enqueue(myCharQ, 'e');
    myCharQ.Enqueue(myCharQ, 'f'); myCharQ.PrintQueueInfo(myCharQ);
    myCharQ.Enqueue(myCharQ, 'g'); myCharQ.PrintQueueInfo(myCharQ);
    cout << endl;
    // print the dequeued characters
    while(!myCharQ.IsEmpty(myCharQ))
    {
        ch = myCharQ.Dequeue(myCharQ);
        cout << ch << " ";
    }
    cout << endl << endl;
    return 0;
}

不初始化成员变量frontrearcount。通过再次声明具有相同名称的变量,可以在构造函数中隐藏它们。删除int并分配它们(虽然这不是为什么值不能正确打印的原因,更多关于这一点)。实际上,也不要这样做;使用初始化列表:

CPPQueue::CPPQueue() 
  : front(0), rear(0), count(0) 
{ }

还有,为什么你有一个initQueue函数?你已经有了一个构造函数,依靠它来初始化你的实例(这不是C!)。

接下来,像IsEmpty这样的函数是非静态成员函数,但它们不对当前实例进行操作。不要将queue作为参数,只要返回实例是空的、满的或其他的。您的代码必须像这样使用:

Queue q;
q.IsEmpty(q);

只是奇怪。所有的成员函数都是这样操作的。当你可以调用成员函数时,一个指向当前实例的隐式指针作为一个隐藏参数传递(this)。因此,每次调用函数时,它都在调用它的实例的上下文中进行操作。你不需要把实例作为参数。

还要认识到,所有的函数都是按值接受参数的。您将疯狂地创建这些队列的副本。如果修改了参数,调用者将看不到它。例如:

void CPPQueue::initQueue(CPPQueue q)
{
    q.front = q.rear = q.count = 0;
}

这在本质上是无用的(除了初始化函数是不必要的)。在操作副本时,对q.frontq.rearq.count的更改在该函数之外是不可见的。

所以即使你的构造函数由于变量遮蔽而坏了,这个就是为什么你仍然不打印你在调用initQueue后期望的东西。你正在修改一个副本

至于你的实现,它一点也不健壮。将底层数组公开给类的客户机。这是个坏主意。队列中的项不应该是可直接访问的。如果我决定直接对数组进行处理呢?现在所有的状态函数都错了。frontrearcount都可能无效,因为我没有通过任何函数就修改了队列的状态。

甚至没有必要;我所能做的就是对项目进行排队和退队。就是这样。这就是队列的作用。它不是一个数组,如果我想要一个数组,我将使用一个。

所以,总之,开始学习一门相对复杂的语言是值得称赞的。坚持下去,不要气馁,我们都必须在某些时候学习这些东西。

编辑:我必须运行,但这里是你的一些类的快速重写。我已经删除了项目类型的typedef。为什么?这是不必要的。您不会在某个平台或其他环境变化时将其更改为另一种类型,因此类型定义仅会损害类的可用性。类型定义对于那些可能因为环境原因而改变的东西(例如int32_t)来说是很好的,但是如果它们不能帮助你或你的代码的客户端,它们只是一个额外的阻碍。

class CPPQueue
{
public:
    CPPQueue();
    bool IsEmpty() const;
    bool IsFull() const;
    void Enqueue(char newItem);
    char Dequeue();
    void PrintQ() const;
    void PrintQueueInfo() const;
private:
    char item[MaxQueueSize];
    int front
    int rear;
    int count;
};
CPPQueue::CPPQueue()
  : front(0), rear(0), count(0) { }
bool CPPQueue::IsEmpty() const
{ 
    // you don't actually need the this pointer
    // here, but I included it to make it clear
    // that you are accessing the count variable
    // for the current instance of a CPPQueue
    return this->count == 0; 
}

我希望这能帮助你重写剩下的课程,我要走了。我在不应该改变CPPQueue内部状态的函数声明中添加了const。搜索一下"const正确性",更好地理解为什么要这样做。好运!

构造函数:

int front, rear, count = 0;

是错误的。

你应该使用成员初始化器(在构造函数名后面加冒号)。

还要注意的是,你到处都是按值传递——你可能想通过引用传递——看看每个函数参数并问自己,"我是想要一个新的参数副本,还是我想引用我传入的相同参数(相同的内存位置)?"

CPPQueue::CPPQueue() :
  front(0), rear(0), count(0) 
{
}

注意:@OP这是基础的c++ -你需要仔细阅读并打下基础,否则你会遇到很多很多更难解决的问题。