Archief - C: queue van struct

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

blackrabbit

Legacy Member
Ik zit hier te knoeien met queue-code die ik van het net heb gehaald:

http://www.cs.sunysb.edu/~skiena/392/programs/queue.h
http://www.cs.sunysb.edu/~skiena/392/programs/queue.c

Alsook deze:
http://www.idevelopment.info/data/Programming/data_structures/c/Queue/queue.h
http://www.idevelopment.info/data/Programming/data_structures/c/Queue/queue.c


Hoe kan ik er voor zorgen dat 1 van deze queues overweg kan met de volgende struct:
Code:
typedef struct SPE_instruction
{
	unsigned int instruction;
	unsigned int arg_count;
	unsigned int arg1;
	unsigned int arg2;
	unsigned int arg3;
} SPE_instruction;
Alvast bedankt!

blackrabbit

Legacy Member
Deze implementatie maakt gebruik van een linked list, maar ook deze krijg ik niet helemaal aan de praat:
Code:
#include <stdlib.h>


typedef struct SPE_instruction queueElementT;
typedef struct queueCDT *queueADT;

queueADT QueueCreate(void);
void QueueDestroy(queueADT queue);
void QueueEnter(queueADT queue, queueElementT element);
int QueueIsEmpty(queueADT queue);

Code:
#include "queue.h"


typedef struct queueNodeTag
{
	queueElementT element;
	struct queueNodeTag *next;
} queueNodeT;


typedef struct queueCDT
{
	queueNodeT *front, *rear;
} queueCDT;


/************* Helper function prototypes ************/

/*
 * Function: NewNode
 * Usage: p = NewNode(element)
 * -----------------------------------
 * Returns a pointer to new node with the
 * specified element filled in.
 */
static queueNodeT *NewNode(queueElementT element);

/**************** Function definitions ***************/

queueADT QueueCreate(void)
{
  queueADT queue;

  queue = (queueADT)malloc(sizeof(queueCDT));

  if (queue == NULL) {
   // fprintf(stderr, "Insufficient memory for new queue.\n");
    exit(1);  /* Exit program, returning error code. */
  }

  queue->front = queue->rear = NULL;

  return queue;
}

