1

I've been trying to find answers from previous posts of my same issue but it's not working out. Below is only a few of the links I've checked:

Code:

#include "listADT.h"
#include "client.h"
#include <stdlib.h>
#include <stdio.h>


struct node {
   ClientInfo *data; // added pointer here
   struct node * next;
};

struct list_type {
   struct node * front;
   int size;
};

ListType create() {

    ListType listptr = malloc(sizeof(struct list_type));

    if (listptr != NULL) {
        listptr->front = NULL;
        listptr->size = 0;
    }
    return listptr;
}



void push(ListType listptr, ClientInfo item) {  <--- error here

   struct node *temp = malloc(sizeof(struct node));

   if (temp != NULL) {
       temp->data = item;
       temp->next = listptr->front;
       listptr->front = temp;
       (listptr->size)++;
   }
}

int is_empty(ListType l) {
    return l->size == 0;
}

int size_is(ListType l) {
    return l->size;
}

void make_empty(ListType listptr) {

    struct node* current = listptr->front;

    while (current->next != NULL) {
        destroy(listptr);
        current = current->next;        
    }

    (listptr->size)--;

}

void destroy(ListType listptr) {
    struct node *temp = malloc(sizeof(struct node));
    temp = listptr->front;
    listptr->front = listptr->front->next;

    free(temp); 
    (listptr->size)--;
}

void delete(ListType listptr, ClientInfo item) { <--- error here
    struct node* current = listptr->front;
    struct node *temp = malloc(sizeof(struct node));

    while (current-> data != item) {
        temp = current;
        current = current->next;        
    }

    temp->next = current->next;
    (listptr->size)--;
}

int is_full(ListType l) {

}

Here is what the struct ClientInfo contains in another c file:

typedef struct ClientInfo {
    char id[5];
    char name[30];
    char email[30];
    char phoneNum[15];
} ClientInfo;

And here is the error I'm getting:

listADT.c:41:40: error: parameter 2 (‘item’) has incomplete type
void push(ListType listptr, ClientInfo item) {
                                    ^
listADT.c:83:42: error: parameter 2 (‘item’) has incomplete type
void delete(ListType listptr, ClientInfo item) {

I'm absolutely lost at this point on how to fix it. Please let me know if there is any other info I need to include.

EDIT PORTION |

listADT.h:

#ifndef LISTADT_H
#define LISTADT_H

typedef struct list_type *ListType;
typedef struct ClientInfo ClientInfo;

ListType create(void);
void destroy(ListType listP);
void make_empty(ListType listP);
int is_empty(ListType listP);
int is_full(ListType listP);
void push(ListType listP, ClientInfo item);
void delete(ListType listP, ClientInfo item);
void printl(ListType listP);

#endif

Error after changing ClientInfo item to ClientInfo *item:

listADT.h:12:6: note: expected ‘ClientInfo * {aka struct ClientInfo *}’ 
but argument is of type ‘ClientInfo {aka struct ClientInfo}’
void push(ListType listP, ClientInfo *item);
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Jasmine
  • 313
  • 2
  • 23
  • 1
    "in another c file". That's not going to work. It needs to be defined in every C file it is used in. Either directly or in an included header file. – kaylum Nov 30 '16 at 05:30
  • Or the parameter may be changed to `ClientInfo *item`. – Ken Y-N Nov 30 '16 at 05:31
  • @kaylum in my assignment it states "Structure definition and operations can either be written in a separate .h and .c files or they can reside in client.h and client.c" – Jasmine Nov 30 '16 at 05:32
  • @KenY-N I got an error by doing that – Jasmine Nov 30 '16 at 05:33
  • What your assignment says does not change the C standard :-) But what @KenY-N tells you is correct and addresses the assignment. The full `ClientInfo` is not needed by your list implementation. You should be storing pointers. If you have errors when you do that then you should ask about those errors. – kaylum Nov 30 '16 at 05:36
  • @kaylum by adding the full `ClientInfo` it compiled with no error. If I try @KenY-N's, I come up with an error. I'll update my post with the error. – Jasmine Nov 30 '16 at 05:39
  • @KenY-N I did what you suggested and posted the error up so you can see. – Jasmine Nov 30 '16 at 05:45
  • 1
    You need to of course also change the places that call those functions to pass in a pointer instead of the struct. – kaylum Nov 30 '16 at 05:46
  • @kaylum I don't have any calls to these functions yet – Jasmine Nov 30 '16 at 05:48
  • See also [Is it a good idea to typedef pointers](https://stackoverflow.com/q/750178/151168) — TL;DR the answer is usually "No", with possible exceptions for function pointers. – Jonathan Leffler Mar 02 '20 at 06:01

1 Answers1

4

typedef struct ClientInfo ClientInfo;

This is a forward declaration - a declaration of an incomplete type that will later on get completed in your client.c file. However, this design with a forward declaration in a header file makes the contents of the struct private.

No other file in your program will know what the struct contains, nor will they be able to access members. For them, the struct will still be incomplete and therefore they can't declare variables of this struct type. They can however declare pointers to the struct.

This is actually how you do private encapsulation of objects in C. The concept is called "opaque type" and is considered good OO design practice.

What you can do to fix the problems, is to change all functions in "client.h" and "client.c" so that they work with ClientInfo* pointers instead. Then every other file using ClientInfo will have to use pointers. Since they won't be able to declare any object of that type, you'll have to provide a constructor (and destructor). For example:

ClientInfo* client_create (void)
{
  return malloc(sizeof(ClientInfo));
}
Lundin
  • 195,001
  • 40
  • 254
  • 396