wrong result of total nodes in C - c

I have the following program which creates a simple linked list of chars.
typedef struct letter{
char c;
struct letter *next;
}letter;
int count(letter *c){
int n = 0;
letter *t = c;
while(t){
n++;
t = t->next;
}
t = NULL;
return n;
}
int main(){
letter *head = (letter*)malloc(sizeof(letter));
letter *cur = head;
int n;
printf("Give me a number:");
scanf("%d",&n);
while(n > 0){
printf("Give me a char:");
scanf(" %c",&cur->c);
cur->next = (letter*)malloc(sizeof(letter));
cur=cur->next;
cur->next = NULL;
printf("Give me a number:");
scanf("%d",&n);
}
cur = head;
printf("Total nodes: %d",count(head));
system("pause");
return 0;
}
I am filling the list with characters until the user presses 0.The problem is that when I try to output the total number of nodes using count() function I get wrong result.For example consider the following input:
1
a
2
b
3
c
0
the result is:
Total nodes:4
which is wrong. It should be Total nodes:3
Can you explain why this is happening?

When you create the list you also create the first node, but you never assign its char a value.
I have two suggestions on how to fix your problem:
Don't count the first node. Always skip it when retrieving values or counting list length. This is slightly easier to implement, IMO.
or
Let the head point to NULL when the list is empty. Not that this solution means that the head pointer changes it's value when you insert the first element, so you need to pass the list pointer by reference to your insert/delete functions.

cur->next = (letter*)malloc(sizeof(letter));
cur=cur->next;
cur->next = NULL;
This code will create a node every time loop executes, so after 3rd char entry, node will be created without containing any value.
so in count loop it will result in 4 nodes.
Modified Loop: Run and check
while(n > 0){
printf("Give me a char:");
scanf(" %c",&cur->c);
cur->next = NULL;
printf("Give me a number:");
scanf("%d",&n);
if(n > 0)
{
cur->next = (letter*)malloc(sizeof(letter));
cur=cur->next;
}
}

Related

Linked list in C is not printing

I think it is not printing because I am not inserting into the list correctly. I see most people allocate space outside of the loop, but I am not sure that is the case.
#include <stdio.h>
#include <stdlib.h>
typedef struct intList {
int number;
struct intList *next;
} INT_LIST;
int main() {
INT_LIST *start = NULL, *temp;
INT_LIST *trvPtr = start;
/* Insert into list */
while (temp->number != 0) {
temp = malloc(sizeof(INT_LIST));
printf("Enter your integer: ");
scanf("%d", &(temp->number));
temp->next = start;
start = temp;
}
printf("List is: \n");
while (trvPtr != NULL) {
printf("%d", trvPtr->number);
trvPtr = trvPtr->next;
}
return 0;
}
temp is uninitialized and points to garbage. Checking temp->number != 0 is undefined behavior.
You can solve this with a do/while loop. The loop will always run once. Allocate temp, set it, then check.
INT_LIST *start = NULL, *temp;
do {
temp = malloc(sizeof(INT_LIST));
printf("Enter your integer: ");
scanf("%d", &(temp->number));
temp->next = start;
start = temp;
} while(temp->number != 0);
Note that your list will always start with a value of 0. To avoid this, check the input before doing anything else. Use while(1) for an infinite loop and use break to end the loop.
INT_LIST *start = NULL;
while(1) {
int input;
printf("Enter your integer: ");
scanf("%d", &input);
if(input == 0) {
break;
}
INT_LIST *temp = malloc(sizeof(INT_LIST));
temp->number = input;
temp->next = start;
start = temp;
}
When you print, trvPtr will always be NULL; it will not track changes to start. You have to assign it to the new value of start.
printf("List is: ");
INT_LIST *trvPtr = start;
while (trvPtr != NULL) {
printf("%d ", trvPtr->number);
trvPtr = trvPtr->next;
}
puts("");
Note that you're not limited to declaring all the variables at the start of the function.
I have made some modifications/corrections in your code and the following should work -
Correct Code -
#include <stdio.h>
#include <stdlib.h>
typedef struct intList {
int number;
struct intList *next;
} INT_LIST;
int main() {
INT_LIST *start = NULL, *temp;
temp = (INT_LIST*)malloc(sizeof(INT_LIST));
INT_LIST *trvPtr = temp;
/* Insert into list */
do {
printf("Enter your integer: ");
scanf("%d", &(temp->number));
start = temp;
temp->next = (INT_LIST*)malloc(sizeof(INT_LIST));
temp = temp->next;
}while (start->number != 0);
temp->next=NULL;
printf("List is: \n");
while (trvPtr->next != NULL) {
printf("%d", trvPtr->number);
trvPtr = trvPtr->next;
}
return 0;
}
SAMPLE OUTPUT :
Enter your integer: 1
Enter your integer: 2
Enter your integer: 3
Enter your integer: 0
List is:
1230
If you don't want the 0 to be printed, include temp = start, right after the first while loop ends.
Explanation :
Firstly, in your code, you hadn't assigned temp anything. It should have been allocated space and assigned something first or else the statement temp->number != 0 is just undefined behavior.
Nextly, I have used start to check for the last value entered by the user. If it is 0, the loop will break. Do note I have converted the loop into do-while loop, since start is NULL at the beginning.
Lastly, once the loop ends, I have set the next of temp to null so that the printing loop will execute correctly. In your code, this part also had a mistake since you had assigned NULL to trvPtr but never changed the value. So, in your case, the loop would never have executed.
NOTE : It's always better to mention the cast-type explicitly while using malloc. Some compiler would give warnings/errors. So, I have modified that as well wherever you have used malloc()

