C Queue questions (Exercise) - c

I just started my first lesson in queues for C, and I was given an exercise to create a queue, adding elements and deleting elements into the queue. However, I am having trouble with checking whether the queue is full or empty.
#include <stdio.h>
typedef struct FloatQueue
{
float data[100];
int rear;
int size;
int front;
} FloatQueue;
typedef enum {false, true} bool;
void initQ (FloatQueue * pq);
bool isFullQ (FloatQueue * pq);
bool isEmptyQ (FloatQueue * pq);
void addQ(FloatQueue * pq, float x);
float deleteQ ( FloatQueue * pq);
int sizeQ (FloatQueue * pq);
void initQ (FloatQueue * pq)
{
pq->size = 0;
pq->front = pq->rear = 0;
}
void main ()
{
FloatQueue q1;
initQ (&q1);
addQ (&q1, 99.9);
addQ (&q1, 888);
while (!isEmptyQ(&q1))
{
printf("%f", deleteQ (&q1));
}
}
int sizeQ (FloatQueue * pq)
{
return pq->size;
}
bool isFullQ (FloatQueue * pq)
{
return true;
}
bool isEmptyQ (FloatQueue * pq)
{
return false;
}
void addQ ( FloatQueue * pq, float x)
{
(pq->rear) ++;
(pq->data[pq->rear]) = x;
(pq->size) ++;
}
float deleteQ ( FloatQueue * pq )
{
(pq->front)++;
return;
}

