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();
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;
}
This is an extract of a code, where I populate a list with the elements of an array.
#include <stdlib.h>
#include <stdio.h>
#include "../../lib/kernel/list.h"
#include "./listpop.h"
struct item {
struct list_elem elem;
int value;
int priority;
};
void populate(struct list * l, int * a, int n);
void populate(struct list * l, int * a, int n)
{
int i = 0;
while(i != n) {
struct item * newitem = malloc(sizeof(struct item));
newitem->value = a[i];
list_push_back(l,newitem);
i++;
}
}
void test_assignment_1()
{ struct list our_list;
list_init(&our_list);
populate(&our_list, ITEMARRAY, ITEMCOUNT);
}
Code inside list.h:
/* List element. */
struct list_elem
{
struct list_elem *prev; /* Previous list element. */
struct list_elem *next; /* Next list element. */
};
/* List. */
struct list
{
struct list_elem head; /* List head. */
struct list_elem tail; /* List tail. */
};
void list_init (struct list *);
Code inside list.c:
/* Initializes LIST as an empty list. */
void
list_init (struct list *list)
{
ASSERT (list != NULL);
list->head.prev = NULL;
list->head.next = &list->tail;
list->tail.prev = &list->head;
list->tail.next = NULL;
}
And finally, the code inside listpop.h:
#define ITEMCOUNT 10
int ITEMARRAY[ITEMCOUNT] = {3,1,4,2,7,6,9,5,8,3};
Here are the warnings I get:
warning: implicit declaration of function ‘malloc’
warning: incompatible implicit declaration of built-in function ‘malloc’
So far, all I've read about those warnings is to add stdlib.h, but as you can see from my code I've already done it, and the code still give me those warnings. I've restarted the code many times, so the error lays somewhere in the code.
Anyone knows what is not working here?
You might be compiling on a obsolete system with a non conforming compiler and/or C library. Try including <malloc.h> in addition to <stdlib.h> and always include the standard headers first.
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.
This is my first C program and I don't know why I get the error below.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
struct ListNode* next;
int content;
} ListNode;
int main() {
//puts("Hello UPC World"); /* prints Hello UPC World */
//ListNode* h = malloc(sizeof(ListNode));
gridinit(3, 5);
//int c = h->content;
//printf("%d",c);
return EXIT_SUCCESS;
}
ListNode* gridinit(int numcolumns, int numrows) {
ListNode* head = malloc(sizeof(ListNode));
head->content = 2;
head->next = NULL;
return head;
}
Why do I get an error saying
type conflict in func gridinit()
Define your function declaration at the top of your struct
ListNode* gridinit(int numcolumns, int numrows);
typedef struct {
struct ListNode* next;
int content;
} ListNode;
int main() {
//puts("Hello UPC World"); /* prints Hello UPC World */
//ListNode* h = malloc(sizeof(ListNode));
gridinit(3, 5);
//int c = h->content;
//printf("%d",c);
return EXIT_SUCCESS;
}
ListNode* gridinit(int numcolumns, int numrows) {
ListNode* head = malloc(sizeof(ListNode));
head->content = 2;
head->next = NULL;
return head;
}
That is because your function is defined after it is called. You can declare a prototype of the function just after your struct and before main as
ListNode* gridinit(int numcolumns, int numrows);
and you will be good for compile.
TL;DR answer - For all the functions which are used (called) before they are defined, you need to add a forward declaration for those functions before the caller function. In this case, as the definition of gridinit() is written after main() and main() uses gridinit() you have to add the forward declaration of gridinit() before main() and you'll be good to go.
To elaborate the case, in your main() function, you're calling gridinit(), but till that point, compiler has no idea about the prototype of the gridinit() function.
Due to backward compatibility, a feature called implicit declaration of a function assumes that a function, which has been used before it is defined or declared, accepts any number of parameters and returns an int.
Later, when you're actually defining the function, you're making the return type as ListNode*, which is creating the conflict here.
FWIW, as per the C99 standard (onwards), the (evil) feature of implicit function declaration has been officially removed but compilers still continue to support the same for legacy code. If you enable compiler warnings and compile with strict conformance, you should get warned (or even stopped) by your compiler, in case, a forward declaration is missing.
Add a forward declaration for gridinit() and everything works fine:
...
typedef struct {
struct ListNode* next;
int content;
} ListNode;
// Declare the gridinit function
ListNode* gridinit(int, int);
...
There should be a declaration or definition of gridinit before it is called in main (the compiler needs to know it exists).
Also, you should not ignore the return value of gridinit, which returns a pointer you have allocated memory for (ignoring it would therefore cause a memory leak), instead you should assign it to h without allocating memory in main (because you're doing that already in gridinit).
#include <stdio.h>
#include <stdlib.h>
typedef struct {
struct ListNode* next;
int content;
} ListNode;
ListNode* gridinit(int numcolumns, int numrows) {
int main() {
//puts("Hello UPC World"); /* prints Hello UPC World */
ListNode* h = gridinit(3, 5);
int c = h->content;
printf("%d",c);
return EXIT_SUCCESS;
}
ListNode* gridinit(int numcolumns, int numrows) {
ListNode* head = malloc(sizeof(ListNode));
head->content = 2;
head->next = NULL;
return head;
}
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.