I need to build a "social network" for college, but I always get unknown type name 'List' while compiling. I removed a lot of functions from my headers, but I still get the same error and I don't know why.
I've got 3 headers:
My friend's header
#ifndef FRIEND_H
#define FRIEND_H
#include "ListHeadTail.h"
typedef struct Friend{
int id;
struct Friend *nextFriend;
}Friend;
void printFriends(List *l);
void removeFriend(List *l);
void addFriend(List *l);
#endif /* FRIEND_H */
My list header:
#ifndef LISTHEADTAIL_H
#define LISTHEADTAIL_H
#include "Student.h"
typedef struct pStudent{
struct pStudent *ant;
Student *s;
struct pStudent *prox;
}pStudent;
typedef struct list{
pStudent *head;
pStudent *tail;
}List;
void startList(List *l);
void printList(List *l);
void freeList(List *l);
#endif /* LISTHEADTAIL_H */
My student's header
#ifndef STUDENT_H
#define STUDENT_H
#define MAX 51
#include "Friend.h"
#include "ListHeadTail.h"
typedef struct Student{
int id;
char name[MAX];
Friend *friends;
}Student;
Student* readStudent ();
void printStudent(Student* a);
void changeData(List *l);
#endif /* STUDENT_H */
My main:
#include <stdio.h>
#include <stdlib.h>
#include "ListHeadTail.h"
#include "Friend.h"
#include "Student.h"
int main(int argc, char** argv) {
List l;
startList(&l);
freeList(&l);
return (EXIT_SUCCESS);
}
Thanks for reading.
Here's the (first) error I get when I try to compile this set of files:
$ cc main.c
In file included from main.c:4:
In file included from ./ListHeadTail.h:4:
In file included from ./Student.h:6:
./Friend.h:11:19: error: unknown type name 'List'
void printFriends(List *l);
Look at the file names and line numbers. Note that at ListHeadTail.h line 4, you've already defined LISTHEADTAIL_H, but you haven't yet reached the actual declaration of List. You then go into Student.h, and from there into Friend.h. That includes ListHeadTail.h again -- but since LISTHEADTAIL_H is already defined, this include does nothing. So you continue through Friend.h with no declaration of List, and therefore get an error on the declarations that reference it.
As noted by #lurker in their comment, the basic issue here is circular dependency, and a simple fix is forward declaration. In this case, you could simply modify Friend.H, replacing #include "ListHeadTail.h" with typedef struct list List;.
But to me this is a bit hacky. If you shift the order of includes somewhere, the build might break again.
I think the real problem is that the declarations of the functions (printFriends, etc.) don't belong in Friend.h; they belong in ListHeadTail.h. The functions have nothing to do with the Friend type. Sure, they have "Friend" in their names, but the only type referenced in the declarations is List. So they belong in ListHeadTail.h. Same goes for the changeData function in Student.h.
In an object-oriented design (say, in Java), these functions would all probably be methods of the List class, and would be declared in that class's source file.
How would I go about linking 2 header files that depend on each other with their c files?
For instance I have a file stack.h that depends on a struct declared in linkedlist.h, and the file "stack.c" calls on functions from linkedlist.c which depend on both header files. main.c depends on both header files
linkedlist.h
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
struct listNode
{
int nodeValue;
struct listNode * next;
};
typedef struct listNode listNode;
stack.h
#include "linkedList.h"
typedef struct stack {
listNode *list;
}stack;
How would I go about linking 2 header files that depend on each other
Don't. You should never have such a scenario or your program design is broken.
For your specific example, it appears that you try to implement a stack ADT by using a linked list. If so the stack should include the linked list ADT and that's it.
I am learning to write programs in professional way. Like, by creating separate .C and .h file.i decided to write a simple code with structures but I am getting errors.
I have done these things :
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
struct list{
int a;
struct list *next;
};
typedef struct list LIST;
LIST *pHead=NULL,*pCurrent=NULL;
void display(void);
#endif
/*---list.c file ---*/
#include "main.h"
void display()
{
pHead->a=100;
printf("%d",pHead->a);
}
/*----main.h file-----*/
#ifndef MAIN_H
#define MAIN_H
#include<stdio.h>
#include "list.h"
#endif
/*---main.c file---*/
#include "main.h"
void main(void)
{
LIST *New=pHead;
display();
printf("\n\n%d",New->a);
getch();
}
when i compile the code , I am getting following errors
1>main.obj : error LNK2005: _pCurrent already defined in list.obj
1>main.obj : error LNK2005: _pHead already defined in list.obj
can anyone please tell me what I am doing wrong ? Am I including something twice because of which I am getting redeclaration error ?
This is because you define things in your header, as opposed to merely declaring them.
This:
LIST *pHead=NULL,*pCurrent=NULL;
means that every C file that includes the list header, tries to create two global variables. When you then link these C files together, those variables collide. This is broken, you should never do that. Never define things in a header.
You defined the objects in a header file and then included them in multiple source files thus breaking the one definition rule.
If you want to create global variables which you can use across different translation units, you should use the extern keyword.
Generally speaking, .c files contain embodiment of variables, functions, etc.; while .h files contain prototypes of variables, functions, etc., found in it's companion .c file.
It is generally the case that variable and function bodies are not placed in a .h file; only variable and function prototypes should be placed in .h files.
When considering how to split-up code into separate files, it is important to consider which functions, structures and macros are the most primitive. For example, if you write two functions, and function 'a' calls function 'b', function 'b' is most primitive.
The idea is to group functions into a 'c' file that are related, and are at a similar primitive level.
In the case of this question, the more primitive list functions should be embodied in list.c. Then 'list.h' is used to prototype functions and structures used by other less primitive .c files such as main.c.
The most primitive functions are also the most self sufficient. While less primitive functions should call more primitive functions, the reverse makes for clumsy code-flow.
Now to review the question code:
/*---list.c file ---*/
#include "main.h"
list.c should be considered as more primitive than main.c. Hence, having list.c include main.h is (professionally) not a good idea. list.c, being more primitive should be more self-sufficient.
Rather than including main.h, it would be better for list.c to include it's own list.h so that it has access to it's own `struct list' definition, etc.
void display()
{
pHead->a=100;
printf("%d",pHead->a);
}
In order to better isolate list.c, the above function should not reference a 'global' variable (pHead). Rather, it would be better to have the 'node to display' passed into the function as an argument.
With this in mind, here are how 'list.c' and 'list.h' might be improved:
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
typedef struct NODE_S
{
int a;
struct list *next;
} NODE_T;
typedef struct LIST_S
{
NODE_T *head;
} LIST_T;
extern void NodeDisplay(NODE_T *node);
#endif
/*---list.c file ---*/
#include <stdio.h> // printf()
#include "list.h" // NODE_T, LIST_T
void NodeDisplay(NODE_T *node)
{
printf("%d\n",pHead->a);
return;
}
Note that pHead and pCurrent are not prototyped, or embodied, in list.h or list.c Those variables are not used in list.c, and there is no functional reason to place them in list.h
Now examine main.h and main.c as they are in the question code:
/*----main.h file-----*/
#ifndef MAIN_H
#define MAIN_H
#include<stdio.h>
#include "list.h"
#endif
In isolation, what is the purpose that main.h requires stdio.h and list.h? If they were removed, would there be something left 'undefined' in 'main.h'? Perhaps these two include files don't really belong in main.h. "But if they are removed from main.h, why even have a main.h?" Good point. perhaps main.h serves no purpose and perhaps should not even exist.
The main.c file is the least primitive of all files, and shouldn't generally export anything to other (more primitive) files.
/*---main.c file---*/
#include "main.h"
void main(void)
{
LIST *New=pHead;
display();
printf("\n\n%d",New->a);
getch();
}
So what exactly does main.c need? It needs calls printf(), so it will need to include stdio.h. It calls display(), and references the LIST structure, so it needs list.h.
Yes, those .h files were included in main.h; good point. However, the code will be less clumsy (more professional) if main.c includes exactly what it needs explicitly.
With this philosophy in mind, here is a reworked main.c, without a superfluous main.h:
/*---main.c file---*/
#include <stdio.h> // printf()
#include <conio.h> // getch()
#include "list.h" // NodeDisplay(), LIST_T
int main(void)
{
LIST_T pList =
{
.head = NULL
};
/* Allocate & Insert a node into the list. */
NodeCreate(&pList, 100);
NodeDisplay(pList.head);
getch();
return(0);
}
This version of main.c includes exactly what is required, and appropriately calls less primitive functions. It has no need for 'global variables' because it passes its local storage to more primitive functions as needed.
Oh! you noticed the function NodeCreate()!
While the operation of allocating and inserting a new list node could be performed in main.c, such an operation is most likely a common occurrence that fits nicely with other linked list operations. Hence, add such a function to list.c:
/*---list.c file ---*/
#include <stdio.h> // printf()
#include <stdlib.h> // malloc()
#include "list.h" // NODE_T, LIST_T
void NodeDisplay(NODE_T *node)
{
printf("%d\n",node->a);
return;
}
void NodeCreate(LIST_T *list, int a)
{
NODE_T *newNode = malloc(sizeof(*newNode));
if(NULL == newNode)
{
fprintf(stderr, "malloc(newNode) failed.\n");
goto CLEANUP;
}
if(NULL == list)
{
fprintf(stderr, "Passing NULL as the list address not allowed.\n");
goto CLEANUP;
}
/* Initialize new node fields (payload) */
newNode->a = a;
/* Link newNode as new 'list head' node. */
newNode->next = list->head ? list->head->next : NULL;
list->head = newNode;
newNode=NULL;
CLEANUP:
if(newNode)
free(newNode);
return;
}
And so that this function can be called from the less primitive main.c, add a prototype of the function to list.h:
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
typedef struct NODE_S
{
int a;
struct list *next;
} NODE_T;
typedef struct LIST_S
{
NODE_T *head;
};
extern void NodeDisplay(NODE_T *node);
extern void NodeCreate(LIST_T *list, int a);
#endif
See spoiler code here.
I am writing a linked list implementation for a networking project I'm working on. It is split into two files: llist.h and llist.c. I include llist.h in several of the project files, and when compiling I link to library that I compiled which includes llist.c. Unfortunately I get a "multiple definitions" error for every method header in llist.h. ie:
../util//libdutil.a(llist.o): In function `LListContains':
llist.c:(.text+0x0): multiple definition of `LListContains'
../util//libdutil.a(llist.o):llist.c:(.text+0x0): first defined here
I'm not quite sure why I'm getting this error. It used to be fine, but this has started happening since I added one more method. Here is the entire h file:
#ifndef _LLIST_H_
#define _LLIST_H_
typedef struct _LinkedList
{
int length;
void* data;
struct _LinkedList* head;
struct _LinkedList* tail;
}* LinkedList;
LinkedList LListContains(LinkedList list, void* data, int (*cmp)(const void *, const void *));
void* getDataLList(LinkedList list);
LinkedList createLList(void* data);
void* getFromHeadLList(LinkedList list, int pos);
void* popHeadLList(LinkedList list);
void* popTailLList(LinkedList list);
LinkedList getNextLList(LinkedList current);
LinkedList getPrevLList(LinkedList current);
void addHeadLList(LinkedList list, void* data);
void addTailLList(LinkedList list, void* data);
void FreeLList(LinkedList list);
#endif
Thanks!
UPDATE: Okay, the problem seems to come from the following code snippet in one of the project files:
OPP_DIRECTION(getDirToXYPOS((XYPOS*)getFromHeadLList(memories[avID], 0), &curPos)))
Note that getFromHeadLList is the method that I added to llist.h and defined in llist.c. By simply commenting out that part and adding in a dummy parameter, ie:
OPP_DIRECTION(getDirToXYPOS(&curPos, &curPos)))
It compiles fine.
Most probably you have compiled your llist.c into your project as well as into the static library.
Here's my problem: I need to implement a FIFO/LIFO list stack as ADT species 1. My program is modular and it have an item.h module:
#ifndef ITEM_H_INCLUDED
#define ITEM_H_INCLUDED
typedef struct
{
char stringa[20];
int numero;
} Item;
#endif // ITEM_H_INCLUDED
The head.h module:
#ifndef HEAD_H_INCLUDED
#define HEAD_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include "item.h"
void QUEUEinit();
int QUEUEempty();
void QUEUEput_top(Item);
void QUEUEput_bottom(Item);
Item QUEUEget_top();
Item QUEUEget_bottom();
#endif // HEAD_H_INCLUDED
The main.c and data.c; what i need is how i declare a QEUEnode struct and where.
Thank you for the help :)
Since none of your QUEUE* functions receive a QUEUEnode *, you can hide it in the head.c file, along with the QUEUEnode root; that they operate on.
If you want to use multiple queues, then it should probably be in the head.h file so they can be created in main.c. For this, you'll also need to modify the functions to accept a queue to operate on.