The queue is full if size == 100 and empty if size == 0. Why is it difficult to check for that?
However, as it is implemented now, it holds that size == 0 if and only if front == rear. That means, you could remove the size from the FloatQueue completely and instead check if front - rear == 0 resp. 100.
BUT: You have to think about one thing: what happens if the rear end exceeds the size? Then you surely have to rearrange something. I leave it to you to find a good solution, which could might mean making use of size again after all (Hint: you don't necessarily have to move data around in the array).

bool isFullQ (FloatQueue * pq)
{
if(pq->size==100)
return true;
}
bool isEmptyQ (FloatQueue * pq)
{
if(pq->front==pq->rear)
return false;
}

Related

Making a generic ArrayLIst in C

I am trying to implement a java like arraylist in C and now I am trying to make it generic. I am new to C
and pointer arithmetic but I triedusing void* pointer for container, then element size(for size of data type), capacity and size. Currently in my add method I am getting an error saying (expression must have struct or union type in the add method inside of memcpy). As I understand memcpy, the first parameter is the destination where i want to put my input so i iterate from start of my container to elementSize*numElements ahead to reach the last index to append my input. Then the third parameter is the size of input. And is the resize function alright?
I am new to C and playing around for educational purposes and any help is appreciated.
Thank you
_____________________________________________________________________________________________
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
typedef struct ArrayList ArrayList;
typedef int bool;
#define false 0
#define true 1
struct ArrayList {
void *con;
int elementSize;
int numElements;
int conSize;
};
ArrayList *createArrayList();
void freeArrayList(ArrayList *);
void add(ArrayList *, void*);
#endif
___________________________________________________________________________________________________
#include<stdio.h>
#include<stdlib.h>
#include"Consts.h"
#include "ArrayList.h"
#define CAPACITY 5
ArrayList *createArrayList(int elementSize) {
ArrayList *arrayList = malloc(sizeof(ArrayList));
arrayList->elementSize = elementSize;
arrayList->conSize = CAPACITY;
arrayList->numElements = 0;
arrayList->con = malloc(sizeof(elementSize) * CAPACITY);
return arrayList;
}
void freeArrayList(ArrayList * arrayList) {
if (arrayList == NULL) {
return;
}else {
free(arrayList->con);
free(arrayList);
}
}
void add(ArrayList *list, void *input) {
if (list->numElements >= list->conSize) {
resize(list);
printf("resized\n");
}
memcpy(list->con + (list.numElements) * (list.elementSize), input, list->elementSize * list->numElements);
list->numElements++;
}
void resize(ArrayList *list) {
void *temp = realloc(list->con, (list->conSize + 100) * list->elementSize);
if (temp != NULL) {
list->conSize += 100;
list->con = temp;
}
}
It looks like you're pretty close, but there were some issues with your add function.
Since list is a pointer you need list->numElements not list.numElements and the same for list->elementSize. Also since you are only inserting one element, the third argument to memcpy should just be list->elementSize.
void add(ArrayList *list, void *input) {
if (list->numElements >= list->conSize) {
resize(list);
printf("resized\n");
}
memcpy((char*)list->con + list->numElements * list->elementSize, input, list->elementSize);
list->numElements++;
}
The resize function looks almost correct, except that if realloc fails it just returns. It should probably either error out or return a value indicating an error to the caller.

Implementing a generic arraylist in C [duplicate]

This question already has an answer here:
Making a generic ArrayLIst in C
(1 answer)
Closed 2 years ago.
I am trying to implement a java-like arraylist in C and now I am trying to make it generic. I am new to C and pointer arithmetic but I tried using void* pointer for container, then element size(for size of data type), capacity and size. I am trying to debug my code and it is giving a random value on the screen.
I cant seem to find what is wrong with my add method ? and how should I go about the printlist method as we are not sure about the data type. I think my printLIst is wrong.
I am new to C and playing around for educational purposes and any help is appreciated. Thank you
____________________________________________________________________
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
typedef struct ArrayList ArrayList;
typedef int bool;
#define false 0
#define true 1
struct ArrayList {
void *con;
int elementSize;
int numElements;
int conSize;
};
ArrayList *createArrayList(int );
int remove(ArrayList *, int);
void freeArrayList(ArrayList *);
int add(ArrayList *, void*);
void *getAtIndex(ArrayList *, int);
void printList(ArrayList *);
void resize(ArrayList *);
bool isEmpty(ArrayList*);
int getNumElements(ArrayList*);
int getConSize(ArrayList*);
#endif
_______________________________________________________________________
#include<stdio.h>
#include<stdlib.h>
#include"Consts.h"
#include<memory.h>
#include "ArrayList.h"
#define CAPACITY 5
#define EXTRA 100
ArrayList *createArrayList(int elementSize) {
ArrayList *arrayList = malloc(sizeof(ArrayList));
arrayList->elementSize = elementSize;
arrayList->conSize = CAPACITY;
arrayList->numElements = 0;
arrayList->con = malloc(elementSize * CAPACITY);
return arrayList;
}
void freeArrayList(ArrayList * arrayList) {
if (arrayList == NULL) {
return;
}else {
free(arrayList->con);
free(arrayList);
}
}
int add(ArrayList *list, void *input) {
if (list != NULL && input != NULL) {
if (list->numElements >= list->conSize) {
resize(list);
printf("resized\n");
}
list->con = input;
memcpy((char*)list->con + (list->numElements*list->elementSize), input, list->elementSize);
list->numElements++;
return 1;
}
return -1;
}
void resize(ArrayList *list) {
void *temp = realloc(list->con, (list->conSize + EXTRA) * list->elementSize);
if (temp != NULL) {
list->conSize += 100;
list->con = temp;
}
}
int remove(ArrayList * list, int i) {
if (list != NULL) {
//find index of value to remove
int elementSize = list->elementSize;
int lenToMove = elementSize * (list->numElements - (i + 1));
memmove((char *)list->con + i*elementSize, (i+1)*elementSize, lenToMove);
list->numElements--;
return 1;
}
return -1;
}
void printList(ArrayList *list) {
if (list != NULL) {
char *p = list->con;
for (int i = 0; i < list->numElements; i++) {
void* val = getAtIndex(list, i);
printf("%d \n", val);
}
}
}
void *getAtIndex(ArrayList *listptr, int index) {
return (char*)listptr->con + index * (listptr->elementSize);
}
int getNumElements(ArrayList * list) {
return list->numElements;
}
int getConSize(ArrayList * list) {
return list->conSize;
}
bool isEmpty(ArrayList * list) {
return list->numElements == 0;
}
___________________________________________________
#include<stdio.h>
#include<stdlib.h>
#include"ArrayList.h"
#include "Consts.h"
#pragma warning(disable : 4996)
int main() {
ArrayList * list = createArrayList(sizeof(int));
int x = 5;
add(list, &x);
printf("%d",(int *)getAtIndex(list, 0));
freeArrayList(list);
system("pause");
return 0;
}
Pay attention to the comments above. I know you're new to the site, but it's worth while getting to know how it works.
Anyway the problem is in this line of code:
printf("%d",(int *)getAtIndex(list, 0));
getAtIndex() returns a pointer so you need to dereference it to get the value. It should be:
printf("%d",*(int *)getAtIndex(list, 0));

Generic ArrayList in C

I have made a Java like ArrayList class in C for educational purposes however currently it is only good for integers. I want to make it Generic so it can take any type of data. How do I go about it. I read somewhere about creating a typedef void pointer. Any thoughts ?
........................................................................................................
Here is My code
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
typedef struct ArrayList ArrayList;
typedef int bool;
#define false 0
#define true 1
struct ArrayList {
int *con;
int numElements;
int conSize;
};
ArrayList *createArrayList();
void freeArrayList(ArrayList *);
void add(ArrayList *, int);
void printList(ArrayList *);
void resize(ArrayList *);
int remove(ArrayList *, int);
bool isEmpty(ArrayList*);
int getNumElements(ArrayList*);
int getConSize(ArrayList*);
#endif
_____________________________________
#include<stdio.h>
#include<stdlib.h>
#include"Consts.h"
#include "ArrayList.h"
#define CAPACITY 5
ArrayList *createArrayList() {
ArrayList *arrayList = malloc(sizeof(ArrayList));
arrayList->conSize = CAPACITY;
arrayList->numElements = 0;
arrayList->con = malloc(sizeof(int) * CAPACITY);
return arrayList;
}
void freeArrayList(ArrayList * arrayList) {
if (arrayList == NULL) {
return;
}else {
free(arrayList->con);
free(arrayList);
}
}
void add(ArrayList *arrayList, int input) {
//printf("Num elements in add method before adding %d \n", arrayList->numElements);
if (arrayList->numElements >= arrayList->conSize) {
resize(arrayList);
printf("resized\n");
}
int size = arrayList->numElements;
//add element to the last
arrayList->con[size] = input;
arrayList->numElements = arrayList->numElements + 1
}
void resize(ArrayList *arrayList) {
int num = arrayList->numElements;
int oldSize = arrayList->conSize;
int newSize = oldSize + 50;
int *temp = realloc(arrayList->con, sizeof(type) * newSize);
if (temp != NULL) {
arrayList->con = temp;
arrayList->conSize = newSize;
}
}
int remove(ArrayList * arrayList, int val) {
int i = 0;
while (arrayList->con[i] != val) {
i++;
}
//remove this index
if (i == arrayList->conSize) {
return -1;
}
else {
int removedVal = arrayList->con[i]; int j;
for (j = i; j < arrayList->numElements ; j++) {
arrayList->con[j] = arrayList->con[j + 1];
}
arrayList->con[j + 1] = NULL;
arrayList->numElements = arrayList->numElements - 1;
return removedVal;
}
}
If you want the array list be able to store any type of data, you need to
1) make con a void pointer. void *con;
2) store additional metadata in the struct about the memory alignment of the type
3) add one more parameter to the constructor of array list, which is the additional metadata mentioned in 2)
4) when allocating memory, use the stored metadata instead of sizeof(whatever), like temp=malloc(stored_metadata_about_type*50);
Also notice that it is not usually a good idea to hardcode 50, and better declare it as a constant like buffer_size.