int QueueIsEmpty(queueADT queue)
{
	if (queue->front == NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

queueElementT QueueDelete(queueADT queue)
{
	if (queue->front == NULL)
	{  /* Queue is empty, do nothing */
		return NULL;
	}
	else
	{
		queueNodeT* node = queue->front;
		queue->front = queue->front->next;
		return node->element;
	}
}

void QueueDestroy(queueADT queue)
{
  /*
   * First remove each element from the queue (each
   * element is in a dynamically-allocated node.)
   */
  while (!QueueIsEmpty(queue))
  {
	QueueDelete(queue);
	}

  /*
   * Reset the front and rear just in case someone
   * tries to use them after the CDT is freed.
   */
  queue->front = queue->rear = NULL;

  /*
   * Now free the structure that holds information
   * about the queue.
   */
  free(queue);
}

void QueueEnter(queueADT queue, queueElementT element)
{
  queueNodeT *newNodeP;

  /* Get a new node with the information stored in it. */

  newNodeP = NewNode(element);

  /*
   * Link the element into the right place in
   * the linked list.
   */

  if (queue->front == NULL) {  /* Queue is empty */
    queue->front = queue->rear = newNodeP;
  } else {
    queue->rear->next = newNodeP;
    queue->rear = newNodeP;
  }
}



static queueNodeT *NewNode(queueElementT element)
{
  queueNodeT *newNodeP;

  /* Allocate space for a node in the linked list. */

  newNodeP = (queueNodeT *)malloc(sizeof(queueNodeT));

  if (newNodeP == NULL) {
   // fprintf(stderr, "Insufficient memory for new node.\n");
    exit(1);  /* Exit program, returning error code. */
  }

  /* Place information in the node */

  newNodeP->element = element;
  newNodeP->next = NULL;

  return newNodeP;
}

blackrabbit

Legacy Member
queue.h
Code:
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include "MPGA_common.h"

struct my_struct
{
  struct SPE_instruction* num;
  struct my_struct* next;
};

struct my_list
{
  struct my_struct* head;
  struct my_struct* tail;
};

struct my_list* list_add_element( struct my_list*, struct SPE_instruction*);
struct my_list* list_remove_element( struct my_list*);

struct my_list* list_new(void);
struct my_list* list_free( struct my_list* );
queue.c
Code:
/* This Queue implementation of singly linked list in C implements 3
 * operations: add, remove and print elements in the list.  Well, actually,
 * it implements 4 operations, lats one is list_free() but free() should not
 * be considered the operation but  a mandatory practice like brushing
 * teeth every morning, otherwise you will end up loosing some part of
 * your body(the software) Its is the modified version of my singly linked
 * list suggested by Ben from comp.lang.c . I was using one struct to do
 * all the operations but Ben added a 2nd struct to make things easier and
 * efficient.
 *
 * I was always using the strategy of searching through the list to find the
 *  end and then addd the value there. That way list_add() was O(n). Now I
 * am keeping track of tail and always use  tail to add to the linked list, so
 * the addition is always O(1), only at the cost of one assignment.
 *
 *
 * VERISON 0.5
 *
 */

#include  "queue.h"

/* Will always return the pointer to my_list */
struct my_list* list_add_element(struct my_list* s, struct SPE_instruction* i)
{
  struct my_struct* p = malloc( 1 * sizeof(*p) );

  if( NULL == p )
    {
      fprintf(stderr, "IN %s, %s: malloc() failed\n", __FILE__, "list_add");
      return s;
    }

  p->num = i;
  p->next = NULL;

  if( NULL == s )
    {
      printf("Queue not initialized\n");
      return s;
    }
  else if( NULL == s->head && NULL == s->tail )
    {
      /* printf("Empty list, adding p->num: %d\n\n", p->num);  */
      s->head = s->tail = p;
      return s;
    }
  else if( NULL == s->head || NULL == s->tail )
    {
      fprintf(stderr, "There is something seriously wrong with your assignment of head/tail to the list\n");
      free(p);
      return NULL;
    }
  else
    {
      /* printf("List not empty, adding element to tail\n"); */
      s->tail->next = p;
      s->tail = p;
    }

  return s;
}

/* This is a queue and it is FIFO, so we will always remove the first element */
struct my_list* list_remove_element( struct my_list* s )
{
  struct my_struct* h = NULL;
  struct my_struct* p = NULL;

  if( NULL == s )
    {
      printf("List is empty\n");
      return s;
    }
  else if( NULL == s->head && NULL == s->tail )
    {
      printf("Well, List is empty\n");
      return s;
    }
  else if( NULL == s->head || NULL == s->tail )
    {
      printf("There is something seriously wrong with your list\n");
      printf("One of the head/tail is empty while other is not \n");
      return s;
    }

  h = s->head;
  p = h->next;
  free(h);
  s->head = p;
  if( NULL == s->head )  s->tail = s->head;   /* The element tail was pointing to is free(), so we need an update */

  return s;
}

/* ---------------------- small helper fucntions ---------------------------------- */
struct my_list* list_free( struct my_list* s )
{
  while( s->head )
    {
      list_remove_element(s);
    }

  return s;
}

struct my_list* list_new(void)
{
  struct my_list* p = malloc( 1 * sizeof(*p));

  if( NULL == p )
    {
      fprintf(stderr, "LINE: %d, malloc() failed\n", __LINE__);
    }

  p->head = p->tail = NULL;

  return p;
}
Looking good..?

Wanneer ik het volgende doe, krijg ik echter wel nog compile errors:
Code:
struct my_list* dataQueue = NULL;
dataQueue = list_new();

Code:
mpga_spe_lib.h:19: warning: data definition has no type or storage class
mpga_spe_lib.h:19: warning: type defaults to 'int' in declaration of 'dataQueue'
mpga_spe_lib.h:19: error: conflicting types for 'dataQueue'
mpga_spe_lib.h:18: error: previous definition of 'dataQueue' was here
mpga_spe_lib.h:19: warning: initialization makes integer from pointer without a cast
mpga_spe_lib.h:19: error: initializer element is not constant

Kemblin

Legacy Member
is uw vraag nu opgelost? Want uit de laatste post ziet dat er toch zo uit.

blackrabbit

Legacy Member
Wel, ik kom in de buurt, maar nog niet alle problemen zijn opgelost...
Zoals je kan zien, krijg ik nog steeds compile errors bij het gebruik van de linked list implementatie.

Kemblin

Legacy Member
van waar roept ge die list_new() op? Want ik heb precies de indruk dat ge dat vanuit de global scope probeert te doen.

blackrabbit

Legacy Member
Bon, ik ben begonnen met het schrijven van mijn eigen queue ADT, gebaseerd op een array-implementatie. In de context waarin ik die queue ga gebruiken is dat niet zo erg, zelfs beter (beperkt geheugen + enqueuen kan uitgesteld worden moest de queue vol geraken).

Ik plaats later mijn code wel, en misschien nog vragen moest dat nodig blijken ;-)


Kemblin zei:
van waar roept ge die list_new() op? Want ik heb precies de indruk dat ge dat vanuit de global scope probeert te doen.
Geen idee meer, miss was dat wel het probleem, was daarstraks eventjes het noorden kwijt :-)

