Linked lists in C with chars and integers (troubleshooting) - c

I want to programm a linked list in C, trying to apply everything I've learned so far.
I wrote this program to create a linked list:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node *head = NULL;
//Define struct node
struct node{
char * name;
int num;
struct node * next;
};
//Print List
void printList(){
struct node * temp = head;
while (temp != NULL){
printf("%s", temp->name);
printf("%d", temp->num);
temp = temp->next;
}
}
//Create New Node
struct node * newNode (char * name, int num){
struct node * newNode = (struct node*)malloc(sizeof(struct node));
newNode->name = name;
newNode->num = num;
newNode->next = NULL;
return newNode;
}
//Function to insert and sort Elements
void insertSorted (char * name, int num){
//Empty Liste -> Head is NULL
if (head == NULL){
head = newNode(name, num);
}
else if (strcmp(name, head->name) <=0){
// strcmp-output = -1 ->string 1 > string 2; 0 -> both strings are the same
struct node * temp = newNode(name, num);
temp->next = head;
head = temp;}
struct node * current = head; struct node *prev = NULL;
if (strcmp(name, current->name)>0){ //-> 1, string1 < string 2 ->insert after
while(current != NULL && strcmp(name, current->name)<=0){
prev = current;
current = current->next;
}
struct node * temp = newNode(name, num);
prev->next = temp;
temp->next = current;
}
}
//Test of the linked list
int main()
{
char name; int num;
//Testprogram
printf("Enter a name\n");
scanf("%s", &name);
printf("Enter a number\n");
scanf("%d", &num);
insertSorted(&name, num);
char name2; int num2;
printf("Enter a name\n");
scanf("%s", &name);
printf("Enter a number\n");
scanf("%d", &num2);
insertSorted(&name2, num2);*/
char name3; int num3;
printf("Enter a name\n");
scanf("%s", &name);
printf("Enter a number\n");
scanf("%d", &num3);
insertSorted(&name3, num3);
printList();
return 0;
}
Output example:
Input: Anna 1, Claudio 2, Berta 3
Output: 32Berta1
It somehow...makes the Names vanish and the numbers are in the wrong order too. I'm pretty new to programming, so I have troubles fixing this by myself.
Any help would be hugely appreciated :) Not only to fix the error, but also tips on how to program more...elegantly, so to say.
Thanks :)
//Edit:
Thank you for all the input so far! I messed up the input of the string while testing the program.
As suggested I tried to skip the part with the input, testing the linked list like this in main() (thanks Julien!):
insertSorted("Anna", 1);
insertSorted("Claudio", 2);
insertSorted("Berta", 3);
printList();
it results in the programm not executing and exiting with a negative number error code. Does this point to an infinite loop?

I haven't looked at the linked list details, but one issue I see is that you are using single char variable to store the names (which should be an array or characters). This lack of enough space to store the input make you program have an undefined behaviour after the call to scanf.
As #franji1 stated, try working step by step. If you want to check the code of your list, try testing:
insertSorted("Anna", 1);
insertSorted("Claudio", 2);
insertSorted("Berta", 3);
And check the result is what you expect. Once this is working, add the code asking for input from the user using scanf.

Im not an expert at C but since you mentioned code elegancy I can tell you this. You didn't need to use all these different if statements, you could use the while loop from the begining and insert after you find a name that is bigger than current. This will work even if it has to be inserted before the head node as long as you check that prev is not null. I hope I helped you and that you will find a solution to your problem!

Related

printf segmentation fault and wrong sorted linked list