Linked lists in C with chars and integers (troubleshooting)

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!

weird number appears on output-C

I have made a simple list like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
struct node{
int am;
struct node *next;
};
typedef struct node node;
int main(){
int n;
node *head=(node *)malloc(sizeof(node));
node *cur=head;
printf("Give me a number:\n");
scanf(" %d",head->am);
cur=head;
while(1){
printf("Give me a number\n");
scanf(" %d",&n);
if(n==0)
break;
cur->am=n;
cur->next=(node *)malloc(sizeof(node));
cur=cur->next;
cur->next=null;
}
travel(head);
printf("Total nodes available :%d\n",count(head));
system("pause");
return 0;
}
Now travel is supposed to go through each node in the list and display the integer saved in each node.
void travel(node *h){
if(h==NULL)
return;
printf("Received data from node: \t %d\n",h->am);
travel(h->next);
}
Now the problem is that when travel is called it wont print the integer from the first node.It will also print another "Received data from node:" followed by a strange number.
For example
If i give 1,2,3,4 as inputs these are the results
Received data from node: 2
Received data from node: 3
Received data from node: 4
Received data from node: 4026432
Any ideas?
Now the problem is that when travel is called it wont print the
integer from the first node
This can be precisely known from this part of the main() function
printf("Give me a number:\n");
scanf(" %d",head->am); //this is wrong use of scanf("%d",&head->am);
cur=head;
while(1){
printf("Give me a number\n");
scanf(" %d",&n);
if(n==0)
break;
cur->am=n;
as I've mentioned you're scanning wrongly but that doesn't matter because later in the code in while loop you replace it this way...
you scan number and store it at head->am
then you assign head to cur so head->am and cur->am are both the same now... so in while loop when you first assign n to cur->am, it gets assigned to head->am. so this explains why you never get to print first node.
Solution:
to overcome it ... in while loop, before assigning cur->am=n try doing:
cur->next=(node *)malloc(sizeof(node));
cur=cur->next;
//then... assign
curr->am=n;
this way you'll not lose first node.
suggestion:
As someone has already said it's much easier to traverse/ travel the list using loops (never mind... if you want to do it recursively)
here's how you do it with the loops:
void travel(node *h)
{
if(h==NULL)
return; //list is empty,consider printing "list empty" :)
while(h!=NULL)
{
printf("Received data from node: \t %d\n",h->am);
h=h->next;
}
}
To put all together your code without changing the travel() function as suggested would be:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int am;
struct node *next;
};
typedef struct node node;
void travel(node *h);
int main() //I have a habit of returning values from main() :)
{
int n;
node *head=(node *)malloc(sizeof(node));
node *cur=head;
printf("Give me a number:\n");
scanf(" %d",&head->am);
cur=head;
while(1)
{
printf("Give me a number\n");
scanf(" %d",&n);
if(n==0)
break;
cur->next=(node *)malloc(sizeof(node));
cur=cur->next;
cur->am=n; //NOTE:here's the change!
cur->next=NULL;
}
travel(head);
return 0; //just to signify successful compilation
}
void travel(node *h)
{
if(h==NULL)
return;
printf("Received data from node: \t %d\n",h->am);
travel(h->next);
}
Sample Input : 5 6 3 1 0
Sample Output :
Give me a number:
5
Give me a number
6
Give me a number
3
Give me a number
1
Give me a number
0
Received data from node: 5
Received data from node: 6
Received data from node: 3
Received data from node: 1
There are (at least) those issues:
The line scanf(" %d",head->am) is wrong since scanf() expects an address of the memory location of the expected value meaning &head->am.
Your loop scans a number and puts it in the current node and only after it creates a new node. Therefore, the first number you enter will be overridden (after fixing the first issue) and the last node created will contain random data because the loop will terminate after entering 0 but before putting anything in the last node.
I propose like this:
int main(void){
int n;
node anchor = {0, NULL};//dummy head
node *head, *cur = &anchor;
while(1){
printf("Give me a number\n");
scanf("%d", &n);
if(n==0)
break;
cur->next = malloc(sizeof(node));
cur = cur->next;
cur->am = n;
cur->next = NULL;
}
head = anchor.next;
travel(head);
printf("Total nodes available :%d\n", count(head));
return 0;
}
You are missing & at the first scanf:
scanf(" %d", &head->am);
But it could be made to do all the scanf inside the while:
int main(){
node *head=0;
node *cur=0;
node *prev=0;
while(1){
prev = cur;
cur=(node *)malloc(sizeof(node));
cur->next=NULL;
printf("Give me a number\n");
scanf("%d",&cur->am);
if(cur->am==0)
break;
if(head == NULL) head = cur;
if(prev != NULL) prev->next = cur;
}
travel(head);
printf("Total nodes available :%d\n",count(head));
return 0;
}
I hope I didnt make any mistake as I wrote it in this SO editor..
and as someone said, you should free the linked list .. but thats out of scope here..
HTH

