Argument incompatible in print linked list - C - c

So I try to print a linked list, and it says that the argument head is incompatible argument type.
The list is already made correctly and works if not put in another function. I just can't understand why this specific function doesn't work.
struct data {
char foodName[FILENAME_MAX];
int rating;
float price;
};
typedef struct listElement {
struct listElement *next;
struct data food;
struct listElement *previous;
} listElement;
void printList(listElement *head);
void printElement(listElement *element);
int main()
{
struct data food;
listElement head;
printList(head); <-- this one gets an error
return 0;
}
void printList(listElement *head)
{
if (head == NULL) {
printf("Linked list is empty.\n");
} else {
printf("Printing linked list to result file...\n");
printElement(head);
printf("Linked list successfully printed to result file.\n");
}
}
void printElement(listElement *element)
{
if (element == NULL || file == NULL) {
return;
} else {
printf ("name = %s rating = %d price = %f\n", element->food.foodName, element->food.rating, element->food.price);
printElement(element->next);
}

In this function void printList(listElement *head) you are expecting a pointer to a listElement but in the main function you are calling the printList function with a listElement type, not a listElement* type.
To fix this you have to declare your head variable like this listElement* head; or you have to give the printList function a pointer to the head variable, like this printList(&head);.
Either way, it depends on what you want to do with it. But the first suggestion is more common.

Related

Building a Linked List of Strings

I had a singly linked list that took in integers successfully, but now I want to use strings. However it is not working. I am getting so many different errors about "casting". I am finding conflicting information online as well. One comment here, Creating linked list of strings, said not to use strcpy, but I see strcpy used in a few examples online.
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
struct node {
char value[];
struct node* next; // pointer of structure type
};
// set existing type, node, to the alias, node_t
typedef struct node node_t;
node_t *create_new_node(char value) {
// create space for node with malloc
node_t *result = malloc(sizeof(node_t));
// set the value of the new node
result->value = value;
//strcpy(result->value, value);
// set the value's next pointer to null
result->next = NULL;
return result;
}
node_t *insert_at_head(node_t **head, node_t *node_to_insert) {
node_to_insert->next = *head;
*head = node_to_insert;
return node_to_insert;
}
//Prints linked list
void printlist(node_t* head) {
node_t *temporary = head;
while (temporary != NULL) {
//print out the value of the node that temporary points to
// printf("%d - ", temporary->value);
// to move along the list
temporary = temporary->next;
}
printf("\n");
}
int main() {
node_t *tmp;
// declaring head pointer
node_t *head = NULL;
// CREATING LINKED LIST
// for (int i = 0; i < 25; i++) {
// tmp = create_new_node(i);
// // sending the address of the head variable
// //calling by reference
// //SINCE HEAD IS ALREADY A NODE POINTER
// insert_at_head(&head, tmp);
// }
printlist(head);
tmp = create_new_node("I like food");
insert_at_head(&head, tmp);
}
How can I get this Linked List of string to work?
Thank you.
If you reorganize it a bit, you will be able to allocate the space the struct & the place for the string in the single malloc.
struct node
{
struct node* next; // pointer of structure type
char value[];
};
// set existing type, node, to the alias, node_t
typedef struct node node_t;
node_t *create_new_node(const char *value)
{
// create space for node with malloc
node_t *result = malloc(sizeof(*result) + strlen(value) + 1);
if(result)
{
strcpy(result->value, value);
result->next = NULL;
}
return result;
}
Please use your compiler! I ran $gcc -Wall a.c on this code and got:
a.c:7:10: error: flexible array member not at end of struct
char value[];
^
a.c: In function ‘main’:
a.c:67:5: warning: passing argument 1 of ‘create_new_node’ makes integer from pointer without a cast [enabled by default]
tmp = create_new_node("I like food");
^
a.c:15:9: note: expected ‘char’ but argument is of type ‘char *’
node_t *create_new_node(char value) {
^
a.c:70:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Now we know what the problems are. Firstly, char value[] should be char *value since it's a pointer rather than a flexible array member (FAM). You could also move the FAM to the end of the struct if you want as shown here.
Next, node_t *create_new_node(char value) is relying on a char value when you really want a string, char *value for the parameter. There are issues beyond this: you'll likely want to make a copy of the string for the node in case it disappears from the stack. This memory should be cleaned up after use.
Other tips:
Avoid noisy, redundant comments like:
// declaring head pointer
node_t *head = NULL;
malloc(sizeof(*name_of_the_var)); is safer than malloc(sizeof(node_t)); if the data changes.
node_t *insert_at_head(node_t **head, node_t *node_to_insert) modifying its parameter and returning it is a little unusual. I'd make it void to make the in-place contract explicit.
Alphabetize and remove unused imports.
Check that malloc calls succeeded.
Remember to return 0; from main.
typedef struct node node_t; is okay but also hides info--I prefer keeping the struct there.
Here's a possible rewrite:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *value;
struct node* next;
};
struct node *create_new_node(char *value) {
struct node *node = malloc(sizeof(*node));
if (!node) {
fprintf(stderr, "%s:%d malloc failed\n", __FILE__, __LINE__);
exit(1);
}
node->next = NULL;
node->value = strdup(value);
if (!node->value) {
fprintf(stderr, "%s:%d malloc failed\n", __FILE__, __LINE__);
exit(1);
}
return node;
}
void insert_at_head(struct node **head, struct node *node_to_insert) {
node_to_insert->next = *head;
*head = node_to_insert;
}
void print_list(struct node *head) {
for (; head; head = head->next) {
printf("%s->", head->value);
}
puts("");
}
void free_list(struct node *head) {
while (head) {
struct node *tmp = head;
head = head->next;
free(tmp->value);
free(tmp);
}
}
int main() {
struct node *head = NULL;
for (int i = 0; i < 10; i++) {
char n[16];
sprintf(n, "%d", i);
insert_at_head(&head, create_new_node(n));
}
print_list(head);
free_list(head);
return 0;
}
Output:
9->8->7->6->5->4->3->2->1->0->

Unable to add to header of linkedlist

I've got a LinkedList node struct defined as such:
struct intnode {
int item;
struct intnode *next;
};
typedef struct intnode IntNode;
Which I am using to do some simple sorting. However, in creating this linked list, I am having difficulty with scope. In my main function I've got a Null header IntNode object to serve as the first element in the list, however I can't modify it within my insert function, despite the fact that I'm passing a pointer to it. The code never reaches the print statement saying the list is no longer empty, which I am confused by. Does this have something to do with defining a new IntNode element to add within the insert function which is then thrown away after the function is done?
int main() {
IntNode *header = NULL;
printf("Enter some numbers, ending with -1: ");
int a;
while(a != -1) {
scanf("%d",&a);
if(a != -1) {
insert(header, a);
}
}
return 0;
}
IntNode *createNode(int val) {
IntNode *new_node;
new_node = malloc(sizeof(IntNode));
new_node->item = val;
return new_node;
}
void insert(IntNode *header, int val) {
IntNode *newNode = createNode(val);
if(header == NULL) { //list is empty, so insert at front
printf("list still empty\n");
newNode->next = header;
header = newNode;
printf("%d",header->item);
} else {
printf("the list is no longer empty...");
//do more stuff here
}
}
If you want to modify a pointer, you need to pass a pointer of that pointer. Therefore
insert(header, a);
should be
insert (&header, a);
and adjust your insert() function accordingly.

Applying Singly Linked List in C

Creating a list in C implementing SLL.
struct dat
{
char fname[20];
char lname[20];
};
typedef struct node_s
{
struct dat data;
struct node_s *next;
}NODE;
NODE *list=NULL;
NODE *list_create(struct dat *data)
{
NODE *node;
if(!(node=malloc(sizeof(NODE))))
{
return NULL;
}
node->data = data;
node->next = NULL;
return node;
}
NODE *list_insert_after(NODE *node, struct dat *data)
{
NODE *newnode;
newnode = list_create(data);
newnode->next = node->next;
node->next = newnode;
return newnode;
}
I cant find any good examples using SLL.
Now i have this append function now i will apply the two SLL functions, list_create and list_insert_after.
Is this correct?
void app(struct dat x)
{
FILE *fp;
fp=fopen("database.dat","a");
if(fp==NULL)
{
printf("file error");
}
if(fp!=NULL)
{
printf("enter lname: ");
gets(x.lname);
printf("enter fname: ");
gets(x.fname);
fprintf(fp,"%s %s\n",x.lname,x.fname);
if(list == NULL)
{
list=list_create((&x));
}
else
{
next=list_insert_after(list,&x);
}
}
fclose(fp);
}
To complete your example you should decide:
a) what if the role of your file database.dat.
b) how you work with your list.
I suppose you need two pointers to operate with the list: a pointer to the first element (it is list I think) and pointer to the last element (may be it is next).
Now call such as list_insert_after(list,&x); always inserts element after the first element, so your list cannot be longer than 2.
Consider the changes in your code as follows:
if(list == NULL)
{
list = list_create((&x));
next = list; // the last is the first
}
else
{
next=list_insert_after(next,&x); // insertion after the last
}
And about the file: if you decide to store not strings in text file, but structures in the binary file, save only struct dat to file, because storing pointers has no sense.
Even if C is a low level language, it is not forbidden to structure data. The node should be an internal object of the list. How to implement it in C depends on how you want to use it. Some examples :
a FIFO stack : 2 functions push and pop, and the list only needs to retain the last added element (you won't add after but before - left as an exercise)
a LIFO queue : still only 2 functions add and take, and the list needs to retain first element (its head) because its the next that will be taken, and last one (its tail) because it is where you will add next
typedef struct list_s {
NODE *head;
NODE *tail;
int len;
} LIST;
int add(LIST *list, struct dat *data) {
list->tail = list_insert_after(list->tail, data);
list->len += 1;
return list->len;
}
struct dat * take(LIST *list) {
if (list->len == 0) return NULL;
struct dat *data = head->data;
NODE *n = head;
head = head->next;
free(n);
return data;
}
of course, you will have to initialize a list, could take its length, ...
a true list : internally the same as a LIFO, but you will have to define an iterator (only contains a NODE *), and for example a BOOL hasnext(*ITERATOR) and struct dat * next(*ITERATOR)
the remaining is only limited by your requirements
NB: I assumed NODE.data was a struct dat * not a struct dat ...

Linked Lists in C, Random output?

#include <stdio.h>
struct list
{
int data;
struct list *next;
};
struct list *start, *end;
void add(struct list *head, struct list *list, int data);
void delete(struct list *head, struct list *tail);
int main(void)
{
start=end=NULL;
add(start, end, NULL);
add(start, end, NULL);
printf("First element: %d");
delete(start, end);
return 0;
}
void add(struct list *head, struct list *tail, int data)
{
if(tail==NULL)
{
head=tail=malloc(sizeof(struct list));
head->data=data; head->next=NULL;
} else {
tail->next=malloc(sizeof(struct list));
tail=tail->next;
tail->data=data;
tail->next=NULL;
}
}
void delete(struct list *head, struct list *tail)
{
struct list *temp;
if(head==tail)
{
free(head);
head=tail=NULL;
} else {
temp=head->next;
free(head);
head=temp;
}
}
I am aiming to return an output of 3 but keep getting random results. Any insight is greatly appreciated
As you want to modify head and tail you need to pass a pointer to them.
i.e.
void add(struct list **head, struct list **tail, int data)
{
if(*tail==NULL)
{
*head = *tail = malloc(sizeof(struct list));
(*head)->data = data;
(*head)->next = NULL;
} else {
(*tail)->next = malloc(sizeof(struct list));
*tail = (*tail)->next;
(*tail)->data = data;
(*tail)->next = NULL;
}
}
Do similarly for the other function. Then head and tail will also change outside the function.
The line
printf("First element: %d");
It requires an integer to print - supply it - see the manual page for printf
Avoid using keywords for C++ in C programs - such as delete
Parameters of C functions are passed by value. Thus, the changes that you make to the values of head and tail in the add() function will not be reflected in main() from which add() is called.
And, it doesn't seem that you've supplied a second parameter for printf(), so the %d format is not going to get the integer value that it will be looking for.
In your program start and end are global variables, so there is no need to pass it as arguments to other functions, because other methods can directly access it.
//Structure to store data
struct list
{
int data;
struct list *next;
};
// global variables
struct list *start, *end;
void add(int);
void delete();
// start of program
int main(void)
{
start=end=NULL;
add(5);
add(6);
printf("\nFirst element: %d",start->data);
delete();
printf("\nFirst element: %d",start->data);
return 0;
}
//add node to list
void add(int data)
{
if(end==NULL)
{
start=end=malloc(sizeof(struct list));
start->data=data; start->next=NULL;
} else {
end->next=malloc(sizeof(struct list));
end=end->next;
end->data=data;
end->next=NULL;
}
}
// delete node from list
void delete()
{
struct list *temp;
if(start==end)
{
free(start);
start=end=NULL;
} else {
temp=start->next;
free(start);
start=temp;
}
}
OUTPUT:
First element: 5
First element: 6
Note:
If you don't want your start and end to be global than it can be a local variable of main function. Here you have to either work on double pointer mechanism or return memory address to retain the modification.
There are a number of problems here.
First, when you pass a pointer to a function, the pointer is passed by value. Any changes to the pointer in the called function will not be reflected in the calling function. To change what the pointer in the calling function is pointing to, you need to pass a pointer-to-pointer. So your add()function needs to be:
void add(struct list **head, struct list **tail, int data) {
if(*tail == NULL) {
*head = *tail = malloc(sizeof(struct list));
(*head)->data = data;
(*head)->next = NULL;
}
else {
(*tail)->next = malloc(sizeof(struct list));
(*tail) = (*tail)->next;
(*tail)->data = data;
(*tail)->next = NULL;
}
return;
}
And your delete() function needs to be changed similarly.
Secondly, you are passing NULL as your data value to the add function. NULL is a pointer; it is typically defined as a macro, and could be (void*) 0 in the implementation. It should not be used as an integer. Pass 0 as the integer, not NULL.
Third, you have this statement:
printf("First element: %d");
Your format string has the conversion specifier %d but there is no argument that matches the %d. This is undefined behavior. What integer exactly are you trying to print?
Where do you expect the output 3, and for what reason?

finding the pointer to an element in linked list in c

i want to get the pointer to an element in linked list in c.
here is my code. Im getting the error "incompatible types when returning type ‘bigList’ but ‘struct bigList **’ was expected". please help. thanks
/*this is the struct*/
struct bigList
{
char data;
int count;
struct bigList *next;
};
int main(void)
{
struct bigList *pointer = NULL;
*getPointer(&pointer, 'A'); //here how do I store the result to a pointer
}
/*function to return the pointer*/
bigList *getPointer(bigList *head, char value)
{
bigList temp;
temp=*head;
while(temp!=NULL)
{
if(temp->data==value)
break;
temp = temp->next;
}
return *temp; //here I get the error I mentioned
}
You need 2 pointers, a head pointer to your base list and the place you want to return your pointer:
int main(void)
{
struct bigList *pointer = NULL;
struct bigList *retValPtr = getPointer(pointer, 'A'); //here how do I store the result to a pointer
}
struct bigList *getPointer(struct bigList *head, char value)
{
struct bigList *temp; // Don't really need this var as you could use "head" directly.
temp = head;
while(temp!=NULL)
{
if(temp->data==value)
break;
temp = temp->next;
}
return temp; // return the pointer to the correct element
}
Notice how I've changed around the pointers such that they are all the same type whereas your code is kinda random about thsi. It matters quite a bit!

Resources