This is my algorithm for adding nodes to a linked list which is in a sorted way for surnames of persons.
Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Node {
char Name[1024];
char Surname[1024];
char Telno[1024];
struct Node* next;
};
void Add(struct Node** firstnode, struct Node* NewNode)
{
struct Node* tempo;
//printf("%d",strcmp((*firstnode)->Surname,NewNode->Surname));
if (*firstnode == NULL || (strcmp((*firstnode)->Surname,NewNode->Surname) > 0)) {
NewNode->next = *firstnode;
*firstnode = NewNode;
}
else {
tempo = *firstnode;
while (tempo->next != NULL && strcmp(tempo->Surname,NewNode->Surname) < 0) {
tempo = tempo->next;
}
NewNode->next = tempo->next;
tempo->next = NewNode;
}
}
struct Node* CreateNode(char name[1024], char surname[1024], char telno[1024])
{
struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
strcpy(NewNode->Name,name);
strcpy(NewNode->Surname,surname);
strcpy(NewNode->Telno,telno);
NewNode->next = NULL;
return NewNode;
}
void Printlinkedlist(struct Node* head)
{
struct Node* temp = head;
while (temp != NULL) {
printf("%s %s %s\n", temp->Name,temp->Surname,temp->Telno);
temp = temp->next;
}
}
struct Node* head = NULL;
struct Node* temp;
int main()
{
int personcount;
char name[1024],surname[1024],telno[1024];
printf("Please give the count of person:");
scanf("%d", &personcount);
for (int i = 0; i < personcount; i++) {
printf("Please give the name of %d. person:", i + 1);
scanf(" %s", &name);
printf("Please give the surname of %d. person:", i + 1);
scanf(" %s", &surname);
printf("Please give the phone number of %d. person:", i + 1);
scanf(" %s", &telno);
temp = CreateNode(name,surname,telno);
Add(&head, temp);
}
printf("\n -------------- Linkedlist --------------\n");
Printlinkedlist(head);
return 0;
}
The first problem is this: For example, if I enter people's surnames as G, A, L, E, K (So first person's last name will be "G", second person's last name will be "A" etc..), it gives an incorrectly ordered output.
And the second one is: If I delete the comment line characters behind the printf inside the add function, I get a segmentation fault that I don't understand why
Thanks for the answer.
It should first be said that you could, and should, have figured it out yourself by either:
Debugging the program:
On Linux: How Can I debug a C program on Linux?
On Windows: How do you debug a C program on Windows?
Enabling core dumps and analyzing the core file you get when your program crashes; see this explanation.
But, more to the point, let's have a look at (some of) your code:
if (*firstnode == NULL || /* another condition */) {
// do stuff
}
else {
// so *firstnode may be NULL here
tempo = *firstnode;
while (tempo->next != /* some value */ && /* another condition*/ ) {
// do stuff
}
// do stuff
}
See the problem? tempo could get assigned a NULL point, and then de-referenced to get to the next field. That would likely cause a segmentation fault.

What does the -> operator do in C? [duplicate]

This question already has an answer here:
What does this mean "->"?
(1 answer)
Closed 6 years ago.
I have to learn this by 10 am tomorrow for a final because I'm a procrastinator.
I know can all scold me if you like. What I have here is I have to understand pointers to understand linked lists and the one thing that boggles my mind when working with pointers is when -> is used.
From what I've googled, it changes what a variable points to?
This confuses me when there are lines in the example code my professor gave me, such as temp = temp->head in this code or when it states printf("%d", temp->num);
Can anyone please help explain this? Thank you in advance.
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
struct node
{
int num;
struct node *ptr;
};
typedef struct node NODE;
int main()
{
NODE *head, *temp = 0, *first;
int count = 0;
int choice = 1;
while(choice)
{
head = (NODE *)malloc(sizeof(NODE));
printf("Enter the value: \n");
scanf("%d", &head->num);
if (first != 0)
{
temp->ptr = head;
temp = head;
}
else
first = temp = head;
fflush(stdin);
printf("Do you want to continue?");
scanf("%d", &choice);
}
temp->ptr = 0;
temp = first;
printf("\nStatus of the linked list");
while (temp != 0)
{
printf("%d->" temp->num);
count++;
temp = temp->ptr;
}
printf("NULL\n");
printf("Number of entries in linked list %d", count);
return 0;
}
}
It dereferences a pointer to a structure, and access a member of the structure.
Take for example, from your code:
temp->ptr = head;
This is the same as
(*temp).ptr = head;
The "arrow" operator make it a little simpler.
There is some history behind the -> operator if you're curious.

