C LinkedList example doesn't compile - c

The following C code is my own way of writing a primitive linked list. It uses a struct called lnode. I know this is not the best/most efficient way to do it but my idea is this: create the base node, use an "iterator" pointer, here q, that points to that last node in the list and then add a new node.
The following code will not compile. I can't find the cause but it hates this line
struct lnode *q= malloc(sizeof(struct lnode));
Any advice on making this idea work? Thanks in advance.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
struct lnode{
int value;
struct lnode *nextnode;
};
int main(){
struct lnode *startnode = malloc(sizeof(struct lnode));
startnode->value=0;
startnode->nextnode=NULL;
struct lnode *q= malloc(sizeof(struct lnode));
int i = 0;
for(i=0;i<10;i++){
struct lnode *p = malloc(sizeof(struct lnode));
p= q->nextnode;
p->value=i;
p->nextnode=NULL;
q=p;
}
return 0;
}
I would like to point out that I'm a novice. I'm using the Watcom compiler (Why? My computer is old and its all I need for these practice porgrams) The log output is
structure1.c(17): Error! E1063: Missing operand structure1.c(17):
Warning! W111: Meaningless use of an expression structure1.c(17):
Error! E1009: Expecting ';' but found 'struct' structure1.c(17):
Error! E1011: Symbol 'lnode' has not been declared structure1.c(17):
Error! E1011: Symbol 'q' has not been declared structure1.c(17):
Error! E1014: Left operand must be an 'lvalue' structure1.c(19):
I followed the advice given and changed the code the new code is this:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
struct lnode{
int value;
struct lnode *nextnode;
};
int main(){
struct lnode *startnode = (struct lnode *)malloc(sizeof(struct lnode));
struct lnode *q;
startnode->value=0;
startnode->nextnode=NULL;
q = malloc(sizeof(struct lnode));
doLoop(q);
return 0;
}
void doLoop(struct lnode *q){
int i = 0;
for(i=0;i<10;i++){
struct lnode *p = (struct lnode *)malloc(sizeof(struct lnode));
q->nextnode=p;
p->value=i;
p->nextnode=NULL;
printf("%i, %i\n",p->value,q->value);
q=p;
}
}
I printed the "value" values of each node in the list along with the previous value. It works except the first iteration which gives a weird output.

I suspect the compiler (Microsoft compilers for example) supports C89 standard only, which does not permit the intermingling of code and declarations. Move declaration of q to top of scope:
int main(){
struct lnode *startnode = (struct lnode *)malloc(sizeof(struct lnode));
struct lnode *q
startnode->value=0;
startnode->nextnode=NULL;
q = malloc(sizeof(struct lnode));

The code compiles - http://ideone.com/j6fGe - but the logic is wrong:
struct lnode *p = (struct lnode *)malloc(sizeof(struct lnode));
p= q->nextnode;
Besides the fact that you have a memory leak, I'm sure this is not what you intended.
q->nextnode doesn't point to a valid node, just some random memory. Which you then try to overwrite with p->value=i;.

The error messages is due to the mixing of code and declarations.
Further; You switch p and q around in the for loop.
p = q->next_node; /* here you set p to an undefined area.
* q->next_node is not malloc'd */
p->value = i; /* here you cause undefined / erronous behaviour
* Most probably a SIGSEGV */
So to sum it up, perhaps something like:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
struct lnode{
int value;
struct lnode *nextnode;
};
int main(void)
{
struct lnode *startnode;
struct lnode *p;
size_t z;
int i;
z = sizeof(struct lnode);
if ((startnode = malloc(z)) == NULL) {
fprintf(stderr, "Unable to malloc %d bytes.\n", z);
return 1;
}
/* Fill list */
p = startnode;
for (i = 0; i < 10; i++) {
if ((p->nextnode = malloc(z)) == NULL) {
fprintf(stderr, "Unable to malloc %d bytes.\n", z);
return 1;
}
p->value = i;
p = p->nextnode;
p->nextnode = NULL;
}
/* Print values */
p = startnode;
while (p->nextnode != NULL) {
printf("value: %2d\n", p->value);
p = p->nextnode;
}
/* Free */
p = startnode;
while (p != NULL) {
p = p->nextnode;
free(startnode);
startnode = p;
}
return 0;
}

Related

Why am I getting Segmentation fault (core dumped) or bus error (core dumped) when trying to populate a struct?

So I am trying to use a pointer to a struct of MonsterAttacks as the data that belongs to an element of a linked list. In order to do this I try to populate a struct of MonsterAttacks and then pass that along with a null ptr to a next node to a function called create. However somewhere in the populate method a segmentation fault error occurs. I am working with three files list_demo.c, linked_list.h and linked_list.c. I will build all the the functions that make up a fully functioning linked list, well hoping I can as soon as I get pass this error. Been dealing with this error for about two days and I showed my professor and he could not figure out why its happening, it seems to come from the populate function. I have tried to return a pointer to a strut in which case I get a bus error, and I have tried almost every variation of getting input and storing it on the strut. I even deleted the function and tried to populate it in main, but nothing works. I am new to C and my professor helped me out for about an hour debug this problem and he finally gave up, so any help would be appreciated.
list_demo.c
#include <stdio.h>
#include "linked_list.h"
#include <stdlib.h>
void populate(struct MonsterAttacks *m){
printf("Enter the name for the Monster \n");
scanf("%40s",m->monsterName);
puts("What is his/her attack location?");
scanf("%40s",m->attackLocation);
puts("What are the number of victims this monster has demolished?");
scanf("%ud", &m->numOfVictims);
m->attackID = 0;
}
int main(void)
{
node* tmp = NULL;
struct MonsterAttacks *tmpMonst = (struct MonsterAttacks *)
malloc(sizeof(struct MonsterAttacks));
if(tmpMonst == NULL){
printf("Error allocating memory");
}
else
populate(tmpMonst);
node *head = create(tmpMonst,tmp);
free(tmpMonst);
return 0;
}
linked_list.h
#ifndef LINKED_LIST
#define LINKED_LIST
typedef struct node{
struct MonsterAttacks *monsterAttack;
struct node* next;
} node;
struct MonsterAttacks{
unsigned int attackID;
char monsterName[41];
char attackLocation[41];
unsigned int numOfVictims;
};
/*
create a new node
initialize the data and next field
return the newly created node
*/
node* create(struct MonsterAttacks *m,node* next);
#endif
linked_list.c
// from zentut.com, heavily adapted
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "linked_list.h"
/*
create a new node
initialize the data and next field
return the newly created node
*/
node* create(struct MonsterAttacks *m,node* next)
{
node* new_node = (node*)malloc(sizeof(node));
if(new_node == NULL)
{
printf("Error creating a new node.\n");
exit(0);
}
new_node->monsterAttack->attackID = 0;
new_node->next = next;
strncpy(new_node->monsterAttack->monsterName,m->monsterName,41);
strncpy(new_node->monsterAttack->attackLocation, m->attackLocation, 41);
new_node->monsterAttack->numOfVictims = m->numOfVictims;
return new_node;
}
Btw running on Red Hat using gcc compiler
new_node->monsterAttack->attackID = 0;
Allocating memory for new_node does not allocate memory for the MonsterAttacks struct inside it. That is why dereferencing monsterAttack to get its attackID is causing a seg fault.
A minimal working code
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
// Moved the two structs out to make a minimal reproducible code
/* #include "linked_list.h" */
struct MonsterAttacks{
unsigned int attackID;
char monsterName[41];
char attackLocation[41];
unsigned int numOfVictims;
};
typedef struct node{
struct MonsterAttacks *monsterAttack;
struct node* next;
} node;
void populate(struct MonsterAttacks *m){
printf("Enter the name for the Monster \n");
scanf("%40s",m->monsterName);
puts("What is his/her attack location?");
scanf("%40s",m->attackLocation);
puts("What are the number of victims this monster has demolished?");
scanf("%ud", &m->numOfVictims);
m->attackID = 0;
}
node* create(struct MonsterAttacks *m,node* next)
{
node* new_node = (node*)malloc(sizeof(node));
if(new_node == NULL)
{
printf("Error creating a new node.\n");
exit(0);
}
// Just add this line
new_node->monsterAttack = malloc(sizeof (struct MonsterAttacks));
new_node->monsterAttack->attackID = 0;
new_node->next = next;
strncpy(new_node->monsterAttack->monsterName,m->monsterName,41);
strncpy(new_node->monsterAttack->attackLocation, m->attackLocation, 41);
new_node->monsterAttack->numOfVictims = m->numOfVictims;
return new_node;
}
int main(void)
{
node* tmp = NULL;
struct MonsterAttacks *tmpMonst = (struct MonsterAttacks *)
malloc(sizeof(struct MonsterAttacks));
if(tmpMonst == NULL){
printf("Error allocating memory");
}
else {
populate(tmpMonst);
}
node *head = create(tmpMonst,tmp);
printf("Name: %s\n", tmpMonst->monsterName);
printf("num victim: %d\n", tmpMonst->numOfVictims);
free(tmpMonst);
return 0;
}
When you allocate memory for new_node in create(...), you allocate memory on the heap for a structure of type node to hold all the variables it contains. In this case, monsterAttack in node is initially a pointer to a struct that is pointing to nowhere. You need to explicitly allocate memory for the monsterAttack pointer to point to.
Edit: #bruceg pointed out the lack of semicolon, this malloc isn't the issue. #lightalchemist have highlighted that the second one is the fault.
struct MonsterAttacks *tmpMonst = (struct MonsterAttacks *);
malloc(sizeof(struct MonsterAttacks));
Your malloc call is wrong, malloc allocates and returns a pointer to the memory. You ignore/discard the pointer value.
Later code seems to assume that tmpMonst points to this allocated memory but there is no link between the two.
Try struct MonsterAttacks *tmpMonst = malloc(sizeof(struct MonsterAttacks));

Inserting nodes in a linked list in decreasing order - C

I have to make a list that arrange the people in decreasing order of their number('no' for my program). I tryed to make it by modifying the addNode function but I got no result(peoples do not arrange by their number). This is my code:
Header code:
#ifndef __EX__
#define __EX__
typedef struct Person{
char name[10];
float no;
struct Person *pNext;
} NODE, *pNODE, **ppNODE;
void addNode(ppNODE, pNODE);
void travers(pNODE, unsigned int*);
#endif
Functions folder:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "EX.h"
void addNode (ppNODE ppPrim, pNODE p){
pNODE q = (pNODE)malloc(sizeof(NODE));
assert(q!=NULL);
printf("Add name: \n");
scanf("%s", &q->name);
printf("\nAdd no: ");
scanf("%f", &q->no);
if (p == NULL || q->no < p->no) {
q->pNext = *ppPrim;
*ppPrim = q;
} else {
q->pNext = p->pNext;
p->pNext = q;
}
return;
}
void travers(pNODE pPrim, unsigned int *pLen){
*pLen = 0;
pNODE tmp = pPrim;
while (tmp != NULL){
puts (tmp->name);
fprintf(stdout, " no %.2f\n", tmp->no);
tmp = tmp->pNext;
(*pLen)++;
}
return;
}
Main folder:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "EX.h"
int main(){
unsigned int len;
pNODE prim = NULL;
int i;
for (i=0; i<=1; i++){
addNode(&prim, prim);
addNode(&prim, prim->pNext);
}
travers(prim, &len);
return 0;
}
When you insert a new node to the list, you must traverse the list until you find a suitable place to insert it. Your code takes a second argument, which isn't really needed and causes confusion, and only looks at that.
The code to insert a code q at the end of a list that is defined by its head is:
Node *prev = NULL;
Node *p = *head;
while (p) {
prev = p;
p = p->pNext;
}
q->pNext = p;
if (prev == NULL) {
*head = q;
} else {
prev->pNext = q;
}
You can get rid of keeping track of the previous node and the distinction between inserting at the head and inserting after that by traversing the list with a pointer to node pointer:
Node **p = &head;
while (*p && (*p)->no < q->no) {
p = &(*p)->pNext;
}
q->pNext = *p;
*p = q;
In this concise code, p holds the address of the head at first and the address of the pNext pointer of the previous node. Both can be updated via *p.
You can now use this code to traverse only as far as the numbers associated with each node are smaller than the one of the node to insert. here's a complete program:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct Node Node;
void addNode(Node **p, const char *name, float no);
void travers(Node *pPrim, unsigned int *pLen);
struct Node {
char name[10];
float no;
Node *pNext;
};
void addNode(Node **p, const char *name, float no)
{
Node *q = malloc(sizeof(*q));
assert(q != NULL);
snprintf(q->name, sizeof(q->name), "%s", name);
q->no = no;
while (*p && (*p)->no < q->no) {
p = &(*p)->pNext;
}
q->pNext = *p;
*p = q;
}
void traverse(const Node *pPrim, unsigned int *pLen)
{
*pLen = 0;
while (pPrim != NULL) {
fprintf(stdout, "%-12s%.2f\n", pPrim->name, pPrim->no);
pPrim = pPrim->pNext;
(*pLen)++;
}
}
int main()
{
unsigned int len;
Node *prim = NULL;
addNode(&prim, "Alice", 0.23);
addNode(&prim, "Bob", 0.08);
addNode(&prim, "Charlie", 0.64);
addNode(&prim, "Dora", 0.82);
traverse(prim, &len);
printf("\n%u entries.\n", len);
return 0;
}
Things to node:
I've used Node * and Node ** instead of the typedeffed pNODE and ppNODE. In my opinion using the C pointer syntax is clearer.
You should separate taking user input from adding a node.
In your code you shouldn't pass the address of the char array when scanning a string, just the char array. (It happens to work, but it isn't correct. The compiler should warn you about that.)