Toch bedankt!

Kemblin

Legacy Member
Ok, als ge maar weet dat ge enkel functies kunt oproepen in andere functies ;)

blackrabbit

Legacy Member
v0.1

queue.h
Code:
typedef struct instructionQueue
{
	SPE_instruction* array;
	int head;
	int count;
	int size;
} instructionQueue;
//instructionQueueSize

void q_init(instructionQueue* instructionQueue, int size);
void q_push(instructionQueue* instructionQueue, SPE_instruction i);
SPE_instruction q_pop(instructionQueue* instructionQueue);
int q_isFull(instructionQueue* instructionQueue);
int q_isEmpty(instructionQueue* instructionQueue);
void q_destroy(instructionQueue* instructionQueue);

queue.c
Code:
#include "queue.h"
#include <stdlib.h>
#include <stdio.h>

int nextFreePos(instructionQueue* instructionQueue);


void q_init(instructionQueue* instructionQueue, int size)
{
	instructionQueue->array=(SPE_instruction*)malloc(sizeof(SPE_instruction)*size);
	instructionQueue->size=size;
}

void q_push(instructionQueue* instructionQueue, SPE_instruction i)
{
	if(q_isFull(instructionQueue))
	{
		printf("ERROR: Tried to push element in queue while it was full.\nPlease check for fullness (q_isFull) before pushing elements.\n");
		exit(2);
	}
	else
	{
		int freePos=nextFreePos(instructionQueue);
		instructionQueue->count=(instructionQueue->count+1)%instructionQueue->size;
		instructionQueue->array[freePos]=i;
	}
}

//remove & return head instruction
SPE_instruction q_pop(instructionQueue* instructionQueue)
{
	if(q_isEmpty(instructionQueue))
	{
		printf("ERROR: Tried to pop element from queue while it was empty.\nPlease check for emptyness (q_isEmpty) before popping elements.\n");
		exit(2);
	}
	else
	{
		int headPos=instructionQueue->head;
		struct SPE_instruction instr = instructionQueue->array[headPos];
		instructionQueue->head++;
		instructionQueue->count--;
		return instr;
	}
}


int nextFreePos(instructionQueue* instructionQueue)
{
	return (instructionQueue->head+instructionQueue->count)%instructionQueue->size;
}

void q_destroy(instructionQueue* instructionQueue)
{
	free(instructionQueue->array);
}

int q_isFull(instructionQueue* instructionQueue)
{
	if(instructionQueue->count == instructionQueue->size) return 1;
	else return 0;
}

int q_isEmpty(instructionQueue* instructionQueue)
{
	if(instructionQueue->count == 0) return 1;
	else return 0;
}