Segmentation Fault when using Linked Lists and Char arrays

I'm struggling through my programming homework and need a hand with Linked Lists. Basically we have to create a program that contains certain functions to manage linked lists. Fairly standard. I tried it last week and just couldn't get it. I'm trying to get it working this weekend and was making good progress until I ran into segmentation faults.
struct STUDENT
{
char *FirstName;
char *LastName;
char *PUID;
int age;
struct STUDENT *next;
};
This is the structure I'm trying to use. The first three values are char arrays and the fourth is just a number. Following this I tried to declare a starting and current node globally.
struct STUDENT *head = NULL;
struct STUDENT *curr = NULL;
Following this I have my create node function, which takes a user input and puts it into the list.
void *createListNode()
{
char first[MAXNAME];
char last[MAXNAME];
char ID[MAXID];
char *pfirst;
char *plast;
char *pID;
int tage;
struct STUDENT *temp = (struct STUDENT *) malloc (sizeof(struct STUDENT));
printf("Enter a first name: ");
scanf("%s", first);
pfirst = first;
printf("entered name: %s\n", pfirst);
printf("Enter a last name: ");
scanf("%s", last);
plast = last;
printf("entered name: %s\n", plast);
printf("Enter the Purdue ID: ");
scanf("%s", ID);
pID = ID;
printf("ID: %s\n", pID);
printf("Enter an age: ");
scanf("%d", &tage);
printf("age: %d\n", tage);
temp->FirstName = strdup(first);
printf("first\n");
temp->LastName = strdup(last);
printf("last\n");
temp->PUID = strdup(ID);
printf("id\n");
temp->age = tage;
printf("age\n");
temp->next = NULL;
printf("next\n");
if (curr == NULL)
{
printf("inside if\n");
head->next = temp; //-------SEGMENTATION FAULT---------------------
printf("line 107\n");
head = curr = temp;
printf("line 109\n");
}
else
{
curr = temp;
}
}
Background of what I'm done up to this point:
I was getting segmentation faults when I tried to assign my arrays to my 'temp' node, but by using malloc on it I solved that problem. Using print statements, I've tracked the problem to the indicated line. When I try to run the code, I get a segmentation fault. I tried the same malloc code above on the 'head' and 'curr' nodes, but that gave me:
carlton#carlton-Inspiron-N7010:~/CNIT315$ gcc lab5.c
lab5.c:20:64: error: invalid initializer
struct STUDENT head = (struct STUDENT *) malloc (sizeof(struct STUDENT));
This is where I believe the problem is, but I've been searching and experimenting for several hours and haven't gotten anywhere. And I just realized this is now a very long post. Thanks for reading it through and I appreciate any push in the right direction!
You initialize head to NULL. You can't dereference head before assigning a valid pointer to it. head->next = temp; gives you a segfault because head is a null pointer.
Thus, you need to review this part of the code:
if (curr == NULL)
{
printf("inside if\n");
head->next = temp; //-------SEGMENTATION FAULT---------------------
printf("line 107\n");
head = curr = temp;
printf("line 109\n");
} else
{
curr = temp;
}
Since it seems like you want to insert at the end of the list, I would suggest something like this:
temp->next = NULL;
if (head == NULL) {
curr = head = temp;
} else {
curr->next = temp;
curr = temp;
}
This makes curr always point to the last node, and head always points to the beginning of the list.
Am I wrong or do you set head->next = temp; but never set head to a valid object before?
You either have to initialize head with an 'empty' Student at the beginning or you just have to set head = temp;
Assuming that you've defined the head variable outside the createListNode() function, here's the problem:
Memory is never assigned to it, since you have never called malloc()

Linked List Appcrash