Inserting element in linked list after the biggest element in the list

I've been smashing my head here to see if I could find a solution but after few infinite loops, here's the code I'd like to be reviewed:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_STRING 100
typedef struct Node {
char val;
struct Node *next;
} node;
node *create_list(char *list_string) {
node *momentary=NULL, *new=NULL, *head;
int i;
for(i=0; i<strlen(list_string); i++) {
new = (node *)malloc(sizeof(node));
new->val = list_string[i];
new->next = NULL;
if (!momentary) head = new;
else momentary->next = new;
momentary = new;
}
return head;
}
int print_list(node *head) {
node *momentary;
if(!head) return -1;
for(momentary=head; momentary!=NULL; momentary=momentary->next)
printf("%c ", momentary->val);
printf("\n");
return 0;
}
node *find_biggest(node *head) {
node *momentary=NULL, *biggest=head;
if (head==NULL) return NULL;
for (momentary=head; momentary!=NULL; momentary=momentary->next) {
if (momentary->val > biggest->val) biggest = momentary;
}
return biggest;
}
void insert_after_biggest(node **head, node **biggest, char val) {
node *p = *head, *temp=NULL;
*head = p->next;
if(*head!=NULL){
if(p->val==(*biggest)->val){
temp=p;
p->next=temp;
p->val=temp->val;
p->next=NULL;
*biggest=p;
p->next=(*biggest);
p->val=(*biggest)->val;
//*biggest=p;
p->next=NULL;
//temp=p;
p->next=temp;
p->val=temp->val;
}
else if(p->val<(*biggest)->val){
*head = p->next;
}
}
}
int main () {
node *head=NULL, *biggest=NULL;
int menu_choice;
char c, val, list_string[MAX_TREE_STRING];
setbuf(stdout, NULL);
do {
menu_choice = 0;
printf("\n1 Create list \n2 Print");
printf("\n3 Insert after biggest");
printf("\n4 exit\n");
scanf("%d", &menu_choice);
switch (menu_choice) {
case 1:
if (head) {
printf("List exist.\n");
break;
}
printf("Enter list as digits without spaces: ");
scanf(" %s", list_string);
head = create_list(list_string);
break;
case 2:
print_list(head);
break;
case 3:
scanf(" %c", &val);
insert_after_biggest(&head, &biggest, val);
break;
case 4:
break;
default:
while((c=getchar())!='\n' && c!=EOF);
}
} while(menu_choice!=4);
return 0;
}
Now the task here is:
Write a function "insert_after_biggest" so that the new elements are
put behind the element with the highest value and complexity of the
function must be O (1). In other words, the function "find_biggest"
that has complexity of O (n) can be called only if the "biggest" has
not yet been defined. If the list has no elements , it still needs to
be first.
Here's a console example to have clearer picture:
1|<-Insert into linked list option|
Enter list as digits without spaces: 683 |<-Prompt and entered value|
3 |<-Option(the function)|
2 |<-Number to be inserted|
2 |<-Print option|
6 8 2 3|<-Output|
3 |<-Option|
8 |<-Number to be inserted|
2 |<-Print option|
8 |<-Output|
I've been typing this code myself and I have no idea anymore how to look at this.
I would humbly ask if someone can help me to solve this, the code compiles but executing the option 3 in the console only makes it run in infinite loop, resulting in crashing the console.
The specific: how to solve it (step by step) and how it should look like(the done code, possibly included here?).
Thank you.
If you can assume that
1) You don't need to remove elements
You merely need to keep an extra pointer that points to the node with the largest value at all times. It's nice that you are allowed to scan the list for the largest if you've never called
insert_after_biggest, but that's not even necessary. Call that node max, and the pointer to max p_max.
For each insertion
a) The value you're about to insert is larger than the value held by max, in which case you insert the new value, and change p_max = p_new.
n_new->next = p_max;
p_max = p_new;
b) The value you're about to insert is larger than the value held buy max, in which case simply insert and leave p_max unchanged.
For insert_after_max
you explicitly do
p_new->next = p_max->next;
p_max->next = p_new;
Or if the new value is larger then do as described above.
Since you don't have to scan the list to insert, the complexity of insertion is O(1)