Generic Struct in C

I have a problem in return values int/double using void*.
For example:
#include "stdio.h"
#include "stdlib.h"
typedef struct list {
void *info;
struct list *prox;
} List;
typedef struct queue {
List* begin;
List* end;
} Queue;
Queue* create_queue (void) {
Queue* f = (Queue*) malloc(sizeof(Queue));
f->begin = f->end = NULL;
return f;
}
Queue* insert_queue_end (List* end, void* v) {
List* p = (List*) malloc(sizeof(List));
p->info=v;
p->prox=NULL;
if(end!=NULL) {
end->prox=p;
}
return p;
}
double queue_empty_double(Queue* f) {
return (f->begin==NULL);
}
double queue_remove_double(Queue* f) {
List* t;
double v;
if(queue_empty_double(f)) {
exit(1);
}
t=f->begin;
v=*((double*)(t->info));
f->begin=t->prox;
if (f->begin==NULL) {
f->end = NULL;
}
free(t);
printf("%.3lf\n",v);
}
void insert_queue(Queue* f, void* v) {
f->end = insert_queue_end(f->end,v);
if(f->begin==NULL) {
f->begin=f->end;
}
}
void print_queue_double(Queue* f) {
List* i;
for(i=f->begin;i!=NULL;i=i->prox)
printf("%.3lf\n",*((double*)i->info));
}
int main () {
Queue* f;
f = create_queue();
char ent1[100];
double n1;
scanf("%s",ent1);
while(ent1[0]!='X')
{
if(ent1[0]=='E') {
scanf("%lf",&n1);
insert_queue(f,&n1);
scanf("%s",ent1);
}
else if (ent1[0]=='D') {
queue_remove_double(f);
scanf("%s",ent1);
}
}
}
But the function doesn't work with double values, just with int.
Another new code, now the code can print double but in the function queue_remove_double there's a problem, she should remove the first element from a queue and print the first element. I believe this problem is from the generic struct because the function remove the first and print him in a normal struct.
Input:
E 1.2
E 2.1
D
X
Output:
1.200
The wrong output:
2.100
It works on codeblocks ide. Specify the type of *info to know how to cast the pointer.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef enum DataTypes {
INTEGER,
FLOAT,
DOUBLE,
CHAR
} DataType;
typedef struct list {
void *info;
struct list *next;
DataType type;
} List;
List* create_list(void *firstInfo, DataType firstType)
{
List *f=(List*)malloc(sizeof(List));
f->info=firstInfo;
f->type=firstType;
f->next=NULL;
return f;
}
List* insertion(List *end, void *data, DataType type)
{
List *p=(List*)malloc(sizeof(List));
p->info=data;
p->next=NULL;
p->type=type;
if(end != NULL)
{
end->next=p;
}
return p;
}
void showTheList(List **theBase)
{
List *run=*theBase;
while(run != NULL)
{
switch(run->type)
{
case INTEGER:
printf("Showing the value: %d \n",*((int*)run->info));
break;
case FLOAT:
printf("Showing the value: %f \n",*((float*)run->info));
break;
case DOUBLE:
printf("Showing the value: %lf \n",*((double*)run->info));
break;
default:
printf("Showing the value: %c \n",*((char*)run->info));
}
run=run->next;
}
}
List* getEnd(List **theBase)
{
List *run=*theBase;
while(run->next != NULL)
run=run->next;
return run;
}
void clearList(List **theBase)
{
List *run=(*theBase)->next;
free(*theBase);
while(run != NULL)
{
*theBase=run;
run=run->next;
free(*theBase);
}
*theBase=NULL;
}
int main(void)
{
List *theList=NULL;
int valA=10;
float valB=1.25;
double valC=23.45;
char valD='C';
theList=create_list(&valA,INTEGER);
insertion(getEnd(&theList),&valB,FLOAT);
insertion(getEnd(&theList),&valC,DOUBLE);
insertion(getEnd(&theList),&valD,CHAR);
showTheList(&theList);
clearList(&theList);
if(theList == NULL)
printf("Ok, all operations realized !");
return 0;
}
Try use a cast with the pointer. You need to know the type of the pointer.
void print_queue_double(Queue* f)
{
List* i;
for(i=f->begin;i!=NULL;i=i->prox)
printf("%.3lf\n",*((double*)i->info));
}
Your problem is pointer. If you use n1, then void * always contain the last n1 value because points to n1. Then when you free the list (queue_remove_double), always is show the value of n1 (the most recent)...
Some Solutions:
(1) Array - showed below - is limited....
(2)New double value with the copy of variable (malloc double) - "ilimited" (limit of your memory...)
In the new double case:
List* insert_queue_end (List* end, void* v) {
List* p = (List*) malloc(sizeof(List));
double *data=(double*)malloc(sizeof(double)); /*New double new address*/
*data=*((double*)v); /*Copy the VALUE and not the address to new double in new and fixed address*/
/*void* points to a new double with a new address in memory */
p->info=data;
p->prox=NULL;
if(end!=NULL) {
end->prox=p;
}
return p;
}
Don't forget to free the memory from the new double in the remove function !
SOME SOLUTIONS:
SOLUTION 1 - The array of doubles:
#include "stdio.h"
#include "stdlib.h"
typedef struct list {
void *info;
struct list *prox;
} List;
typedef struct queue {
List* begin;
List* end;
} Queue;
Queue* create_queue (void) {
Queue* f = (Queue*) malloc(sizeof(Queue));
f->begin = f->end = NULL;
return f;
}
/*Yes the type of return is List* and not Queue* - check your code */
List* insert_queue_end (List* end, void* v) {
List* p = (List*) malloc(sizeof(List));
///If you want create a new double this is the local - don't use the same address in v !
p->info=v;
p->prox=NULL;
if(end!=NULL) {
end->prox=p;
}
return p;
}
double queue_empty_double(Queue* f) {
return (f->begin==NULL);
}
double queue_remove_double(Queue* f) {
List* t;
double v;
double isRemoved=0;
if(queue_empty_double(f)) {
exit(1);
}
t=f->begin;
v=*((double*)(t->info));
f->begin=t->prox;
if (f->begin==NULL) {
f->end = NULL;
}
free(t);
printf("%.3lf\n",v);
}
void insert_queue(Queue* f, void* v) {
f->end = insert_queue_end(f->end,v);
if( f->begin==NULL) {
f->begin=f->end;
}
}
void print_queue_double(Queue* f) {
List* i;
for(i=f->begin;i!=NULL;i=i->prox)
printf("%.3lf\n",*((double*)i->info));
}
int main () {
Queue* f;
f = create_queue();
char ent1[100];
///One Double Allocated - only one address in memory !!!
///double n1;
double listOfDoubles[20]; ///All doubles allocated and one per one have a address in memory !!!
int countDoubles=0;
scanf("%s",ent1);
while(ent1[0]!='X' && countDoubles < 20)
{
if(ent1[0]=='E') {
///IN YOUR CODE:
///Fill the same one double...
///scanf("%lf",&n1);
///Testing new code
scanf("%lf",&listOfDoubles[countDoubles]); ///a new double with your address
///IN YOUR CODE:
///The same address of one variable. The same result.
///Remember void * is a pointer and use the address of n1, and then, print the most recent &n1 content...
///insert_queue(f,&n1);
///A new double in a new address, the content is not equal
insert_queue(f,&listOfDoubles[countDoubles]);
countDoubles++;
}
else if (ent1[0]=='D') {
///free the address and decrement the index of array to reuse a double
queue_remove_double(f);
countDoubles--;
}
else
{
///Print the list - and see the result "debug"
print_queue_double(f);
}
scanf("%s",ent1);
}
free(f);
}
SOME SOLUTIONS:
SOLUTION 2 - A new double with the copy of value
#include "stdio.h"
#include "stdlib.h"
typedef struct list {
void *info;
struct list *prox;
} List;
typedef struct queue {
List* begin;
List* end;
} Queue;
Queue* create_queue (void) {
Queue* f = (Queue*) malloc(sizeof(Queue));
f->begin = f->end = NULL;
return f;
}
/*Yes the type of return is List* and not Queue* check your code */
List* insert_queue_end (List* end, void* v) {
List* p = (List*) malloc(sizeof(List));
double *data=(double*)malloc(sizeof(double)); /*New double new address*/
*data=*((double*)v); /*Copy the VALUE and not the address to new double in new and fixed address*/
/*void* points to a new double with a new address in memory */
p->info=data;
p->prox=NULL;
if(end!=NULL) {
end->prox=p;
}
return p;
}
double queue_empty_double(Queue* f) {
return (f->begin==NULL);
}
double queue_remove_double(Queue* f) {
List* t;
double v;
double isRemoved=0;
if(queue_empty_double(f)) {
exit(1);
}
t=f->begin;
v=*((double*)(t->info));
f->begin=t->prox;
if (f->begin==NULL) {
f->end = NULL;
}
free(t->info); ///free the double
free(t);
printf("%.3lf\n",v);
}
void insert_queue(Queue* f, void* v) {
f->end = insert_queue_end(f->end,v);
if( f->begin==NULL) {
f->begin=f->end;
}
}
void print_queue_double(Queue* f) {
List* i;
for(i=f->begin;i!=NULL;i=i->prox)
printf("%.3lf\n",*((double*)i->info));
}
int main () {
Queue* f;
f = create_queue();
char ent1[100];
double n1;
int countDoubles=0;
scanf("%s",ent1);
while(ent1[0]!='X' && countDoubles < 20)
{
if(ent1[0]=='E') {
scanf("%lf",&n1);
insert_queue(f,&n1);
}
else if (ent1[0]=='D') {
queue_remove_double(f);
}
else
{
///Print the list - and see the result "debug"
print_queue_double(f);
}
scanf("%s",ent1);
}
free(f);
}