Compileert zonder problemen.
Kan helaas nog niet runnen, omdat ik eerst paar andere dingen in orde moet brengen.
Ik moet allezins nog wel eens nakijken dat ik geen obvious fouten heb gemaakt met mijn indexes.

MOD: code wat aangepast, eerste bugje gefixed + exit() toegevoegd waar nodig.

Curahee Q

Legacy Member
Waarom geef je een int terug bij q_isEmpty en q_isFull? Waarom niet een bool die true of false terug geeft?

Code:
bool q_isFull(instructionQueue* instructionQueue)
{
	return instrunctionQueu->count == instructionQueu->size;
}

bool q_isEmpty(instructionQueue* instructionQueue)
{
	return instructionQueu->count == 0;
}

Op deze manier kan je deze methods rechtstreeks in een if steken
Code:
if(foo.q_isFull(queu)) {

}

en niet
Code:
if(foo.q_isFull(queu) == 1) {

}

Kemblin

Legacy Member
Nja das één manier, volgens mij lukt het zo ook

Code:
int q_isEmpty(instructionQueue* instructionQueue) {
	return !(instructionQueue->count);
}


Code:
if(foo.q_isEmpty(queu)) {
	// blabla
}

wel ni getest, mss moet ge er dan nog wel wat typecasts tussenflansen :p

*EDIT: blijkbaar gaat dat enkel in C++ werken zonder typecasts, laat maar zitten dus...

blackrabbit

Legacy Member
Curahee Q zei:
Op deze manier kan je deze methods rechtstreeks in een if steken
Code:
if(foo.q_isFull(queu)) {

}

en niet
Code:
if(foo.q_isFull(queu) == 1) {

}
Dat eerste werkt ook hoor: in C is 0 == false, al de rest is true.
Maar ik dacht (verkeerdelijk) dat bool helemaal niet bestond in C. Het keyword bestaat echter wel (hoewel het intern gewoon een integer is, neen?).

Enfin, ik ga dat dan wel aanpassen (is idd gewoon mooier), voorlopig ben ik blij als alles correct werkt :-)

Thanks!

Curahee Q

Legacy Member
Gebruik maar gewoon bool. Als je anders overstapt naar Java of iets anders werkt het dan weer niet. Gebruik de dingen waar ze voor gemaakt zijn ;).

Tyfius

Legacy Member
Curahee Q zei:
Gebruik maar gewoon bool. Als je anders overstapt naar Java of iets anders werkt het dan weer niet. Gebruik de dingen waar ze voor gemaakt zijn ;).
Dan moet uw taal dat natuurlijk wel ondersteunen. Niet alle compilers zijn up to date. (/me wijst naar Microsoft)

bool is pas echt geintroduceerd in C99, en voor de meeste dingen zit die MS compiler nog op C89. Dus by default geen bool. Tenzij ge uw C als C++ gaat compileren, maar dat is dan maar weer de vraag of ge al die andere dingen die dat met zich meebrengt wilt.

blackrabbit

Legacy Member
Curahee Q zei:
Gebruik maar gewoon bool. Als je anders overstapt naar Java of iets anders werkt het dan weer niet. Gebruik de dingen waar ze voor gemaakt zijn ;).
Heb voldoende ervaring met andere talen om daar geen probleem mee te hebben hoor. In C mis ik bool(ean) ook wel, maar echt nodig is het natuurlijk niet. Is ook een kwestie van gewoonte I guess.

Is de eerste keer in járen dat ik nog eens een C programma schrijf, vandaar het geknoei I guess :-)

Kemblin

Legacy Member
tis ook beter om ipv exit() te doen een 'int& success' ofzo mee te geven met de pop en push functie. Zo maar exit() doen is niet meteen wat je verwacht van zo'n functies.

blackrabbit

Legacy Member
Daar ben ik nog niet helemaal uit.
Die dingen gaan draaien op de SPE cores van programma's voor de Cell en in dit geval is het wellicht beter dat executie helemaal stopt ipv af te hangen van de gebruiker van de queue.

Maar dat zijn details waar ik me later wel op ga storten ;)
Bedankt voor de opmerking. Ondersteunt C trouwens references? Dacht eigenlijk van niet.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan