Issue when printing Linked List - c

I am trying to create a linked list of 5 nodes and print them. I don't know why I cannot see the result when printing the linked list even though I do not get errors and I am sure my structure is fine. I only see blank screen. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct msg *M;
struct msg{
double id;
M next;
};
M queue;
void new_msg(double id);
void printList();
void main()
{
double r;
srand(0);
for(int i=0;i<5;i++){
r = rand() % 100;
new_msg(r);
}
printList(); // PRINT DOES NOT SHOW RESULTS :(
}
void printList()
{
M temp;
while (temp->next != NULL){
temp = temp->next;
printf("MSG ID:%6.3f \n", temp->id);
}
}
void new_msg(double id)
{
M m;
if(queue == NULL)
{
m = malloc(sizeof(struct msg));
}
else
{
m= queue;
queue = queue->next;
}
m->id = id;
m->next = NULL;
}

The both functions are invalid and have undefined behaviour at least because in the both functions there is an attempt to write to or read from a non-allocated memory.
Try the following
void printList()
{
for ( M temp = queue; temp != NULL; temp = temp->next; )
{
printf("MSG ID:%6.3f \n", temp->id);
}
}
void new_msg(double id)
{
M m = malloc( sizeof( struct msg ) );
if ( m != NULL)
{
m->id = id;
m->next = queue;
queue = m;
}
}
Take into account that though some compilers allow to use the main declaration with the return type void nevertheless such a declaration is not C compliant.
You should write
int main( void )

The problem is, inside new_msg() function, you define a local variable m, which is never stored and the global queue never gets updated. In every call, queue gets equal to NULL.
Next, in your printList() function,
temp is unitialized
while (temp->next != NULL) is likely to evaluate to false in very first iteration.

Assuming new_msg is correct, you are printing a list of pointers into nothingness, probably resulting in a core dump.
Your M temp; is not initialized. You probably want:
M temp = queue;

Related

What is wrong with my linked list, and why won't it properly set my head to NULL in C?

This is my program I have written in C, I created a structure and a head and I am trying to make a linked list, but I keep getting read access violations and it seems I am not passing in my head pointer properly and it keeps having problems when it is trying to add to my list.
#define _CRT_SECURE_NO_WARNINGS // Since I want to strictly use ANSI C and not Microsoft C without getting the warning message, I'm adding this line of code before I include header files.
#include <stdio.h> // "#include" includes the contents of another file, commonly called header file, into the source code file.
#include <string.h> // This library contains a variety of functions to manipulate strings.
#include <stdlib.h> // Header file which has the necessary information to include the input/output related functions in our program.
#define MAX 100
typedef struct node {
char model[MAX];
float price;
int miles;
struct node *next;
} *NODEPTR;
NODEPTR getNode();
void freeNode(NODEPTR p);
void printTotalMiles(NODEPTR);
void addLast(NODEPTR *list, char c[], float pri, int num);
int main(void) { //It is the first function of every C program that is responsible for starting the execution and termination of the program.
int i = 0;
NODEPTR head = NULL;
if (head == NULL) {
printf("NULL");
}
//head = (NODEPTR) malloc(sizeof(struct node));
//head->next = NULL;
//addFront(head, 2600.00, 48000);
//addFront(head, 1400.00, 22000);
//printf("first, %d", head->price);
addLast(head, "64 Impala", 1800.00, 12000);
addLast(head, "56 Ford", 500.00, 23000);
//printTotalMiles(head);
//printArray(p);
return 0; // This statement indicates "main()" is returning the value 0 upon completion.
} // Curly brace marks the end of the function.
NODEPTR getNode(void) {
NODEPTR p;
p = (NODEPTR)malloc(sizeof(struct node));
if (p == NULL) {
printf("List Overflow.");
}
return (p);
}
void freeNode(NODEPTR p) {
free(p);
}
void addFront(NODEPTR *list, float pri, int num) {
NODEPTR p, q;
p = getNode();
//strcpy(p->model, c);
// memset(p->model, '\0', sizeof(c))
//printf("%s\n", p->model);
p->price = pri;
p->miles = num;
p->next = *list;
*list = p;
q = *list;
printf("hey %.2f hey\n", q->price);
}
void printTotalMiles(NODEPTR *list) {
int total = 0;
NODEPTR p;
while (*list) {
p = *list;
printf(" Car: \tPrice: %.2f\tI drove it: %d\n", p->price, p->miles);
total += p->miles;
list = p->next;
}
printf("The Total Miles: %d", total);
}
void addLast(NODEPTR *list, char c[], float pri, int num) {
NODEPTR p, q;
p = getNode();
memset(p->model, '\0', sizeof(c));
strcpy(p->model, c);
p->price = pri;
p->miles = num;
p->next = NULL;
if (*list == NULL) {
*list = p;
} else {
q = *list;
while (q->next) {
q = q->next;
}
q->next = p;
}
}
//void printArray(struct node cars[]) { //function definition
// break;
//}
How can I get it so I can properly add nodes to this list?
I just want it to add nodes to the list with the character, float and int. I tried messing with the pointers, I tried setting head first and setting head->next to null as well but nothing seems to work. It keeps having errors every time it tries to deal with the null.
void addLast(NODEPTR* list, char c[], float pri, int num);
addLast wants a pointer to pointer (read Is it a good idea to typedef pointers?), but you pass a single pointer here:
addLast(head, "64 Impala", 1800.00, 12000);
addLast(head, "56 Ford", 500.00, 23000);
switch to
addLast(&head, "64 Impala", 1800.00, 12000);
addLast(&head, "56 Ford", 500.00, 23000);
And here:
void addLast(NODEPTR* list, char c[], float pri, int num) {
NODEPTR p, q;
p = getNode();
memset(p->model, '\0', sizeof(c));
strcpy(p->model, c);
sizeof(c) is the size of a pointer (read What is ‘array decaying’ in C?).
Use the size of the member, in this case MAX:
memset(p->model, '\0', MAX);
or better yet: delete the whole line, you don't need it if you call strcpy on the next line.
One more:
void printTotalMiles(NODEPTR* list) {
differs from the propotype:
void printTotalMiles(NODEPTR);
Compile with warnings.

Why the program crased even thoungh I got the correct result?

I am learning the data structure of LinkList, and I have already implemented the source code that works for me. Today I try to do it in another way like below. And I am confusing why the programe will be crashed even though I get the result I want.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define OK 1
#define ERROR 0
typedef int ElemType;
typedef int Status;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode, LinkList; //I don't use the *LinkList on purpose to check it out
//Initialize LinkList: Create a head node
Status InitList(LinkList *L)
{
L = malloc(sizeof(LinkList));
if(!L) return ERROR;
L->next = NULL;
return OK;
}
//CreateList
Status CreateListHead(LinkList *L, int n)
{
LinkList *s;
int i;
if(n < 1) return ERROR;
InitList(L);
srand(time(0));
for(i=0; i<n; i++)
{
s = malloc(sizeof(LinkList));
if(!s) return ERROR;
s->data = rand()%10+1;
s->next = L->next;
L->next = s;
}
return OK;
}
//Travese LinkList
void Traverse(LinkList *L)
{
while(L->next)
{
printf("%d ", L->next->data);
L->next = L->next->next;
}
}
int main()
{
LinkList *L;
int s;
s = InitList(L);
if(s) printf("Successful!");
else printf("Failed!");
CreateListHead(L, 10);
Traverse(L);
return 0;
}
And the result is: Succesful! 1 6 4 6 1 1 8 2 8 2
And then the program crashed
The problem here is, whatever memory you allocate to L inside InitList(), is not going to be reflected back to the actual argument passed to the function when being called.
So, in your code
if(n < 1) return ERROR;
InitList(L); ----------------(1)
srand(time(0));
for(i=0; i<n; i++)
{
s = malloc(sizeof(LinkList));
if(!s) return ERROR;
s->data = rand()%10+1;
s->next = L->next; -------------------(2)
L->next = s;
}
at point (2), L is still uninitialized. Accessing that will invoke undefined behaviour.
C uses pass-by-value, so if you have to modify the argument itself, you need to pass a pointer to that. Something like
InitList(&L);
and then,
Status InitList(LinkList **L)
{
*L = malloc(sizeof(**L));
if(!*L) return ERROR;
(*L)->next = NULL;
return OK;
}
should do the job.
Problem is InitList initializes a local copy of L, but not the L that is in your main function. Change it to InitList(LinkList **L) and call as InitList(&L);, and change your implementation accordingly.
I am actually pretty surprised that it happens to work on your machine in the first place. (It's what's technically known as undefined behaviour and can manifest itself in a variety of ways, including no visible symptomps.)
Anyway, one immediate issue is in InitList: when you set L there, the newly allocated pointer does not propagate back the caller. For that you need to turn it into a pointer to pointer:
Status InitList(LinkList **L)
{
*L = malloc(sizeof(LinkList));
if(!*L) return ERROR;
(*L)->next = NULL;
return OK;
}
You'll then need to call it like so:
InitList(&L);

Address of a node in linked list changes automatically in c

I am learning pointers in c and wrote a program which inserts elements into linked list and prints them in the end.
// this is exercise 2 in chapter 11 on pointers
#include <stdio.h>
#include <stdbool.h>
typedef struct node
{
int value;
struct node * next;
}node;
/**
Insert into linked list
**/
bool insert(node * list, int n);
void printList(node *startNode);
int main(void)
{
node n1,n2;
n1.value = 0;
n2.value = 1;
n1.next = &n2;
n2.next = NULL;
// insert 2 into list
insert(&n1, 2);
// print the updated list
printList(&n1);
printf("Program Executed Successfully \n");
return 0;
}
bool insert(node * list, int n)
{
while(list->next != NULL)
{
if (list->value < n)
{
list = list->next;
}
else
{
node tempNode;
tempNode.value = n;
tempNode.next = list->next;
list->next = &tempNode ;
return true;
}
}
node tempNode;
tempNode.value = n;
tempNode.next = list->next;
list->next = &tempNode ;
return false;
}
void printList(node * startNode)
{
while(startNode->next != NULL)
{
printf("%i\n", startNode->value);
startNode = startNode->next;
}
}
Insertion seems to be fine. I have initially two nodes and then I added one more with a value of 2 but when I print, it just prints the first two elements correctly.
I used GDB debugger and tried to trace where the problem occurs, i saw that when it has printer first and second node, the address of the third node has automatically changed to
0x7ffff7dea560 <_dl_fini>
before at the start of the print function it was
0x7ffffe018
and the output of the complete program is
0
1
-777224576
-443987883
Segmentation fault
The insert function just looks wrong, but the worst offenders are these lines from the function:
else
{
node tempNode;
...
list->next = &tempNode ;
}
Here you declare a local variable `tempNode, and save a pointer to it in the list. The variable will go out of scope and cease to exist once the closing curly brace is reached, leaving you with a stray pointer. Attempting to dereference that stray pointer will lead to undefined behavior.
A little further down you do the same mistake again, saving a pointer to a local variable.

Why does malloc fail to allocate more than once?

I coded a simple source. It contains a queue and some of the function a queue needs but for some reason malloc() only works once.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define QUEUE sizeof(Queue)
Definition of the Node, which is an element of the list, and the queue.
typedef struct node {
char * value;
struct node * next;
} Node;
typedef struct queue {
Node * head;
Node * tail;
} Queue;
int initialization(void ** list, int type){
int code = -1;
//create an empty list.
//if queue dynamically allocate memory and assign NULL to both properties head and tail.
return code;
}
enqueue() add one element in the queue at a time. but for some reason it can only add one element then the program crashes.
int enqueue(Queue * q, char * instruction){
int code = -1;
if(q != NULL){
printf("Prepare to enqueue!\n");
Node * n = NULL;
n = (Node*)malloc(sizeof(Node));
if(n != NULL){
printf("Node created!\n");
strcpy(n->value, instruction);
n->next = NULL;
//if first value
if(q->head == NULL){
q->head = n;
q->tail = n;
printf("Enqueue first Node\n");
}
else {
q->tail->next = n;
q->tail = n;
printf("Enqueue another Node\n");
}
code = 0;
printf("Node \"%s\" Enqueued\n", instruction);
}
}
return code;
}
int dequeue(Queue * q){
int code = -1;
//dequeuing code here.
return code;
}
int isEmpty(void * list, int type){
int code = 0;
//check if the list is empty
return code;
}
the for loop in the main() function never reaches 3
int main(int argc, char * argv[]){
Queue * queue = NULL;
initialization((void*)&queue, QUEUE);
int i = 0;
for(i = 0; i < 3; i++){
if(enqueue(queue, "some value") != 0){
printf("couldn't add more Node\n");
break;
}
}
while(!isEmpty(queue, QUEUE)){
dequeue(queue);
}
return 0;
}
The initialization function is written this way because it should also be able to initialize stacks (I removed the stack code to reduce the source but even without it the bug persist). I also put printfs to debug the code. And I have more than enough memory to make this simple code run how it should.
Thanks in Advance!
Running this, I crash with a segmentation fault, as I'd expect:
n = (Node*)malloc(sizeof(Node));
n is allocated, it's contents uninitialized and effectively random
if(n != NULL){
n is not NULL, so...
strcpy(n->value, instruction);
And we crash.
See the problem? n->value is a pointer to nowhere. Or, to somewhere, but nowhere known. Nowhere good. And we're just dumping a string into that space.
Either change the Node struct so that value is a char [SOME_SIZE], or use strdup() instead of strcpy(), to actually allocate some memory for the poor thing.
n->value = strdup(instruction);

C program not recognizing null pointer

I'm trying to recurvisely implement an insert function in C, but I'm having all sorts of issues. I'm in an intro CS class and they started throwing C labs at us before we had ever worked with it before. Part of the issue is that the list pointer is not being recognized as NULL and I'm also pretty sure that I'm using malloc improperly.
#include <stdio.h>
#include <stdlib.h>
#define True 1
#define False 0
typedef int BOOLEAN;
struct Node{
int value;
struct Node *next;
};
void insert(int x, struct Node **pL){
printf("insert\n");
if(*pL == NULL){
printf("inside if\n");
struct Node *pN;
pN = (struct Node*) malloc(sizeof(struct Node));
(*pN).value = x;
(*pN).next = NULL;
return;
}
if (*pL != NULL){
printf("inside else\n");
insert(x, &(((*pL)->next)));
}
printf("end insert\n");
};
void printList(struct Node *L){
while (L != NULL){
printf("%d", (*L).value);
printList((*L).next);
}
return;
};
main(){
printf("main\n");
struct Node* L;
//L).next = NULL;
int i;
printf("for loop\n");
for (i = 3; i < 20; i+=2){
printf("%d\n", i);
insert(i, &L);
}
printList(L);
};
First of all, in main you need to initialise L:
struct Node* L = NULL;
Second, in insert when you allocate the new node pN, you are not assigning it to the pL, i.e., it doesn't get inserted. Put this right before the return; in insert:
*pL = pN;
(Also you could remove the return and change if (*pL != NULL) into else.)
Then, in printList you are both iterating with a while loop, and with recursion. Choose one, not both, e.g.,:
while (L) {
printf("%d\n", L->value);
L = L->next;
}
Also, throughout your code you can replace (*pointer_to_struct).field with pointer_to_struct->field for better style.

Resources