LINUX.ORG.RU

Класс для работы с очередью


0

0

Это попытка реализовать класс для работы с очередью сообщений.
Сообщение задается в виде структуры, которая содержит указатель
на следующий элемент (такую же структуру).
Хотелось бы узнать, на сколько правильно это организовано,
плюс, что на счет структур с точки зрения именно С++?

Были ьы интересны замечания.

============================BEGIN============================
#ifndef QUEUE_H
#define QUEUE_H

// Message structure
struct queueNodeStruct {
  char to[128];
  char message[512];
  struct queueNodeStruct *nextPtr;
};

typedef struct queueNodeStruct queueNode;
typedef queueNode *queueNodePtr;



// Queue class
class queueClass {
  private:
    queueNodePtr headPtr;
    queueNodePtr tailPtr;

  public:
    queueClass( );
    int isEmpty( queueNodePtr );
    void dequeue( );
    void enqueue( char [], char []);
    queueNodePtr queueHead( );
    queueNodePtr queueTail( );
};


// Constructor
queueClass::queueClass( ) {

  headPtr = NULL;
  tailPtr = NULL;
}


// Queue is empty?
int queueClass::isEmpty( queueNodePtr headPtr ) {

  return headPtr == NULL;
}


// Enqueue -- add message to queue
void queueClass::enqueue( char to[], char msg[]) {
  queueNodePtr newPtr;

  newPtr = new queueNode;
  if( newPtr != NULL ) {
    strncpy( newPtr->to, to, 128 );
    strncpy( newPtr->message, msg, 512 );
    newPtr->nextPtr = NULL;
    if( isEmpty( headPtr ) ) {
      headPtr = newPtr;
    }
    else {
      tailPtr->nextPtr = newPtr;
    }
    tailPtr = newPtr;
  }
  else {
    std::cout << "Cannot allocate memory in queue for new item.\n";
  }
}


// Dequeue -- remove message from queue
void queueClass::dequeue( ) {
  queueNodePtr nodeToDel;

  if( !isEmpty( headPtr ) ) {
    nodeToDel = headPtr;
    headPtr = headPtr->nextPtr;
    if( headPtr == NULL ) {
      tailPtr = NULL;
    }
    delete nodeToDel;
  }
}


// Get head pointer
queueNodePtr queueClass::queueHead( ) {

  return headPtr;
}


// Get tail pointer
queueNodePtr queueClass::queueTail( ) {

  return tailPtr;
}

#endif
=============================END=============================



И пример работы с очередью, конечно примитивный, но просто
для проверки работы :-)

============================BEGIN============================

#include <iostream>
#include "queue.h"

void instructions( void );
void printQueue( queueNodePtr currentNode );


int main() {
  queueClass queue;
  int choice;
  char to[128], msg[512];


  instructions();
  std::cout << "? ";
  std::cin  >> choice;

  while( choice != 3 ) {
    switch( choice ) {
      case 1:
        std::cout << "Message to: ";
        std::cin  >> to;
        std::cout << "Message: ";
        std::cin  >> msg;
        queue.enqueue( to, msg );
        printQueue( queue.queueHead() );
        break;

      case 2:
        queue.dequeue( );
        printQueue( queue.queueHead() );
        break;

      default:
        std::cout << "Invalid choice\n";
        instructions();
        break;
    }

    std::cout << "? ";
    std::cin  >> choice;
  }

  std::cout << "End of run.\n";
  return 0;
}


void instructions( void ) {

  std::cout << "Your choice:\n" << "  1. add item\n" << "  2. remove item\n" << "  3. quit\n";
}


void printQueue( queueNodePtr currentPtr ) {

  if( currentPtr == NULL ) {
    std::cout << "Queue is empty" << std::endl;
  }
  else {
    std::cout << "The queue is:" << std::endl;
    while( currentPtr != NULL ) {
      std::cout << currentPtr->to << " -> [" << currentPtr->message << "]" << std::endl;
      currentPtr = currentPtr->nextPtr;
    }
  }
}
=============================END=============================
Ответ на: комментарий от fenring

Спасибо за совет. Это и было интересно узнать. :-)

igor_ua
() автор топика

std::queue - наиболе правильный выбор. Но есть пару ньюансов именно в вашем, не правильно реализованных с точки зрения С++, на которые хотелось бы указать (ведь не все реализовано в std):
1. class должен скрывать особенности реализации, а то, что он в методах queueHead и queueTail возвращает структуру, частью которой является служебное поле, нужное для реализации очереди, не совсем красиво.
2. вытекает из первого (все инкапсулируется в рамках класса),
struct queueNodeStruct {
char to[128];
char message[512];
struct queueNodeStruct *nextPtr;
};

typedef struct queueNodeStruct queueNode;
typedef queueNode *queueNodePtr;

Надо запихнуть в private класса.
3. Все от тудова же, важной информацией является char to[128]; char message[512]; Есть такой утилитный класс std::pair - пользуйся им смело.
4. Не вижу деструктора
5. Само по себе ограничение на длину строк в структуре не обосновано. Нет действительно стоящей причины так делать. Юзай просто char *. strdup() и std::auto_ptr, дабы следить за памятью.
6. Желательно по возможности вообще использовать std::string (не указатель на std::string)
7. Забыл указать какие исключения будут брошены и указать константные методы (методы, не меняющие данные).

ИТОГО класс:

// Queue class
class queueClass {
private:
struct queueNodeStruct {
char *to; //[128];
char *message; //[512];
/*struct*/ queueNodeStruct *nextPtr;
};
typedef /*struct*/ queueNodeStruct queueNode; // в С++ не надо указывать, что тип - это структура, ты же не пишешь так: class std::sring my_string;
//typedef queueNode *queueNodePtr; -- вообще глупость (ты программируешь на С++, а не на паскале, показывай явно, что это указатель

public:
typedef std::auto_ptr<char *> CharPtr;
typedef std::pair<CharPtr, CharPtr> StringsPair;

private:
queueNode *headPtr; queueNode *tailPtr;

public:
queueClass()
throw ();
virtual ~queueClass()
throw ();
/*int в плюсах есть тип bool*/
bool isEmpty(/*queueNodePtr - глупость, скрываем все.*/) const
throw ()
{
return headPtr == 0;
}
void dequeue()
throw ();
void enqueue(const char *, const char *)
throw (std::bad_alloc);
StringsPair queueHead( ) const
throw ();
StringsPair queueTail( ) const
throw ();
};

mutable
()
Ответ на: комментарий от mutable

Да, это классное объяснение. :) Огромное спасибо автору.

А мне еще читать и читать, а затем учиться и учиться.

Спасибо большое.

igor_ua
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.