Segmentation fault but can't find the bug - c

#include<stdio.h>
#include<stdlib.h>
struct node {
char str[200];
int nn;
struct node* next;
};
int number;
struct node* start=NULL;
struct node* current;
//function to insert into the list
void insert() {
struct node* n;
n=(struct node*)malloc(sizeof(struct node));
n->str=malloc(sizeof(char) * 1000);
printf("please enter the data that you would like to insert: ");
gets(n->str);
printf("asdasdasdasd");
n->next=NULL;
if( start==NULL ) {
start->next=n;
current=n;
}
else {
current->next=n;
current=n;
}
printf("done\n");
}
void display() {
current=start;
int i=0;
while( current->next!=NULL ) {
printf("node%d= %s\n",++i,current->str);
current=current->next;
}
printf("this the end");
}
int main() {
char c;
int input;
do {
printf("Select from the following options:\n"
"1.Display list\n"
"2.Add to list\n"
"3.delete from list\n");
scanf("%d",&input);
switch (input) {
case 1: display(); break;
case 2: insert(); break;
// case 3: delete(); break;
default : printf("Please select 1 , 2 or 3\n");
}
printf( "would you like to continue?(y/n)\n");
scanf("%s",&c);
} while(c=='y');
return 0;
}
This is giving me an error in the insert function, A SEGMENTATION FAULT !
I Tried things but I just don't get the clear picture. I am a bit weak with pointers, actually confused !
Please help me out by telling me what I am doing wrong. Forget about my linked list logic, let it be wrong. I just wanna know why a segmentation fault is occurring !

you have many mistakes, but your crash is because you don't allocate start
n->next=NULL;
if( start==NULL ) {
start->next=n;
current=n;
}
else {
current->next=n;
current=n;
you ask if start is null, and if it is you try to read it by calling start->next it. you need to allocate it first.

Since you did not tell us the line in which your segfault happened, I can only guess.
At least these lines sounds bogus to me:
if( start==NULL ) {
start->next=n;
current=n;
}
Are you sure that you want to dereference start when it is NULL? That is what you are doing with start->next. Dereferencing NULL causes a segfault.
Maybe this will work the way you expect it:
if( start==NULL ) {
start=n;
current=n;
}
So basically, if start was not defined yet, define it and it also becomes your current item.

You should use debugger (not us) in order to find more information about the problem.
For example gdb (GNU Debuger).

Compilation Error
n->str=malloc(sizeof(char) * 1000);
and this is address reassign on a constant!!!!!You are changing the address of array???
Dangerous Function with 25% probability to execute.
gets(n->str);
Setting value at null pointer!!!
struct node* start=NULL;....
start->next=n;
Example of working Code
#include<stdio.h>
#include<stdlib.h>
struct node {
char *str;
int nn;
struct node* next;
};
int number;
struct node* start=NULL;
struct node* current;
//function to insert into the list
void insert() {
struct node* n;
n=(struct node*)malloc(sizeof(struct node));
n->str=(char*)malloc(sizeof(char) * 1000);
printf("please enter the data that you would like to insert: ");
scanf("%s",n->str);
printf("asdasdasdasd");
n->next=NULL;
if( start==NULL ) {
//start->next=n;
current=n;
}
else {
current->next=n;
current=n;
}
printf("done\n");
}
void display() {
current=start;
int i=0;
while( current->next!=NULL ) {
printf("node%d= %s\n",++i,current->str);
current=current->next;
}
printf("this the end");
}
int main() {
char c;
int input;
do {
printf("Select from the following options:\n"
"1.Display list\n"
"2.Add to list\n"
"3.delete from list\n"
);
scanf("%d",&input);
switch (input) {
case 1: display(); break;
case 2: insert(); break;
// case 3: delete(); break;
default : printf("Please select 1 , 2 or 3\n");
}
printf( "would you like to continue?(y/n)\n");
scanf("%s",&c);
}while(c=='y');
return 0;
}

if( start==NULL ) {
start->next=n;
current=n;
}
I think you have a little problem here ;-)

the next line is not safe:
scanf("%s",&c);
scanf adds terminating null character '\0' that corrupts stack in your case.

Related