I was trying to do an example about linked list. First, I added the values to the variables and there was no problem. But when I tried to get values from user, the program crashed when entering midterm 2 grade. I tried other input functions but the result is same. Where is the problem?
#include <stdio.h>
struct student
{
char *name;
int m1,m2,final;
struct student* next;
};
main()
{
addStudent();
system("PAUSE");
}
addStudent()
{
struct student *node = NULL;
struct student *firstnode;
firstnode = (struct student *)malloc(sizeof(struct student));
node = firstnode;
printf("press 0 to exit \n");
while(1)
{
printf("Student name: ");
scanf("%s", node->name)
if(node->name == "0") break;
printf("Midterm 1: ");
scanf("%d", node->m1);
printf("Midterm 2: ");
scanf("%d", node->m2);
printf("Final: ");
scanf("%d", node->final);
node->next = (struct student *)malloc(sizeof(struct student));
node = node->next;
}
node->next = NULL;
node = firstnode;
while(node->next);
while(node->next != NULL)
{
printf("%s - ",node->name);
printf("%d ", node->m1);
printf("%d ", node->m2);
printf("%d ", node->final);
node = node->next;
}
system("PAUSE");
return 0;
}
Fix 1
Remove the line
while(node->next);
Reason: It will put you on an infinite loop in most cases and it is unnecessary.
Fix 2
Replace the loop
while(node->next != NULL) {
}
with
if (node->next != NULL) {
while (node->next->next != NULL) {
}
}
Reason: You are allocating one additional struct each time and keeping it empty for reading next time. So the Linked List will end before the next becomes NULL.
Fix 3
Replace following in struct
char *name;
with
char name[80];
Reason: Memory not being allocated.
Fix 4
Replace at all occurrences of scanf (except for name)
scanf("%d", node->m1);
with
scanf("%d", &node->m1);
Reason: scanf needs memory location of data to be read.
Good luck
Your code has multiple errors.
To start with, the first scanf("%s", node->name) is missing its terminating semicolon.
Next, your function signatures are sloppy. main() should be int main(void). addStudent() should be int addStudent(void). (Or, get rid of its return 0 and let it return void.) Since you don't pre-declare addStudent(), you should define it before main() so that main() can know about it.
The crash, though, is because you haven't allocated memory for node->name. You've allocated memory for a node, but that doesn't give you space to put the name.

malloc() causing EXC_BAD_ACCESS error in Xcode

I am trying to implement the Linked List data structure for my college course, but on executing the code the following line produces an EXC_BAD_ACCESS(code=1, address=0x8) error.
temp->next = (ptrtonode) malloc(sizeof(struct node));
Following is the code in its entirety.
#include <stdio.h>
#include <stdlib.h>
typedef struct node *ptrtonode;
typedef ptrtonode header;
struct node
{
int data;
ptrtonode next;
};
ptrtonode create(int n)
{
int i;
header temphead = NULL;
ptrtonode temp = temphead;
for(i=0;i<n;i++)
{
temp->next = (ptrtonode) malloc(sizeof(struct node));
printf("Enter data for node %d: ", i+1);
scanf("%d", &temp->next->data);
temp = temp->next;
}
temp->next = NULL;
return temphead;
}
int main(int argc, const char * argv[])
{
header head;
int n;
printf("How many nodes do you wish to create?");
scanf("%d", &n);
head = create(n);
}
Any help would be appreciated.
Thanks all!
On first iteration of the for loop inside the create() function temp is NULL, which is then dereferenced causing the failure (not malloc() causing the failure). You will need to restructure the code slightly to prevent dereferencing a NULL pointer.
Other points:
casting the return value of malloc() is not required.
check the result of scanf() to ensure n was assigned a valid integer (and confirm that the int is positive):
/* scanf() returns the number of assignments made,
which in this case should be 1. */
if (1 == scanf("%d", &n) && n > 0)
{
/* 'n' assigned a sensible value. */
}

Resources