I am new to C and for my first project I need to implement an array based queue.
I want my queue to be able to hold any kind of object so I created a QueueElement structure to hold a void pointer to an object of any type. I think all is working except I am unable to read the 'position' and 'value' fields from my QueueElement struct. I get the following error when I try to compile.
Error:
Runnable.c: In function `main':
Runnable.c:10: error: dereferencing pointer to incomplete type
Runnable.c:11: error: dereferencing pointer to incomplete type
I'm pretty sure I'm just not casting properly. Any help is appreciated.
Thanks again,
Pooch
Runnable.c
#include <stdio.h>
#include "Queue.h"
int main(void) {
int i = 9;
Queue q = CreateQueue();
QueueElement e = CreateQueueElement(&i);
Enqueue(q, e);
QueueElement f = Dequeue(q);
/* PROBLEM IS HERE */
printf("position: %d", f->position);
printf("value: %d", (int *)(f->value));
DestroyQueue(q);
return 0;
}
Queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include "QueueElement.h"
typedef struct QueueStruct *Queue;
Queue CreateQueue(void);
void DestroyQueue(Queue q);
void Enqueue(Queue q, QueueElement e);
QueueElement Dequeue(Queue q);
#endif
Queue.c
#include "QueueElement.h"
#include "Queue.h"
#define QUEUE_SIZE 10
struct QueueStruct {
QueueElement contents[QUEUE_SIZE];
int size;
};
Queue CreateQueue(void) {
Queue q = malloc(sizeof(struct QueueStruct));
q->size = 0;
return q;
}
void DestroyQueue(Queue q) {
int i;
for(i = 0; i < q->size; i++) {
free(q->contents[i]);
}
free(q);
}
void Enqueue(Queue q, QueueElement e) {
if (q->size < QUEUE_SIZE) {
q->contents[q->size++] = e;
}
}
QueueElement Dequeue(Queue q) {
if (q->size > 0) {
return q->contents[--q->size];
}
return;
}
QueueElement.h
#ifndef QUEUE_ELEMENT_H
#define QUEUE_ELEMENT_H
typedef struct QueueElementStruct *QueueElement;
QueueElement CreateQueueElement(void *v);
void DestroyQueueElement(QueueElement e);
int GetPosition(QueueElement e);
#endif
QueueElement.c
#include <stdio.h>
#include "QueueElement.h"
struct QueueElementStruct {
int position;
void *value;
};
QueueElement CreateQueueElement(void *v) {
QueueElement e = malloc(sizeof(struct QueueElementStruct));
e->position = 0;
e->value = v;
return e;
}
void DestroyQueueElement(QueueElement e) {
free(e);
}
int GetPosition(QueueElement e) {
return e->position;
}
The definition of QueueElementStruct has to be visible in Runnable.c to be able to access fields of it. You can put QueueElementStruct into a header that you can include in Runnable.c and QueueElement.c. Alternatively, you can use your GetPosition function and add a GetValue function and use those from Runnable.c instead of direct field access.
You have to cast the void * back to point at the "real" type before you can dereference it. e.g., if you start with an int, you can take its address, and put it in the queue. To look at the int, you'll have to cast it back to int *. Keeping track of the real type can be (usually is) non-trivial (e.g., creating an enumeration of all types you want to be able to put in the collection and associating one of those with each item in the collection).
There's a reason that C++ (for one example) opts for only putting one type of object into any given collection.
Related
I'm new to C and I'm trying to code a queue problem. At the moment, I'm coding something that will check if the queue is empty. This is what I have so far:
For Queue.h (this was provided by our instructor)
#include <stdio.h>
#include <stdlib.h>
struct queueNode {
char data;
struct queueNode *nextPtr;
};
typedef struct queueNode QueueNode;
typedef QueueNode* QueueNodePtr;
typedef struct Queue {
QueueNodePtr head;
QueueNodePtr tail;
} Queue;
void instructions();
int isEmpty(Queue);
void enqueue(Queue*, char);
char dequeue(Queue*);
void printQueue(Queue);
void freeQueue(Queue*);
For Queue.c
#include <stdio.h>
#include <stdlib.h>
#include "Queue.h"
int isEmpty(struct Queue queue)
{
if (Queue == NULL)
{
return 1;
}
}
The problem is in line 8 of Queue.c, the compiler says "error: expected expression before 'Queue'" How will I resolve this?
Edit: I tried to use queue == NULL instead of Queue == NULL and the compiler said: error: invalid operands to binary == (have 'struct Queue' and 'void*').
Thank you very much!
To begin with, use a consistent way of passing your queue around. Note the differences in the interfaces:
int isEmpty(Queue); //<-- by value
void enqueue(Queue*, char); //<-- by reference
char dequeue(Queue*); //<-- by reference
void printQueue(Queue); //<-- by value
void freeQueue(Queue*); //<-- by reference
Some of these are passing a Queue structure by value, and others by reference (pointer). It's likely that you want all your functions to operate on a pointer, i.e. Queue*.
Next, you should have some kind of operation that initializes the queue. You have freeQueue already, which does the inverse. So you probably want something like initQueue:
void initQueue(Queue* q) {
q->head = NULL;
q->tail = NULL;
}
Now, on to the actual question... As I've already suggested, you should change isEmpty (and printQueue) to accept a pointer to the queue. And then you use whatever logic should indicate the queue is empty. Since I've asserted above that on initialization, the head pointer should probably be NULL, then that would be an appropriate "empty" test as well:
int isEmpty(Queue* q) {
return q->head == NULL;
}
And finally, since you're likely to ask how to actually use this:
int main(void)
{
Queue q;
initQueue(&q);
printf("Queue empty: %d\n", isEmpty(&q));
enqueue(&q, 'X');
printf("Queue empty: %d\n", isEmpty(&q));
enqueue(&q, 'Y');
enqueue(&q, 'Z');
printQueue(&q);
printf("Removed %c\n", dequeue(&q));
printQueue(&q);
freeQueue(&q);
return 0;
}
Pretty new to C here. I'm using sys/queue.h to make a simple queue. I've searched quite a bit on SO and Google and cannot find a solution to this particular question.
This works fine:
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
TAILQ_HEAD(, q_item) head;
typedef struct q_item {
int value;
TAILQ_ENTRY(q_item) entries;
} q_item;
void enqueue(int n) {
// enqueue the node with value n
q_item *item;
item = malloc(sizeof(q_item));
item->value = n;
printf("queued %d\n", item->value);
TAILQ_INSERT_TAIL(&head, item, entries);
}
void dequeue() {
q_item *returned_item;
returned_item = TAILQ_FIRST(&head);
printf("dequeued %d\n", returned_item->value);
TAILQ_REMOVE(&head, returned_item, entries);
free(returned_item);
}
int main() {
TAILQ_INIT(&head);
enqueue(1);
enqueue(2);
enqueue(3);
dequeue();
return 0;
}
I know in general global variables should be avoided. Though I also know TAILQ_HEAD() is a macro, so maybe that changes how I should think about this. Anyway, this doesn't compile:
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
typedef struct q_item {
int value;
TAILQ_ENTRY(q_item) entries;
} q_item;
void enqueue(int n, TAILQ_HEAD(, q_item) * head) {
// enqueue the node with value n
q_item *item;
item = malloc(sizeof(q_item));
item->value = n;
printf("queued %d\n", item->value);
TAILQ_INSERT_TAIL(head, item, entries);
}
void dequeue(TAILQ_HEAD(, q_item) * head) {
q_item *returned_item;
returned_item = TAILQ_FIRST(head);
printf("dequeued %d\n", returned_item->value);
TAILQ_REMOVE(head, returned_item, entries);
free(returned_item);
}
int main() {
TAILQ_HEAD(, q_item) head; // <-- I've moved TAILQ_HEAD into main()
TAILQ_INIT(&head);
enqueue(1, &head);
enqueue(2, &head);
enqueue(3, &head);
dequeue(&head);
return 0;
}
When I try to compile the latter I get the following errors. They are unhelpful since I cannot tell the difference between ‘struct <anonymous> *’ and ‘struct <anonymous> *’.
test_tailq_noglobal.c:32:13: warning: passing argument 2 of ‘enqueue’ from incompatible pointer type [-Wincompatible-pointer-types]
enqueue(1, &head);
^
test_tailq_noglobal.c:10:6: note: expected ‘struct <anonymous> *’ but argument is of type ‘struct <anonymous> *’
void enqueue(int n, TAILQ_HEAD(, q_item) * head) {
^~~~~~~
I know the man page for TAILQ_HEAD shows that you can define the following:
TAILQ_HEAD(tailhead, entry) head;
struct tailhead *headp; /* Tail queue head. */
But I am not sure what to do with this struct tailhead *headp. I have tried passing it as a pointer in place of &head as follows, but this does not seem to work either:
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
typedef struct q_item {
int value;
TAILQ_ENTRY(q_item) entries;
} q_item;
void enqueue(int n, struct headname *headp) {
// enqueue the node with value n
q_item *item;
item = malloc(sizeof(q_item));
item->value = n;
printf("queued %d\n", item->value);
TAILQ_INSERT_TAIL(headp, item, entries);
}
void dequeue(struct headname *headp) {
q_item *returned_item;
returned_item = TAILQ_FIRST(headp);
printf("dequeued %d\n", returned_item->value);
TAILQ_REMOVE(headp, returned_item, entries);
free(returned_item);
}
int main() {
TAILQ_HEAD(headname, q_item) head;
struct headname *headp;
TAILQ_INIT(headp);
enqueue(1, headp);
enqueue(2, headp);
enqueue(3, headp);
dequeue(headp);
return 0;
}
Errors:
test_tailq_headp.c: In function ‘dequeue’:
test_tailq_headp.c:21:18: error: dereferencing pointer to incomplete type ‘struct headname’
returned_item = TAILQ_FIRST(headp);
^
test_tailq_headp.c: In function ‘main’:
test_tailq_headp.c:33:13: warning: passing argument 2 of ‘enqueue’ from incompatible pointer type [-Wincompatible-pointer-types]
enqueue(1, headp);
^~~~~
test_tailq_headp.c:10:6: note: expected ‘struct headname *’ but argument is of type ‘struct headname *’
void enqueue(int n, struct headname *headp) {
^~~~~~~
Can someone tell me what I'm doing wrong, either in my code or in the way I'm thinking about this problem? Thanks.
I never work with this queue but one way I found is add TAILQ_HEAD() inside q_item itself. Its help to avoid global usage of head.
#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>
typedef struct q_item {
int value;
TAILQ_ENTRY(q_item) entries;
TAILQ_HEAD(, q_item) head;
} q_item;
void enqueue(int n, q_item *q) {
// enqueue the node with value n
q_item *item;
item = malloc(sizeof(q_item));
item->value = n;
printf("queued %d\n", item->value);
TAILQ_INSERT_TAIL(&q->head, item, entries);
}
void dequeue(q_item *q) {
q_item *returned_item;
returned_item = TAILQ_FIRST(&q->head);
printf("dequeued %d\n", returned_item->value);
TAILQ_REMOVE(&q->head, returned_item, entries);
free(returned_item);
}
int main() {
q_item q;
TAILQ_INIT(&q.head);
enqueue(1, &q);
enqueue(2, &q);
enqueue(3, &q);
dequeue(&q);
dequeue(&q);
return 0;
}
Also it may be useful to look how this macros expand, just compile with gcc using -E option, and you will see that for example TAILQ_HEAD(, qitem) head expand to
struct {
struct q_item *tqh_first;
struct q_item **tqh_last;
} head;
Also you can find it in <sys/queue.h> header
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
that's why your try with void enqueue(int n, TAILQ_HEAD(, q_item) * head) didn't work because preprocessor makes simple substituion.
I'm creating a simple queue with simple operations. I use an ADT item to contain the informations, in this case only an int value. Then I use this item in the nodes. These are the files:
item.h
typedef struct c_item *item;
item newItem(int x);
int eq(item x, item y);
item input_item();
void output_item(item x);
char* getx(item x);
item cloneItem(item x);
item.c
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include "item.h"
struct c_item {
int x;
};
item newItem(int x){
item n = malloc(sizeof(struct c_item));
n->x=x;
return n;
}
int eq(item x, item y){
if (x->x==y->x)
return 1;
return 0;
}
item input_item(){
item n;
printf("Inserisci x: ");
scanf("%d", n->x);
return n;
}
void output_item(item x){
printf("x: %d\n", x->x);
}
item cloneItem(item x){
item n ;
n->x=x->x;
return n;
}
queue.h
#include "item.h"
typedef struct queue *queuePtr;
queuePtr newQueue();
int emptyQueue(queuePtr q);
item dequeue(queuePtr q);
int enqueue(item val, queuePtr q);
void checkPointer(queuePtr p);
queue.c
#include <stdlib.h>
#include <stdio.h>
#include "item.h"
#include "queue.h"
typedef struct node* nodePtr;
struct node{
item val;
nodePtr next;
};
struct queue{
nodePtr head, tail;
int dim;
};
queuePtr newQueue(){
queuePtr q = malloc(sizeof(struct queue));
if (q==NULL)
return NULL;
q->dim=0;
q->head=NULL;
q->tail=NULL;
return q;
}
int emptyQueue(queuePtr q){
if (q==NULL)
return -1;
return q->dim==0;
}
// aggiunge un nodo alla coda
int enqueue(item val, queuePtr q){
if (q==NULL)
return -1;
nodePtr nuovo = malloc(sizeof(struct node));
if (nuovo==NULL)
return 0;
nuovo->val=val;
nuovo->next=NULL;
if(q->head==NULL) {
q->head = nuovo;
}
else {
q->tail->next = nuovo;
}
q->tail=nuovo;
(q->dim)++;
return 1;
}
item dequeue(queuePtr q){
if (q==NULL)
return (item)NULL;
if (q->dim==0)
return (item)NULL;
item res = q->head->val;
struct node* tmt = q->head;
q->head=q->head->next;
free(tmt);
if (q->head==NULL)
q->tail=NULL;
(q->dim)--;
return res;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
int main() {
queuePtr q = newQueue();
item val = newItem(1);
item val2 = newItem(2);
enqueue(val, q);
enqueue(val2, q);
item ret = dequeue(q);
printf("x: %d\n", ret->x);
return 0;
}
But on compiling I have this error message:
/LibreriaQueque/main.c:17:26: error: dereferencing pointer to incomplete type ‘struct c_item’
printf("x: %d\n", ret->x);
The IDE gives me the same alert message in the queue.c but it works. I think that the problem is the item structure that is declared in the item.c and so it can't be seen in the main file and in the queue.c file. I can't move the structure declaration from item.c. How can I solve this problem?
You're doing an often sensible thing here: The struct is only defined in your implementation of the queue. This makes sure no other module can ever depend on the inner workings of your struct, so you can change it without touching any external code.
But in your main(), you try to do what you explicitly forbid: accessing the content of your struct. It's impossible because the compiler doesn't know the content when compiling your main file.
You have two options:
Move the definition of the struct to your header file, therefore making it public.
(IMHO preferred): Provide an accessor method like
int value(const item it)
{
return it->x;
}
and call that from your main code to get the value.
Side notes:
What is memory.h? I guess you don't need it
Better don't hide pointers behind typedef. You could to typedef struct c_item item; instead and use the explicit asterisk anywhere. It's easier to understand the code, C programmers expect pointers to be explicit.
You are close to using what's known as "opaque type" or "opaque pointers", which is a design pattern used for private encapsulation of ADTs. It works by declaring an incomplete struct in the header file, which the caller has access to. But only defining the struct in the c file, which the caller does not have access to. Therefore the caller can't know what's inside the struct, which is a good thing.
The downside of this method is that the caller can never create an instance of the object - only pointers to it. (It works pretty much like an abstract base class in C++.) So the caller has to rely on your "constructor" and "destructor" to do this.
Misc good practice:
There's a rule of thumb in C saying that you should never hide pointers behind typedefs, because doing so tends to confuse the reader.
When writing an ADT, it is good practice to prefix all functions, types and macros in the same way. In this case, I would name all functions queue_. Ideally you should have a coding standard stating how to prefix/postfix functions, macros and types belonging to an ADT.
You should never use empty parentheis for functions in C, because that's obsolete style and means "take any parameter". (Unlike in C++ where it means take no parameter.)
Use const correctness for the ADT function parameters.
Now to make your ADT opaque (which is good design), you need to do like this:
queue.h
typedef struct queue queue; // typedef of incomplete type
queue* queue_new (void);
void queue_delete (queue* q);
int queue_empty (const queue* q);
// and so on
queue.c
struct queue {
...
};
main.c
queue* q = queue_new();
I'm having problem implementing queue in c using linked list. I've been reading so many other questions on it here in stackoverflow and in other websites as well, but I still don't know how to fix this issue of my code yet. Anyone, please, help me?
here, it is my code in c:
#include <stdio.h>
#include <stdlib.h>
struct elem{
int n;
elem *prox;
};
struct fila{
elem *inicio, *fim;
}nop;
void iniciar(fila *d){
d->inicio = (elem*) malloc(sizeof(elem));
d->fim = (elem*) malloc(sizeof(elem));
d->inicio->prox = d->fim;
d->fim->prox = NULL;
}
void inserir(fila *d, int x){
elem *novo = (elem*) malloc(sizeof(elem));
novo->n = x;
novo->fim->prox = NULL;
if(d->inicio->prox == NULL)
d->inicio->prox = novo;
else{
d->fim->prox = novo;
d->fim = novo;
}
}
void deletar(fila *d){
if(d->inicio->prox = NULL)
printf("Lista vazia")
else{
elem *apg;
apg = d->inicio->prox;
d->inicio->prox = apg->prox;
printf("%d", d->n);
free(apg);
}
}
int main(){
int x;
iniciar(&nop);
scanf("%d", &x);
inserir(&nop, x);
deletar(&nop);
return 0;
}
So, the question is pretty vague, however I do see one problme in this, which is that you're getting tags and typedef's confused. For example:
void inserir(fila *d, int x)
should actually be defined as
void inserir(struct fila *d, int x)
because you defined fila as a tag. The other alternative is to declare the structure fila with the typedef keyword (liek the below)
typedef struct elem{
int n;
struct elem *prox;
} element;
typename struct {
element *inicio, *fim;
}fila nop;
Most of the errors in this code are because you use elem and fila as type names. Those types however are not defined. When referencing a struct type, you need to prefix it with the struct keyword.
You can get around this by adding a typedef for each one so that they may be referenced by just the type name:
typedef struct elem elem;
typedef struct fila fila;
Put these lines at the top of your source file after the includes. That will address most of the compilation issues. The rest you should be able to figure out yourself.
I have a struct defined as:
typedef struct {
int type;
void* info;
} Data;
and then i have several other structs that i want to assign to the void* using the following function:
Data* insert_data(int t, void* s)
{
Data * d = (Data*)malloc(sizeof(Data));
d->type = t;
d->info = s;
return d;
}
struct {
...
} Struct#;
then i just call
insert_data(1, variable_of_type_Struct#);
When i compile this it gives a warning
warning: assignment from incompatible pointer type
i tried to cast the variable in the insert to (void*) but didn't work
insert_data(1, (void *) variable_of_type_Struct#);
How can i get rid of this warning?
Thanks
Pass in the address of the struct, not a copy of it (i.e. not passed by value):
insert_data(1, &variable_of_type_Struct);
Pass a pointer to the struct object:
struct your_struct_type bla;
insert_data(1, &bla);
Hope this program helps!
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int type;
void* info;
} Data;
typedef struct {
int i;
char a;
float f;
double d;
}info;
Data* insert_data(int t, void* s)
{
Data * d = (Data*)malloc(sizeof(Data));
d->type = t;
d->info = s;
return d;
}
int main()
{
info in;
Data * d;
d = insert_data(10, &in);
return 0;
}
I'm not quite sure what this was:
struct {
...
} Struct#;
So, I cleaned up your program a little bit and got no warnings, after putting the address of the struct into the call, insert_data(1, &variable_of_type_Struct);
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int type;
void* info;
} Data;
Data* insert_data(int t, void* s);
Data variable_of_type_Struct;
Data* insert_data(int t, void* s)
{
Data * d = (Data*)malloc(sizeof(Data));
d->type = t;
d->info = s;
return d;
}
void test()
{
insert_data(1, &variable_of_type_Struct);
}
insert_data waits for a void*, you put a Data.
insert_data(1, &variable_of_type_Struct#);
It miss a level of indirection.