What's the problem in this program of Single Linked list?

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node {
int data;
struct node* nextptr;
} * manode;
void add();
void delete ();
void display();
int main()
{
int choice;
int echoice;
while (choice != 4) {
printf("\n \t ENTER YOUR CHOICE FOR SINGLE LINKED LIST ");
printf("\n \t 1. ADD ELEMENT ");
printf("\n \t 2. DISPLAY ELEMENT ");
printf("\n \t 3. DELETE ELEMENT ");
printf("\n \t 4. EXIT ");
scanf("%d", &choice);
switch (choice) {
case 1:
while (echoice != 0) {
add();
printf("\n DO YOU WANT TO CONTINUE 1/0 ");
scanf("%d", &echoice);
}
break;
case 2:
display();
break;
case 3:
delete ();
break;
case 4:
exit(0);
break;
default:
printf("\n \t WRONG VALUE ENTERED ");
};
}
return 0;
}
#Add function is responsible to add the first node and all the remaining nodes as well.
void add()
{
struct node *tmp, *tmp2;
tmp = malloc(sizeof(struct node));
tmp2 = malloc(sizeof(struct node));
int value;
printf(" ENTER THE VALUE YOU WANT TO ENTER ");
scanf("%d", &value);
if (manode == NULL) {
manode = malloc(sizeof(struct node));
printf(" FIRST ENTRY ");
manode->data = value;
manode->nextptr = NULL;
tmp = manode;
printf("THE DATA %d ", manode->data);
}
else {
if (tmp2 == NULL) {
printf("\n MEMORY ALLOCATION FAILED");
}
else {
tmp2->data = value;
tmp2->nextptr = NULL;
tmp->nextptr = tmp2;
tmp = tmp->nextptr;
}
}
//manode=tmp;
}
void display()
{
struct node* tmp1;
if (manode == NULL) {
printf(" MEMORY ALLOCATION FAILED ");
}
else {
tmp1 = manode;
while (tmp1 != NULL) {
printf("\n%d DATA IS DISPLAY \n", tmp1->data);
tmp1 = tmp1->nextptr;
}
}
}
void delete ()
{
struct node* tmp;
if (manode == NULL) {
printf("NOTHING TO DELETE ");
}
else {
tmp = malloc(sizeof(struct node));
}
}
Kindly copy and compile the code, it's working but it doesn't display the contents in the list. Kindly copy and compile the code, it's working but it doesn't display the contents in the list.Kindly copy and compile the code, it's working but it doesn't display the contents in the list.Kindly copy and compile the code, it's working but it doesn't display the contents in the list.
As I see, there are a number of issues with your code.
do not use conio.h. This thing is from the '80s and adds nothing to a modern program but problems
never try to implement an ADT --- any container such as list, set, map --- as a node. It will only give you trouble: a list is a collection of nodes. Each node has a payload, some data. This data can have a key, something used to compare records. A node is not a list. A node is not the data. A list is not a node. As seen from the list, the data are the nodes. This way you can use anything as data in your list. And this is the purpose of a container: write once, use always. And the list has metadata, some obvious controls such its size, starting addres, ending address and possibly other stuff.
do not use void(). Is a waste, sometimes an error. In your case is an error. All pointers are buried inside the functions and die there. So display() and add() does not work
do not typedef pointers. It is a mess. In you case manode is a pointer. How are someone, even yourself a few days from now, remember what is what? If manode is a typedef for a struct everyone knows that
manode* many_nodes[30]
declare many_nodes as a pointer to an array of structs. The asterisk tells everything: many_nodes is a pointer to manode. BTOS if you bury the * inside the typedef you will always need to refer to the code in the header.
do not mix code of the list with I/O. It will only make your like harder. You have a list of simple int, so declare add() for instance as int add(int item, List* the_list). This way is more readable and you can write a simple loop to fill the list with a few hundred or just one node and start testing.
if you have a menu just write it as a function that returns the user option. But add it later to the program. A menu serves nothing to the list and to the program
scanf() was not written to read input from the keyboard. It is for scan formatted input, hence the name. It will always give you trouble when reading from stdin. But do your part and at least always test the return of scanf(). ALWAYS. rtfm.
do not write \n \t on a printf. Use just tabs or count the spaces.
always initialize all variables. In your code you start testing choice and echoice with no value set.
what is the point of having a loop on option 1, add since anyway the user will need to input an answer and enter 1?
Back to your program
See below your code rearranged using some of the things I wrote above. Compare with your code
Sample Code
#include <stdio.h>
#include <stdlib.h>
typedef struct st_node
{
int data;
struct st_node* nextptr;
} Node;
typedef struct tlist
{
unsigned size;
Node* start;
} List;
int add(int, List*);
int delete (int, List*);
int display(List*);
int menu();
int main(void)
{
List one;
one.size = 0;
one.start = NULL;
int res = menu();
printf("menu returned %d\n", res);
display(&one);
for( int i = 0; i<10; i+=1)
add(i,&one);
display(&one);
return 0;
}
int add(int value, List* l)
{
if ( l == NULL ) return -1;
Node* node = (Node*) malloc(sizeof(Node));
// simplest: insert at the beginning
node->nextptr = l->start;
node->data = value;
l->start = node;
l->size += 1;
return l->size;
};
int display(List* l)
{
if ( l== NULL) return -1;
if ( l->size == 0 )
{
printf("\n\tlist is empty\n\n");
return 0;
}
else
{
printf("\n\t%d elements in the list\n\n", l->size);
};
Node* p = l->start;
for( unsigned i = 0; i< l->size; i+=1)
{
printf("%3d: %11d\n", 1+i, p->data);
p = p->nextptr;
};
return l->size;
}
int delete (int v, List* l)
{
return 0;
}
int menu()
{
int choice = 0;
int res = 0;
printf(
"\n\tENTER YOUR CHOICE FOR SINGLE LINKED LIST:\n\
\n\t\t1. ADD ELEMENT\
\n\t\t2. DISPLAY ELEMENT\
\n\t\t3. DELETE ELEMENT\
\n\t\t4. EXIT\
\n\n\t\tYour choice: ");
while( res != 1 )
{
res = scanf("%d", &choice);
if ( choice >=1 && choice <= 4 ) return choice;
};
return 4;
}
OUTPUT
ENTER YOUR CHOICE FOR SINGLE LINKED LIST:
1. ADD ELEMENT
2. DISPLAY ELEMENT
3. DELETE ELEMENT
4. EXIT
Your choice: 2
menu returned 2
list is empty
10 elements in the list
1: 9
2: 8
3: 7
4: 6
5: 5
6: 4
7: 3
8: 2
9: 1
10: 0
And it is just an example of stuff using a more manageable list.