Q: Compiler Error of linked list, but still runs

I am not sure why I am getting these errors, but the weirdest thing, I am still able to run the program and produce the results I want.
The compiler error I get is
IntelliSense: a value of type "MyStruct *" cannot be assigned to an entity of type "Mystuct_struct *"
There are 4 instances of this, but as I stated in my title, the program still seems to run fine, and displays the bin file as I want it to. And yes, I know the name of my structure is bad.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct MyStruct_struct
{
char FlightNum[7];
char OriginAirportCode[5];
char DestAirportCode[5];
int timeStamp;
struct Mystruct_struct* next;
} MyStruct;
int main()
{
time_t time;
MyStruct * ptr;
MyStruct * head;
MyStruct * tail;
MyStruct * temp;
FILE * bin;
MyStruct myStruct;
bin = fopen("acars.bin", "rb");
ptr= (struct MyStruct_struct *) malloc (sizeof(MyStruct) );
fread(ptr,sizeof(MyStruct)-sizeof(MyStruct*),1,bin);
head = ptr; // make head point to that struct
tail = ptr; // make tail point to that struct
while (1)
{
ptr = (struct MyStruct_struct *) malloc(sizeof(MyStruct));
fread(ptr, sizeof(MyStruct) - sizeof(MyStruct*), 1, bin);
tail->next = ptr; // error here
tail = tail->next; //error here
if (feof(bin) != 0)
break;
}
tail->next = NULL;
ptr = head;
while (ptr->next != NULL)
{
printf("%s ", ptr->FlightNum);
printf("%s ", ptr->OriginAirportCode);
printf("%s ", ptr->DestAirportCode);
time = ptr->timeStamp;
printf("%s",ctime( &time));
ptr = ptr->next; // here
}
ptr = head;
while (ptr->next != NULL)
{
temp = ptr;
ptr = ptr->next; //error here
free(temp);
}
fclose(bin);
system("pause");
return 0;
}
You have a typo in your struct definition. The type for your variable next is MyStuct_Struct. Check your spelling on MyStuct_Struct. It still works because C is joiously not type safe. A pointer is a pointer is a pointer so you don't end up with memory errors.