Pointers to structures

typedef struct queue {
int q[max];
int qhead;
int qrear;
} queue;
void init_queue(queue *QUEUE)
{
QUEUE.qhead = 0;
QUEUE.qrear = -1;
}
void enqueue(queue *QUEUE,int data)
{
QUEUE.qrear++;
QUEUE.q[QUEUE.qrear] = data;
}
int process_queue(queue *QUEUE)
{
if(QUEUE.qhead > QUEUE.qrear)
return -1;
else
return QUEUE.q[QUEUE.qhead++];
}
I am implementing queues using arrays just to keep it simple. Wats the error with the above code?
First of all, the . operator is used to access members of a struct. You need -> to access members of a pointer to a struct:
void init_queue(queue *QUEUE)
{
QUEUE->qhead = 0;
QUEUE->qrear = -1;
}
Just as a tid-bit, a->b is equivalent to (*a).b - that is, first dereferencing the pointer a, and then accessing a member of that struct.
Besides the compilation error from using . instead of ->, you also have potential buffer overflow in enqueue; you'll overflow your buffer after max calls. You have a couple of choice depending on what you want.
1) You can turn this into a circular queue:
void enqueue(queue *QUEUE,int data)
{
QUEUE->qrear = (QUEUE->qrear + 1) % max;
QUEUE->q[QUEUE->qrear] = data;
}
2) You can stop adding once you hit max:
void enqueue(queue *QUEUE,int data)
{
if (QUEUE->qrear < (max - 1))
{
QUEUE->qrear++;
QUEUE->q[QUEUE->qrear] = data;
}
}
You should use -> instead of .:
Accessing structs' values using pointers is done using QUEUE-> or (*QUEUE). and not QUEUE.. You first need to dereference the pointer and only then access the value.
typedef struct queue {
int q[max];
int qhead;
int qrear;
} queue;
void init_queue(queue *QUEUE)
{
QUEUE->qhead = 0;
QUEUE->qrear = -1;
}
void enqueue(queue *QUEUE,int data)
{
QUEUE->qrear++;
QUEUE->q[QUEUE->qrear] = data;
}
int process_queue(queue *QUEUE)
{
if(QUEUE->qhead > QUEUE->qrear)
return -1;
else
return QUEUE->q[QUEUE->qhead++];
}

Resources