【问题标题】:Calling functions from header files从头文件调用函数
【发布时间】:2015-05-23 02:17:21
【问题描述】:

家庭作业
我试图从我的三个头文件中的每一个调用我的主函数中的两个函数。

#ifndef UNSORTEDPQ_H
#define UNSORTEDPQ_H

#include <exception>
#include <cstddef>
#include <cmath>
using namespace std;

template <class Type>
class UnsortedPQ
{
private:
struct DLLNode {
    Type data;
    DLLNode *prev;
    DLLNode *next;
};

DLLNode *head, *tail, *node;

public:
void insertUPQ ( Type data ){
  DLLNode *newnode = new DLLNode;
  newnode -> node = data;
  newnode -> prev = NULL;
  if (isEmpty()){
      newnode -> next = NULL;
      head = tail = newnode;
  } 
  else {
      newnode -> next = NULL;
      newnode -> prev = node -> prev -> next;
      tail = newnode;
  }
 }

 // removes and returns the minimum value in the queue
 // throws an exception if the queue is empty
 Type removeUPQ ( void ) throw(exception){
  if (isEmpty()) {
      exception("Can't dequeue empty Priority Queue");
  }

  Type min = head -> data;

  // special case: queue has one element
  if (size()==1){
      while (head != NULL) {
          DLLNode *next = head -> next;
          delete head;
          head = next;
      }
      return min;
  }

  // determine minimum element
  for (node = head; node != NULL; node = node -> next){
      if (node -> data < min) {
          min = node -> data;
      }
  }
  // special case: queue has two elements
  if (size()==2){
      if (head -> data== min){
          delete head;
          tail -> previous = NULL;
          head = tail;
      } 
      else {
          delete tail;
          head -> next = NULL;
          tail = head;
      }
      return min;
  }

  // remove element and update next and previous for elements around it
  for (node = head; node != NULL; node = node -> next){
      if (node -> data == min){
          // special case if min elem is head
          if (node == head){
              DLLNode*oldHead=head;
              head = head -> next;
              head -> prev = NULL;
              delete oldHead;
              return min;
          }
          // special case if min elem is tail
          if(node == tail){
              DLLNode*oldTail=tail;
              tail = tail-> prev;
              tail -> next = NULL;
              delete oldTail;
              return min;
          }
          // for cases where min elem is not head or tail
          DLLNode *prevNode = node -> prev;
          DLLNode *nextNode = node -> next;
          prevNode -> next = node -> next;
          nextNode -> prev = node -> prev;
          delete node;
          return min;
      }
}

#ifndef SORTEDPQ_H
#define SORTEDPQ_H

#include <exception>
#include <cstddef>
#include <cmath>
using namespace std;

template <class Type>
class SortedPQ
{
private:
    struct DLLNode {
        Type data;
        DLLNode *prev;
        DLLNode *next;
    };

    DLLNode *head, *tail, *node;


public:

// inserts a piece of data into the priority queue
void insertSPQ ( Type data ){
DLLNode curr = head;
while(curr != tail && node -> data <= curr -> data){
    curr = curr -> next;
}
DLLNode tempCurr = curr;
node -> next = tempCurr;
node -> prev = tempCurr -> prev;
tempCurr -> prev -> next = node;
tempCurr -> prev = node;
}
// removes and returns the minimum value in the queue
// throws an exception if the queue is empty
Type removeSPQ ( void ) throw(exception){
 if (isEmpty()) {
    exception("Can't dequeue an empty Priority Queue");
}
Type min = head -> node;
if (node == head){
    DLLNode*oldHead=head;
    head = head -> next;
    head -> prev = NULL;
    delete oldHead;
    return min;
}

#ifndef HEAPPQ_H
#define HEAPPQ_H

#include <exception>
#include <cstddef>
#include <cmath>
using namespace std;

template <class Type>
class HeapPQ
{
private:
    Type *data;
    Type heapSize;
    Type arraySize;
    Type floor(Type arg);
    Type getLChildIndex(Type nodeIndex){
        return 2 * nodeIndex + 1;
    } 

    Type getRightChildIndex(Type nodeIndex){
        return 2 * nodeIndex + 2;
    }

    Type getParentIndex(Type nodeIndex){
        return floor((nodeIndex - 1) / 2);
    }

    public:   
    void HeapPropertyInsert(Type nodeIndex){
    Type parentIndex, tmp;
    if(nodeIndex != 0){
        parentIndex = getParentIndex(nodeIndex);
        if(data[parentIndex] > data[nodeIndex]){
            tmp = data[parentIndex];
        data[parentIndex] = data[nodeIndex];
        data[nodeIndex] = tmp;
        HeapPropertyInsert(parentIndex);
        }
    }
   }

   // inserts a piece of data into the priority queue
   void insertHPQ ( Type data ) throw(exception){
    if (heapSize == arraySize){
        exception ("Cannot insert, heap is full");
    }
    else{
        heapSize++;
        data[heapSize - 1] = data;
        HeapPropertyInsert(heapSize - 1);
    }
   }

   void HeapPropertyRemove(Type nodeIndex){
    Type leftChildIndex, rightChildIndex, minIndex, tmp;
    leftChildIndex = getLChildIndex(nodeIndex);
    rightChildIndex = getRightChildIndex(nodeIndex);
    if(rightChildIndex >= heapSize){
        if(leftChildIndex >= heapSize)
            return;
        else
            minIndex = leftChildIndex;
    }
    else{
        if (data[leftChildIndex] < data[rightChildIndex])
            minIndex = leftChildIndex;
        else
            minIndex = rightChildIndex;
    }
    if(data[nodeIndex] > data[minIndex]){
        tmp = data[minIndex];
        data[minIndex] = data[nodeIndex];
        data[nodeIndex] = tmp;
        HeapPropertyRemove(minIndex);
    }
   }

   // removes and returns the minimum value in the queue
   // throws an exception if the queue is empty
   Type removeHPQ ( void ) throw(exception){
    if(isEmpty())
        exception("Cannot remove, heap is empty");
    else{
        data[0] = data[heapSize - 1];
        heapSize--;
        if(heapSize > 0)
            HeapPropertyRemove(0);
    }
   } 

我的 main.cpp:

#include "UnsortedPQ.h"
#include "SortedPQ.h"
#include "HeapPQ.h"
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>

using namespace std;
int main(){

int choice;
int elem;
int array_size = 1024;
char * array = new char[array_size];
int position = 0;

ifstream fin("numbers.txt");
if(fin.is_open()){
    cout << "File opened successfully." << endl;
    while(!fin.eof() && position < array_size){
        fin.get(array[position]);
        position++;
    }
    array[0] = choice;
    switch (choice){
        case '0': //UnsortedPQ
            for(int i = 2; array[i]; i++ ){
                insertUPQ(array[i]); <----- error
                removeUPQ(array[i]); <----- error
            }
            break;
        case '1': //SortedPQ    
            for(int i = 2; array[i]; i++ ){
                insertSPQ(array[i]); <----- error
                removeSPQ(array[i]); <----- error
            }
            break;
        case '2':// HeapPQ  
            for(int i = 2; array[i]; i++ ){
                insertHPQ(array[i]); <----- error
                removeHPQ(array[i]); <----- error
            }
            break;
    }
}
else{
    cout << "File could not be opened." << endl;
}
return 0;
}

我不断收到编译器错误,指出这些函数“未在此范围内声明”。我认为由于包含头文件并且函数是公共的,因此我可以在 main.cpp 中的任何位置随意调用它们。同样,这是家庭作业,所以我不是在寻找快速解决方案,但非常感谢您提供一些建议或正确方向的观点。

【问题讨论】:

  • 您在所有头文件的末尾都缺少#endif
  • Owww...这里的资源太多了。我们不是在解决家庭作业。
  • 例如,insertSPQSortedPQ 类中。这是一种方法。这意味着您只能在类的实例上调用它。而且你似乎在类声明之外的其他地方有一个随机的public:(它只在类/结构中有效)。

标签: c++ scope


【解决方案1】:

这段代码有很多问题。甚至在不涉及单个函数实现可能出现的问题的情况下,需要修复以下错误:

  1. 没有类的实例就不能调用类方法。所以,要调用insertSPQ 方法,你必须有SortedPQ 类。您可以像这样创建一个:

SortedPQ&lt;char&gt; *spq = new SortedPQ&lt;char&gt;;

然后像这样调用函数:

spq-&gt;insertSPQ(array[i]);


  1. 您正在使用不正确的签名调用函数。例如,您尝试调用

spq-&gt;removeSPQ(array[i]);

(在我添加了 spq 类实例之后),但该函数的参数定义为 void,如下所示:

Type removeSPQ(void) throw(exception){

所以你的排序 if 条件应该看起来更像:

    case '1': //SortedPQ    
        SortedPQ<char> *spq = new SortedPQ<char>;

        for (int i = 2; array[i]; i++){
            spq->insertSPQ(array[i]);
            spq->removeSPQ(array[i]);
        }
        break;

当然,这并不能真正解决所有问题,因为您仍然需要从 spq 中释放内存。

此外,正如另一位评论者指出的那样,您缺少 #endif 的。这些应该是每个头文件的最后一行,以关闭您的初始 #ifndef

最后,将类实现和声明放在同一个头文件中通常被认为是一种不好的做法。通常最好有一个用于声明的 .h 文件和一个用于实际实现的单独的 .cpp 文件。它应该按原样工作,而不是最佳实践。

【讨论】:

    【解决方案2】:

    您尝试调用的所有函数都是属于特定方法。为了使用这些方法,您必须创建一个特定对象

    char * array = new char[array_size];
    
    UnsortedPQ<char> Object;
    
    Object.insertUPQ(array[i]);
    

    有一个教程链接解释了 C++ 中的类到底是什么,如何创建和使用它们:

    http://www.cplusplus.com/doc/tutorial/classes/

    【讨论】:

    • 我不需要使用&lt;Type&gt;,因为我的课程是模板化的吗?
    • 你的意思是在每个方法调用上?不。在声明模板类的对象时,你告诉编译器你的类是用什么类编译的:UnsortedPQ&lt;char&gt; Object; 在这种情况下,&lt;Type&gt;&lt;char&gt;,并且类中的所有方法和变量都编译为字符。通过这种方式,您可以创建一个可以处理多种数据类型甚至其他类的类。
    猜你喜欢
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多