linked list creation run-time error

When I'm running the following C program for linked list creation in gcc compiler in ubuntu 13.04, I'm getting a message of : Segmentation fault (core dumped) , after the list elements are input from the user , without proceeding further. Kindly help.
#include<stdio.h>
#include<stdlib.h>
int main()
{
/* creating a singly linked list,displaying its elements and finding the sum and average of its elements and searching a particular element in it */
typedef struct node
{
int info;
struct node *next;
}N;
N *ptr,*start,*prev;
int i,n,x;
ptr=NULL;
start=NULL;
prev=NULL;
printf("Enter the number of list elements: ");
scanf("%d",&n);
prev = (N*)malloc(sizeof(N));
start = (N*)malloc(sizeof(N));
for(i=0;i<n;i++)
{
ptr= (N*)malloc(sizeof(N));
prev->next = ptr;
printf("enter the %dth element\t\n",(i+1));
scanf("%d",&x);
ptr->info = x;
if(start==NULL)
{
start=ptr;
prev=ptr;
ptr->next = NULL;
}
else
{
prev=ptr;
}
} /* linked list created consisting of n nodes */
/* finding sum and average*/
int sum=0;
float avg;
ptr=start;
for(i=0;i<n;i++)
{
sum =sum + ptr->info;
ptr = ptr->next;
}
avg = (float)sum/n; /* summing and averaging completed */
/* displaying data */
ptr=start;
printf("\n The list elements are : ");
while(ptr != NULL)
printf("%d\t",ptr->info);
printf("\n");
printf("The sum of list elements is: %d",sum);
printf("The average of list elements is: %f",avg);
return 0;
}
Looks like you meant to do
start = NULL;
prev = NULL;
at the beginning, and also correct -
prev->next = ptr;
to
if (prev != NULL)
prev->next = ptr;
or move it to the else section (before prev = ptr).
This way, the first iteration would make start point to the first element, and the next ones would make the prev element point to the current ptr.
By the way, some linked lists hold a dummy "anchor" element for simpler maintenance, but in your case I see you expect the data to appear from the first element already.
when I strip your code I come to this Seltsamkeit:
start = (N*)malloc(sizeof(N));
for(i=0;i<n;i++) {
if(start==NULL)
start can never be NULL in this context
i normally use "head" and "next" for the pointer to the working memory, and "list" as a running pointer to the last element of the list for the really allocated memory-linked-list. the metacode is:
list = NULL;
head = NULL;
for (i = 0; i < n; i++) {
next = malloc();
if (head == NULL) {
head = next; // setting the first haed;
} else {
list->next = next; // attaching to the end
}
list = next; // pointing to the last element
}

Resources