How to use gets and puts with linked list using pointers

I've written a linked list program and want to take input with spaces but it's not working.It works fine when I simply use "scanf" with %s but since I want to take input with multiple spaces I tried using "gets" and "puts" I've also tried using scanf("%[^\n]*c"); but on the console it gives me random garbage value for scanf("%[^\n]*c"); and for "gets" it reads blank space,
now let me tell you guys some info about the code and how it works
createNode(); function basically just creates a new node to store in the list and returns the address of this newly created node to the insertend(); function where it aligns the new node at the end of the list and in start=t=newnode start is the head pointer which points to the very first node and t is used to traverse the list until t's value becomes NULL,As you could see in the else part of the insertend(); function we're using another pointer t and storing the value of start in it so that we can traverse the list without losing the the address of the first node which is originally kept in the start pointer.
here's the code ->
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct Node
{
char first[20];
struct Node* next;
};
struct Node* start=NULL;
struct Node* t,*u;
int i=1;
struct Node* createNode() //this function creates a newnode everytime it's called
{
struct Node* create=(struct Node*)malloc(sizeof(struct Node));
return create;
}
int length() //to measure the length of the list.
{
int count = 0;
struct Node* temp;
temp=start;
while(temp!=NULL)
{
count++;
temp = temp->next;
}
return count;
}
void insertend() //to insert a node at the end of the list.
{
int l;
struct Node* newnode = createNode();
printf("Enter Name : ");
fgets(newnode->first,sizeof(newnode->first),stdin);
if(start==NULL)
{
start=t=newnode;
start->next=NULL;
}
else
{
t=start;
while(t->next!=NULL)
t=t->next;
t->next=newnode;
t=newnode;
t->next=NULL;
printf("%s successfully added to the list!",newnode->first);
}
l=length();
printf("The length of the list is %d",l);
}
void display() //to display the list
{
struct Node* dis;
dis=start;
if(start==NULL)
{
system("cls");
printf("No elements to display in the list");
}
else
{
system("cls");
for(int j=1;dis!=NULL;j++)
{
printf("%d.) %s\n",j,dis->first);
dis=dis->next;
}
}
}
int menu() //this is just a menu it returns the user input to the main function
{
int men;
printf("Please select a choice from the options below :-\n\n");
printf("1.) Add at the end of the list\n");
printf("2.) Display list\n");
printf("3.) exit\n");
printf(" Enter your choice : ");
scanf("%d",&men);
return men;
}
int main()
{
while(1)
{
system("cls");
switch(menu())
{
case 1 : insertend();
break;
case 2 : display();
break;
case 3: exit(0);
default : system("cls"); printf("Ivalid choice!Please select an appropriate option!");
fflush(stdin);
break;
}
getch();
}
return 0;
}
gets is not to be used, it has been removed from C standard due to it's lack of security.
If you want to know more read Why is the gets function so dangerous that it should not be used?
If you use [^\n] it should work, though it's also problematic since this specifier does not limit the lenght of the stream to be read only that it must stop when finding a newline character.
I suspect the problem might be in the container rather than in the reading, maybe uninitialized memory, If you provide the struct code it'll be easier to diagnose.
You can try:
fgets(newnode->first, sizeof(newnode->first), stdin)
There is a caveat:
If the inputed stream is larger than the container, the extra characters will remain in the input buffer, you might need to discard them.
EDIT:
So the main problem was the fact that through your code you have lingering characters in the buffer, in the particular case of your fgets input it would catch a '\n' left in the buffer, so it would read it before the inputed stream, leaving it, again, in the buffer.
I added a function to clean up buffer, note that fflush(stdin) leads to undefined behaviour so it's a bad option.
I also added a few small tweaks.
- Note that conio.h is windows specific as is system("cls") and getch()(ncurses.h in Linux systems) so I commented it for this sample.
Live sample here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
struct Node
{
char first[20];
struct Node *next;
};
struct Node *start = NULL;
struct Node *t, *u;
void clear_buf(){ //clear stdin buffer
int c;
while((c = fgetc(stdin)) != '\n' && c != EOF){}
}
struct Node *createNode() //this function creates a newnode everytime it's called
{
struct Node *create = malloc(sizeof(struct Node));
return create;
}
int length() //to measure the length of the list.
{
int count = 0;
struct Node *temp;
temp = start;
while (temp != NULL)
{
count++;
temp = temp->next;
}
return count;
}
void insertend() //to insert a node at the end of the list.
{
int l;
struct Node *newnode = createNode();
printf("Enter Name : ");
clear_buf(); //clear buffer before input
fgets(newnode->first, sizeof(newnode->first), stdin);
newnode->first[strcspn(newnode->first, "\n")] = '\0'; //remove '\n' from char array
if (start == NULL)
{
start = t = newnode;
start->next = NULL;
printf("%s successfully added to the list!", newnode->first);
}
else
{
t = start;
while (t->next != NULL)
t = t->next;
t->next = newnode;
t = newnode;
t->next = NULL;
printf("%s successfully added to the list!", newnode->first);
}
l = length();
printf("The length of the list is %d", l);
}
void display() //to display the list
{
const struct Node *dis;
dis = start;
if (start == NULL)
{
system("cls");
printf("No elements to display in the list");
}
else
{
system("cls");
for (int j = 1; dis != NULL; j++)
{
printf("%d.) %s\n", j, dis->first);
dis = dis->next;
}
}
}
int menu() //this is just a menu it returns the user input to the main function
{
int men;
printf("\nPlease select a choice from the options below :-\n\n");
printf("1.) Add at the end of the list\n");
printf("2.) Display list\n");
printf("3.) exit\n");
printf(" Enter your choice : ");
scanf("%d", &men);
return men;
}
int main()
{
while (1)
{
system("cls");
switch (menu())
{
case 1:
insertend();
break;
case 2:
display();
break;
case 3:
exit(0);
default:
system("cls");
printf("Ivalid choice!Please select an appropriate option!");
clear_buf();
break;
}
getch();
}
return 0;
}

