这堂课怎么了?

时间:2011-10-22 23:54:23

标签: c++ class

我认为问题出现在main()中,但是编译得很好,但我没有输出。我想也许它不是正确的,因为在调试模式下它说 “myCharQ {item=0x0018fa00 "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ̺yâpú" front=-858993460 rear=-858993460 ...}

你会如何改写它以使它合适?我刚开始上课,所以任何帮助都会有用。

以下是基于数组的队列类

#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;
}

2 个答案:

答案 0 :(得分:6)

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

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

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

接下来,像IsEmpty这样的函数是非静态成员函数,但它们不在当前实例上运行。不要将队列作为参数,只要在实例为空,满,等等时返回。您的代码必须像这样使用:

Queue q;
q.IsEmpty(q);

很奇怪。您的所有成员函数都以这种方式运行。当您使用成员函数时,将指向当前实例的隐式指针作为隐藏参数(this)传递。因此,每次调用函数时,它都会在调用它的实例的上下文中运行。您不需要将实例作为参数。

还要意识到所有函数都按值来获取参数。你将像疯了一样创建这些队列的副本。如果修改参数,调用者将无法看到它。例如:

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

这基本上是无用的(除了不需要初始化函数的事实)。当您在副本上操作时,对q.frontq.rearq.count的更改将不会在该函数之外显示。

因此,即使您的构造函数由于变量阴影而中断,也是您在调用initQueue后仍然无法打印预期的原因。 您正在修改副本

至于你的实现,它根本不健壮。您将基础数组公开给您的类的客户端。这是一个坏主意。不应直接访问队列中的项目。如果我决定直接使用数组怎么办?现在你所有的状态变量都是错误的。 frontrearcount都可能无效,因为我修改了队列状态而未通过任何功能。

甚至没有必要;我应该做的就是排队和出队物品。而已。这就是队列的作用。它不是一个数组,如果我想要一个数组,我会用一个。

因此,总而言之,开始学习一门相对复杂的语言。坚持下去,不要气馁,我们都必须在某些时候学习这些东西。

编辑:我必须跑步,但这里是你的一些课程的快速改写。我已删除了item类型的typedef。为什么?这是不必要的。您不会将其更改为某个平台或其他环境更改的其他类型,因此typedef只会伤害您的类的可用性。对于某些环境原因,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; 
}

我希望这可以帮助你重写课程的其余部分,现在就去。我在函数声明中添加了const,这些函数不应该改变CPPQueue的内部状态。搜索“const correctness”以更好地了解为什么要做这样的事情。祝你好运!

答案 1 :(得分:4)

在你的构造函数中:

int front, rear, count = 0;

错了。这些是影响成员变量的局部变量。

您应该使用成员初始值设定项(在构造函数名后面加冒号)。

另请注意,您在整个地方传递值 - 您可能希望通过引用传递 - 查看每个函数参数并问自己,“我是否需要我的参数的新副本或我是否要参考到我传入的相同参数(相同的内存位置)?“

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

注意:@OP这是初级C ++ - 您需要阅读并掌握基础知识,否则您将遇到很多困难,更难以解决问题。