create new nodes that point at each other

struct x{
...;
...;
struct x * next;
};
struct x create() {
struct x new = malloc...
new->... = .;
new->... = ..;
new->next = NULL
};
When i create a new node of struct x how does it work when using struct x create multiple times. It feels strange for me that you can use it multiple times because It allocate memory to a struct x with the same name new each time? Doesn't each node of a struct require an individual name. Or Does it only matters that each time a new memory allocation is done.
Main problem: I will create first node and then a second node. The first node should then point at the second node and so on. But when I create the first node the second doesn't exists so I can't set first->next = second.
I have looked at linked lists examples but it doesn't improve my thinking at the moment. The code isn't that important as my own understanding and thinking. Please help me think and grasp the concept.
//I tried to follow the sugestions from Degustaf(except the next pointer, basically the same as create a new node) but did the implementation wrong. So I wounder whats wrong with this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct x{
int a;
int b;
struct x * next;
}
struct x *create(int a , int b){
struct x *new = malloc(sizeof(struct x));
new->a = a;//namn skitsamma allokering relevant
new->b = b;
new->next = NULL;
return new;
};
int main() {
struct x *x1 = struct x *create(12,13);
return 0;
}
You can simply assign the values of the pointers after you've created both.
i.e.,
struct x x1 = create();
struct x x2 = create();
x1.next = &x2;
x2.next = &x1;
Or Does it only matters that each time a new memory allocation is done.
Correct.
But, there are other issues with your code. In particular, you aren't returning anything from your create function. I see 2 ways to approach this to remedy the problem. The first is that you can return the struct directly, which means that you don't need the malloc:
struct x create()
{
struct x new;
new.member1 = .;
new.member2 = ..;
new.next = NULL;
return new;
};
Then you can populate it using
struct x x1 = create();
struct x x2 = create();
x1.next = &x2;
The other possibility is to return a pointer to a struct, in which case this becomes
struct x *create()
{
struct x *new = malloc...;
new->member1 = .;
new->member2 = ..;
new->next = NULL;
return new;
};
Then you can populate it using
struct x *x1 = create();
x1->next = create();
My opinion is that the second option is cleaner as you don't need to worry about individual elements of your linked list going out of scope, although it does require being careful when it comes to freeing memory (needing to traverse the list and free one element at a time.
I thing this is what you want but this is a example with intenger numbers in a list also yoy can change the code as you wish.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <iostream>
struct cell {
float info;
struct cell * next;
};
int more (float * k)
{
char ans[4];
printf("Continue Yes/No: ");
scanf("%s",ans);
if (ans[0]=='Y') {
printf("insert value: ");
scanf("%f",k);
return(1);
}
else
return(0);
}
struct cell * crelist()
{
struct cell * last = (struct cell *)NULL;
struct cell * ptr = (struct cell *)NULL;
struct cell * list = (struct cell *)NULL;
float k;
ptr = (struct cell *)malloc(sizeof(struct cell));
if (ptr != (struct cell *)NULL) {
printf("insert value: ");
scanf("%f",&k);
ptr->info = k;
ptr->next = (struct cell *)NULL;
list = ptr;
last = ptr;
}
else
return((struct cell *)NULL);
while (more(&k)) {
ptr = (struct cell *)malloc(sizeof(struct cell));
if (ptr != (struct cell *)NULL) {
ptr->info = k;
ptr->next = (struct cell *)NULL;
last->next = ptr;
last = ptr;
}
else
break;
}
return(list);
}
void printlist(struct cell * list)
{
struct cell * p;
p = list;
while (p != (struct cell *)NULL) {
printf("->%f\n",(*p).info);
p=(*p).next;
}
return;
}
int main()
{
struct cell * list;
int i;
list = crelist();
printlist(list);
scanf("%d",&i);
system("pause");
return 0;
}