Command terminated by signal 11

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
struct node{
char data;
int p;
struct node *ptr;
};
struct node *start=NULL;
struct node *insert()
{
struct node *new_node,*z;
int num;
char s;
printf("\nEnter -1 to stop.");
printf("\nEnter the characters and their priorities: ");
scanf("\n%c %d",&s,&num);
while(num!=-1)
{
new_node=(struct node *)malloc(sizeof(struct node));
new_node->data=s;
new_node->p=num;
if(start==NULL)
{
start=new_node;
z=start;
new_node->ptr=NULL;
}
else
{
z->ptr=new_node;
new_node->ptr=NULL;
z=z->ptr;
}
scanf("%c %d",&s,&num);
}
return start;
}
struct node *display()
{
struct node *z;
z=start;
printf("\nDisplaying elements:\n");
while(z!=NULL)
{
printf("\t%c [Priority=%d]\n",z->data,z->p);
z=z->ptr;
}
return start;
}
struct node *sortit()
{
struct node *z,*q;
int t;
char x;
z=start;
while(z->ptr!=NULL)
{
q=z->ptr;
while(q!=NULL)
{
if(z->p>q->p)
{
t=z->p;
x=z->data;
z->p=q->p;
z->data=q->data;
q->p=t;
q->data=x;
}
q=q->ptr;
}
z=z->ptr;
}
return start;
}
struct node *new_insert()
{
struct node *y,*z;
int n;
char s;
y=(struct node *)malloc(sizeof(struct node));
printf("\nEnter character and priority for new node:");
scanf("%c %d",&s,&n);
printf("%c",s);
y->data=s;
y->p=n;
printf("%c",y->data);
printf("%d",y->p);
if(n<start->p)
{
y->ptr=start;
start=y;
printf("%d",y->p);
}
else
{printf("\nff");
z=start;
while(z->ptr->p<=n&&z->ptr!=NULL)
z=z->ptr;
y->ptr=z->ptr;
z->ptr=y;
}
return start;
}
int main()
{
insert();
display();
sortit();
display();
new_insert();
display();
return 0;
}
In this C code, I have tried to implement priority queues.
Everything works perfectly fine except the new_insert() function. The print statements after y->p=n; in new_insert() function print 0.
Hence, the function doesn't work properly. Also, in display() function the print statement prints the [Priority] twice.
Hence, I am not able to add an external node in my priority queue.
Well, you code is not far from working I think.
There are some problems that can be corrected:
the scanf usage is problematic
%c selector must be use with caution, use " %c %d" to prevent end of line problems
return value must be checked
in function insert, z may not be initialized (if insert() is called when start is not NULL)
You don't need to cast malloc returned value.
I tested the following code with this input:
a 2
b 3
c 1
d -1
e 0
And I got this result:
Enter -1 to stop.
Enter the characters and their priorities:
Displaying elements:
a [Priority=2]
b [Priority=3]
c [Priority=1]
Displaying elements:
c [Priority=1]
a [Priority=2]
b [Priority=3]
Enter character and priority for new node:
s: 'e' n: '0'
e00
Displaying elements:
e [Priority=0]
c [Priority=1]
a [Priority=2]
b [Priority=3]
Seems to work isn't? You can test it online
And here's the corrected code:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
struct node{
char data;
int p;
struct node *ptr;
};
struct node *start=NULL;
struct node *insert()
{
/* initialize z in case of start is not null */
struct node *new_node,*z = start;
int num, ok;
char s;
printf("\nEnter -1 to stop.");
printf("\nEnter the characters and their priorities: ");
/* read the scanf return value */
ok = scanf(" %c %d",&s,&num);
/* and assert two elements have been read*/
while(ok == 2 && num!=-1)
{
new_node=malloc(sizeof(struct node));
new_node->data=s;
new_node->p=num;
if(start==NULL)
{
start=new_node;
z=start;
new_node->ptr=NULL;
}
else
{
z->ptr=new_node;
new_node->ptr=NULL;
z=z->ptr;
}
ok = scanf(" %c %d",&s,&num);
}
return start;
}
struct node *display()
{
struct node *z;
z=start;
printf("\nDisplaying elements:\n");
while(z!=NULL)
{
printf("\t%c [Priority=%d]\n",z->data,z->p);
z=z->ptr;
}
return start;
}
struct node *sortit()
{
struct node *z,*q;
int t;
char x;
z=start;
while(z->ptr!=NULL)
{
q=z->ptr;
while(q!=NULL)
{
if(z->p>q->p)
{
t=z->p;
x=z->data;
z->p=q->p;
z->data=q->data;
q->p=t;
q->data=x;
}
q=q->ptr;
}
z=z->ptr;
}
return start;
}
struct node *new_insert()
{
struct node *y,*z;
int n, ok;
char s;
printf("\nEnter character and priority for new node:");
ok = scanf(" %c %d",&s,&n);
if (2 == ok)
{
/* alloc y after having check that user gave usage stuff */
y = malloc(sizeof(struct node));
y->data=s;
y->p=n;
printf("%c",y->data);
printf("%d",y->p);
if(n<start->p)
{
y->ptr=start;
start=y;
printf("%d",y->p);
}
else
{
printf("\nff");
z=start;
while(z->ptr->p<=n&&z->ptr!=NULL)
z=z->ptr;
y->ptr=z->ptr;
z->ptr=y;
}
}
return start;
}
int main()
{
insert();
display();
sortit();
display();
new_insert();
display();
return 0;
}

Passing pointers between functions in an implementation of linked list

The problem was solved. A guy gave it in comments. The problem was that I was using %d to read in a short int. I should have used %hd or I should have used an `int'.
I tried to create a program of singly-linked list using only local variables. I was able to make a working program by using global variables.
The program with local variables compiles but it crashes when I try to traverse the linked list.
I have absolutely no idea what is wrong with the implementation with local variables. What is the problem present in the Implementation with local variables?
ABOUT THE STRUCTURE OF THE PROGRAMS:
I understand that the programs are big so I'll put in something about structure of the program.
The program is structured as a menu driven program. So the initial calls to functions are in main() function
There are 3 options in main() menu - exit, traverse and insertion
Exit returns 0 to exit program while other 2 do function calls
Insertion function itself is arranged as menu-driven program.
It has 3 options - return , insert_begin and insert_end. The last 2 are function calls.
I know there are memory leaks as I haven't freed any memory but I will take care of that after I can understand the problem in the current program.
//WORKING IMPLEMENTATION USING GLOBAL VARIABLE
#include<stdio.h>
#include<stdlib.h>
#define MIN 0
#define MAX 2
#define INS_MIN 0
#define INS_MAX 2
typedef struct node
{
int data;
struct node *next;
}sll_node;
sll_node *start = NULL;
void intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Exit");
printf("\n\t01 Traverse the list");
printf("\n\t02 Insertion into the list");
}
void insert_begin()
{
sll_node *node = malloc(sizeof(sll_node));
if(node == NULL)
{
printf("\n\tNot enough menory");
exit(-1);
}
int data;
printf("\n\tData to be entered: ");
scanf("%d", &data);
node->data = data;
node-> next = start;
start = node;
}
void insert_end()
{
sll_node *node = malloc(sizeof(sll_node));
if(node == NULL)
{
printf("\n\tNot enough menory");
exit(-2);
}
if(start == NULL)
insert_begin();
else
{
printf("\n\tData to be entered: ");
scanf("%d", &(node->data));
node-> next = NULL;
sll_node *node2;
for(node2 = start; node2->next != NULL; node2 = node2->next)
;
node2->next = node;
}
}
void insert_intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Insertion Done");
printf("\n\t01 Insert at beginning");
printf("\n\t02 Insert at end");
}
void insertion()
{
short choice;
while(1)
{
choice = -1;
while(choice < INS_MIN || choice > INS_MAX)
{
insert_intro();
printf("\n\n\tEnter your chocie: ");
scanf("%d", &choice);
}
switch(choice)
{
case 0:
return;
case 1:
insert_begin();
break;
case 2:
insert_end();
break;
}
}
}
void traverse()
{
if(start == NULL)
printf("\n\n\tLinked list is empty");
else
{
printf("\n\n\t");
for(sll_node *node = start; node != NULL; node = node->next)
printf("%d ", node->data);
}
getch();
}
int main()
{
short choice;
while(1)
{
choice = -1;
while(choice < MIN || choice > MAX)
{
intro();
printf("\n\n\tEnter your choice: ");
scanf("%d", &choice);
}
switch(choice)
{
case 0:
return 0;
case 1:
traverse();
break;
case 2:
insertion();
break;
}
}
return 0;
}
//COMPILES BUT CRASHES - Same program but with local variable start and variable passing between functions
#include<stdio.h>
#include<stdlib.h>
#define MIN 0
#define MAX 2
#define INS_MIN 0
#define INS_MAX 2
typedef struct node
{
int data;
struct node *next;
}sll_node;
void intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Exit");
printf("\n\t01 Traverse the list");
printf("\n\t02 Insertion into the list");
}
sll_node* insert_begin(sll_node *start)
{
sll_node *node = malloc(sizeof(sll_node));
if(node == NULL)
{
printf("\n\tNot enough menory");
exit(-1);
}
int data;
printf("\n\tData to be entered: ");
scanf("%d", &data);
node->data = data;
node-> next = start;
return node;
}
sll_node* insert_end(sll_node *start)
{
sll_node *node = malloc(sizeof(sll_node));
if(node == NULL)
{
printf("\n\tNot enough menory");
exit(-2);
}
if(start == NULL)
start = insert_begin(start);
else
{
printf("\n\tData to be entered: ");
scanf("%d", &(node->data));
node-> next = NULL;
sll_node *node2;
for(node2 = start; node2->next != NULL; node2 = node2->next)
;
node2->next = node;
}
return start;
}
void insert_intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Insertion Done");
printf("\n\t01 Insert at beginning");
printf("\n\t02 Insert at end");
}
sll_node* insertion(sll_node *start)
{
short choice;
while(1)
{
choice = -1;
while(choice < INS_MIN || choice > INS_MAX)
{
insert_intro();
printf("\n\n\tEnter your chocie: ");
scanf("%d", &choice);
}
switch(choice)
{
case 0:
return start;
case 1:
start = insert_begin(start);
break;
case 2:
start = insert_end(start);
break;
}
}
}
void traverse(sll_node *start)
{
if(start == NULL)
printf("\n\n\tLinked list is empty");
else
{
printf("\n\n\t");
for(sll_node *node = start; node != NULL; node = node->next)
printf("%d ", node->data);
}
getch();
}
int main()
{
sll_node *start = NULL;
short choice;
while(1)
{
choice = -1;
while(choice < MIN || choice > MAX)
{
intro();
printf("\n\n\tEnter your choice: ");
scanf("%d", &choice);
}
switch(choice)
{
case 0:
return 0;
case 1:
traverse(start);
break;
case 2:
start = insertion(start);
break;
}
}
return 0;
}
You are not returning anything from insertion() function when item is added to a list. So linked list may not get constructed properly.
Probably, you should return start only when its added at the beginning, otherwise start in main() will not point to head of the list.
sll_node* insertion(sll_node *start)
{
...
switch(choice)
{
case 0:
return start;
case 1:
start = insert_begin(start);
return start; //<----- return node
break;
case 2:
start = insert_end(start);
break;
}
...
}
Change short choice to int choice.
Why does this make a difference?
Short answer is that printf("%d") expects an integer.
The long answer is "%d" describes the data type you are passing to printf as an integer (which is commonly 4 to 8 bytes), and you're giving it a datatype of short - which is commonly 2 bytes long. When your program reads the input and stores it at the pointer, &choice, it writes 4 bytes starting at that address (but only 2 were reserved). This causes a segmentation fault and will crash your program.
Here's a list to some printf documentation. You'll notice that to pass a short to printf you would write %hd instead of %d
When i compile your code on my computer, it works, but i changed "short choice" to "int choice", because scanf("%d", &choice) takes 4 bytes to write on, and when choice is short it crashes, because short has only 2 bytes, therefore stack corruption will occur, my be on your computer this corruption damage the "start" pointer.
About the crash. Change the argument start in both functions insert_begin and insert_end to sll_node ** start, and when assigning new value, use the expression *start = your-new-value. It is because you have to pass a pointer to the local variable start which is also pointer. You do not need to change function traverse.
About memory leaks, let me to point-out that when you call insert_begin from inside insert_end, the node created from insert_end is left unused. before exit() and the return in main() you should free the list.
Yes, sorry. There was another bug hard to see. It was at 2 lines where you read (choice).
short choice;
...
// It is ERROR to use "%d" with (short choice), because the stack will
// be overwritten with unsuspected results. The format specifier "%hd"
// say to compiler that (&choice) point to a short 16-bit integer,
// not 32-bit
scanf("%hd", &choice);
This is slightly different version, tested, without memory leaks.
//
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define MIN 0
#define MAX 2
#define INS_MIN 0
#define INS_MAX 2
typedef struct node
{
int data;
struct node *next;
} sll_node;
void clear_list(sll_node** start)
{
assert(start != NULL);
sll_node* node = *start;
while (node != NULL)
{
sll_node* element = node;
node = element->next;
free(element);
}
*start = NULL;
}
void intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Exit");
printf("\n\t01 Traverse the list");
printf("\n\t02 Insertion into the list");
}
void insert_begin(sll_node** pstart)
{
sll_node* node = (sll_node*)malloc(sizeof(sll_node));
if (node == NULL)
{
printf("\n\tNot enough menory");
clear_list(pstart);
exit(-1);
}
int data;
printf("\n\tData to be entered: ");
scanf_s("%d", &data);//scanf
node->data = data;
node->next = *pstart;
// update the local variable start passed from main to point just inserted node
*pstart = node;
}
void insert_end(sll_node** start)
{
assert(start != NULL);
if (*start == NULL)
{
insert_begin(start);
}
else
{
sll_node* node = (sll_node*)malloc(sizeof(sll_node));
if (node == NULL)
{
printf("\n\tNot enough menory");
clear_list(start);
exit(-2);
}
printf("\n\tData to be entered: ");
scanf("%d", &(node->data));
node->next = NULL;
sll_node* node2;
for(node2 = *start; node2->next != NULL; node2 = node2->next)
;
node2->next = node;
}
}
void insert_intro()
{
system("cls");
printf("\n\tThese are the various options:\n");
printf("\n\t00 Insertion Done");
printf("\n\t01 Insert at beginning");
printf("\n\t02 Insert at end");
}
void insertion(sll_node** start)
{
short choice;
while(1)
{
choice = -1;
while(choice < INS_MIN || choice > INS_MAX)
{
insert_intro();
printf("\n\n\tEnter your chocie: ");
scanf("%hd", &choice);
}
switch(choice)
{
case 0:
return;
case 1:
insert_begin(start);
break;
case 2:
insert_end(start);
break;
}
}
}
void traverse(sll_node *start)
{
if (start == NULL)
printf("\n\n\tLinked list is empty");
else
{
printf("\n\n\t");
for(sll_node *node = start; node != NULL; node = node->next)
printf("%d ", node->data);
}
getch();
}
int main()
{
sll_node *start = NULL;
short choice;
while(1)
{
choice = -1;
while(choice < MIN || choice > MAX)
{
intro();
printf("\n\n\tEnter your choice: ");
scanf("%hd", &choice);
}
switch(choice)
{
case 0:
clear_list(&start);
return 0;
case 1:
traverse(start);
break;
case 2:
insertion(&start);
break;
}
}
return 0;
}
P.S. Very hard to edit! I'm new here and do not have enough experience. Wasted a lot of time to edit!

undefined reference to gotoxy in C

I am trying to write a program in C language(code::blocks in windows).
I have added below header files, it compiles with no error, but when it comes to run the code it throws an error undefined reference to gotoxy.
Find the full code.
Error comes where ever I have gotoxy statements.
# include<stdio.h>
# include<conio.h>
# include<malloc.h>
# include<stdlib.h>
# include<windows.h>
#include<dos.h>
struct node
{ int data;
struct node *link;
};
void append(struct node **,int);
void in_begin(struct node **,int);
void del(struct node **,int);
void in_middle(struct node **,int,int);
int count(struct node *);
void display(struct node *);
char ans;
int main()
{ struct node *p; /* p can be said as the head or a start ptr */
p=NULL;
/* Printing the menu */
int num,loc;
char choice;
do
{ //clrscr();
printf("PROGRAM TO IMPLEMENT SINGLY LINKED LIST ");
printf("\n=====================================");
printf("\n\n1.Create \\ Appending The List");
printf("\n2.Insert Node At Begining");
printf("\n3.Insert Node In Middle");
printf("\n4.Deleting a Node");
printf("\n5.Counting The No Of Nodes");
printf("\n6.Displaying the list");
printf("\n7.Exit");
oper:
gotoxy(1,15);printf(" ");
gotoxy(1,11);printf("\n\nEnter ur Choice : ");
choice=getch();
switch(choice)
{
case '1':
// char ans;
do
{ printf("Enter any number : ");
scanf("%d",&num);
append(&p,num);
printf("Enter more (y/n) :");
fflush(stdin);
ans=getchar();
}while(ans !='n');
break;
case '2':
printf("Enter The Data : ");
scanf("%d",&num);
in_begin(&p,num);
break;
case '3':
printf("\nEnter The Position :");
scanf("%d",&loc);
printf("\nEnter The Data : ");
scanf("%d",&num);
in_middle(&p,loc,num);
break;
case '4':
printf("\nEnter The Data u Want To Delete : ");
scanf("%d",&num);
del(&p,num);
break;
case '5':
printf("\nThe No Of Nodes Are %d",count(p));
getch();
break;
case '6':
display(p);
getch();
break;
case '7':
printf("\n\nQuiting.......");
getch();
exit(0);
break;
default:
gotoxy(1,15);printf("Invalid choice.Please Enter Correct Choice");
getch();
goto oper;
}
}while(choice !=7);
return 0;
}
void append(struct node **q,int num)
{ struct node *temp,*r;
temp = *q;
if(*q==NULL)
{ temp = (struct node *)malloc(sizeof(struct node));
temp->data=num;
temp->link=NULL;
*q=temp;
}
else
{ temp = *q;
while(temp->link !=NULL)
{ temp=temp->link;
}
r = (struct node *)malloc(sizeof(struct node));
r->data=num;
r->link=NULL;
temp->link=r;
}
}
void display(struct node *q)
{ if(q==NULL)
{ printf("\n\nEmpty Link List.Can't Display The Data");
getch();
goto last;
}
while(q!=NULL)
{ printf("\n%d",q->data);
q=q->link;
}
last:
;
}
int count(struct node *q)
{ int c=0;
if(q==NULL)
{ printf("Empty Link List.\n");
getch();
goto last;
}
while(q!=NULL)
{ c++;
q=q->link;
}
last:
return c;
}
void in_begin(struct node **q,int num)
{ struct node *temp;
if(*q==NULL)
{ printf("Link List Is Empty.Can't Insert.");
getch();
goto last;
}
else
{ temp=(struct node *)malloc(sizeof(struct node));
temp->data=num;
temp->link=*q;
*q=temp; /* pointing to the first node */
}
last:
getch();
}
void in_middle(struct node **q,int loc,int num)
{ struct node *temp,*n;
int c=1,flag=0;
temp=*q;
if(*q==NULL)
{ printf("\n\nLink List Is Empty.Can't Insert.");
getch();
goto last;
}
else
while(temp!=NULL)
{ if(c==loc)
{ n = (struct node *)malloc(sizeof(struct node));
n->data=num;
n->link=temp->link;
temp->link=n;
flag=1;
}
c++;
temp=temp->link;
}
if(flag==0)
{ printf("\n\nNode Specified Doesn't Exist.Cant Enter The Data");
getch();
}
else
{ printf("Data Inserted");
getch();
}
last:
getch();
}
void del(struct node**q,int num)
{ if(*q==NULL)
{ printf("\n\nEmpty Linked List.Cant Delete The Data.");
getch();
goto last;
}
else
{
struct node *old,*temp;
int flag=0;
temp=*q;
while(temp!=NULL)
{ if(temp->data==num)
{ if(temp==*q) /* First Node case */
*q=temp->link; /* shifted the header node */
else
old->link=temp->link;
free(temp);
flag=1;
}
else
{ old=temp;
temp=temp->link;
}
}
if(flag==0)
printf("\nData Not Found...");
else
printf("\nData Deleted...Tap a key to continue");
getch();
}
last:
getch();
}
Please help me.
The problem you're facing isn't related to Code::Blocks, it's related to the compiler it's using (MinGW by default), and it's because that function isn't standard and wasn't implemented in that compiler. I'm not sure if Borland still provides conio.h, but you could try this one for MinGW.
Have a look at this http://projectsofashok.blogspot.in/2010/05/gotoxy-in-codeblocks.html
You can also try the below snippet, this will work in GCC
#include<stdio.h>
//gotoxy function
void gotoxy(int x,int y)
{
printf("%c[%d;%df",0x1B,y,x);
}
main ()
{
gotoxy(25,50); //reposition cursor
printf("hello world"); //display text
}
You can also have a look at NCURSES.
Code::Blocks(MinGW) doesnt have conio.h header file. So you cant use gotoxy()
#include<stdio.h>
#include<conio.h>
main()
{
gotoxy(10, 10);
printf("C program to change cursor position.");
getch();
return 0;
}
this works fine in C. but not in code blocks.
The problem you're facing isn't related to Code::Blocks, it's related to the compiler it's using (MinGW by default), and it's because that function isn't standard and wasn't implemented in that compiler.
try using these:
SetConsoleCursorPosition(hConsole, TL);
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
or use Borland C which supports conio.h. For getting it Visit the LINK
# include<stdio.h>
# include<conio.h> // you cant use conio.h
# include<malloc.h>
# include<stdlib.h>
# include<windows.h>
For what it is worth, here are some Windows versions of the old Borland functions I wrote maybe a decade ago.
/* console_functions.h */
#ifndef __WINAPI_CONSOLE_WRAPPER_H
#define __WINAPI_CONSOLE_WRAPPER_H
void init_console_functions (void);
void gotoxy (int x, int y);
void clrscr (void);
char getch (void);
#endif /* __WINAPI_CONSOLE_WRAPPER_H */
/* console_functions.c */
#include "ConsoleFunctions.h"
#include <windows.h>
static HANDLE hStdout;
static HANDLE hStdin;
static CONSOLE_SCREEN_BUFFER_INFO csbi;
static const COORD startCoords = {0,0};
void init_console_functions (void)
{
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hStdin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleScreenBufferInfo(hStdout, &csbi);
}
void gotoxy(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(hStdout,coord);
}
void clrscr(void)
{
DWORD dummy;
FillConsoleOutputCharacter(hStdout,
' ',
csbi.dwSize.X * csbi.dwSize.Y,
startCoords,
&dummy);
gotoxy(0,0);
}
char getch(void)
{
INPUT_RECORD inp_rec;
DWORD bytes_read;
BOOL success;
do
{
success = PeekConsoleInput(hStdin, &inp_rec, 1, &bytes_read);
FlushConsoleInputBuffer(hStdin);
} while(!success || inp_rec.EventType != KEY_EVENT || bytes_read==0);
return (char)inp_rec.Event.KeyEvent.uChar.AsciiChar;
}
There are two things for such kinds of questions in C
1) you have to have the proper header with the proper prototp (this i conio.h)
2) you have to have the proper library to link against in this case probably something along libconio.lib
You then have to include the proper header and you have to inform the linker against which libraries you like to link.
The link commands in gcc e.g are -L and -l and both are needed to use conio.
See also: g++ conio.h: no such file or directory
Regards
it is error because there is something missing that can handle the gotoxy try this code
int gotoxy(int x,int y)
{
COORD coord = {x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
Code blocks GUI doesn't work gotoxy()
so you make function it here....
#include<stdio.h>
#include<windows.h>
void gotoxy(int a, int b)
{
COORD c;
c.X=a;
c.Y=b;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
int main()
{
gotoxy(5, 66);
printf("hello");
getch();
}

Resources