How to access an element of an array just given a pointer

struct node
{
int a;
node * link;
}
i have an array A with each element of type 'pointer to node' and hence each element of A can have variable size.Example
A[0]=NULL
A[1]=2->3->4
A[2]=3->4
and so on..
so to dynamically allocate an array if I use
u = (struct node*) malloc( m * sizeof(struct node*) )
then
u+i = NULL
(i is any integer) gives error as Lvalue required.
If I use array pointer as
struct node(*p)[];
and then use
(*p)+i = NULL
it gives error as L value required.
*(p+i) = NULL
gives error as
invalid use of array with unspecified bounds
What is the solution?
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node{
int a;
node * link;
};
void print(node *np){
while(np){
printf("%d->", np->a);
np = np->link;
}
printf("NULL\n");
}
int main(){
struct node four = {4, NULL};
struct node three = {3, &four};
struct node two = {2, &three};
struct node **u;
int m = 3;
u = malloc(m * sizeof(struct node*));
u[0] = NULL;
u[1] = &two;
u[2] = &three;
for(int i=0;i<m;++i)
print(u[i]);
free(u);
return 0;
}
I think what you want is:
(*p) += i;
(*p) = NULL;
or
p[i] = NULL;
Here is a working example:
#include <stdio.h>
#include <string.h>
typedef struct s_node {
int x;
struct s_node *next;
} node ;
main()
{
node n[5];
n[2].x = 42;
printf("%d\n", n[2].x);
node *p = n;
printf("%d\n", p[2]);
p += 2;
printf("%d\n", p->x);
}
Output:
42
42
42
Consider to take a look at a tutorial for pointer arithmetic. Just google for it or click the provided link.

Resources