linked list with function - c

I'm trying to create a program which creates and display linked list.
Now i'm having trouble with my create_list() function, it doesn't create any list.
What i'm doing wrong ?
Sorry for bad english :/
CODE :
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
int main(){
node *start;
start = NULL;
int a,n,on = 1;
while(on == 1){
printf(" \n choose: \n 1 --- create list \n 2 --- display list \n");
scanf("%d",&n);
switch(n){
case 1:
printf("-------------------------------------------- \n");
printf(" Enter the elements. The last element is 0 \n");
printf("-------------------------------------------- \n");
Create_list();
Display_list(start);
break;
case 2:
Display_list(start);
break;
}
}
system("pause");
return 0;
}
void Display_list(node *curr){
if(curr){
while (curr->next != NULL){
printf("%d \n",curr->data);
curr=curr->next;
}
} else {
printf(" \n The list is not created ! \n");
}
}
void Create_list(node *curr){
int i;
node *start = NULL;
if (start == NULL){
curr = (node *)malloc(sizeof(node));
start=curr;
while ( i != 0){
scanf("%d",&i);
if(i == 0){
curr->next=NULL;
curr=start;
} else {
curr->data=i;
curr->next=(node *)malloc(sizeof(node));
curr=curr->next;
}
}
} else {
printf(" \n list already exists ! \n");
}
}

The function Create_List(node *curr) needs some arguments. You are not passing any arguments from main(). Did your code compile?
The function Create_List(node *curr) needs some arguments. You are not passing any arguments from main(). Did your code compile?
What you should do is take a node in main which will store location of first node of the linked list.
void Insert(struct node **q, int num) //Num is the data to be added and **q is the pointer to the first node of the list.
{
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 {
while (temp->link != NULL)
temp = temp->link;
r = ((struct node *)malloc(sizeof(struct node)));
r->data = num;
r->link = NULL;
temp->link = r;
}
}

The start in Create_list is not related to the start in main. Since both are local to their respective functions, one can't even see the other. So setting start doesn't actually set start, if you will. :P
You'll need to either bring start outside of the functions and make it global, or pass &start (as a node**) from main into Create_list and modify *start to set the list head. (The latter is generally preferable, as globals are often trouble waiting to happen.)

Related

Exception fault(Segmentation fault) creating a singly link list in c

Program to create a singly link list but an Exception error (Segmentation fault) occurs while printing the data stored in the link list, although the program runs and show output
.
//Program to create a singly link list
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct node
{
int data;
struct node *next;
};
void main()
{
struct node *head, *newnode, *temp;
head = 0;
int choice = 1;
while (choice)
{
if(choice==1)
{
newnode = (struct node *)malloc(sizeof(struct node));
printf("Enter the data ");
scanf("%d", &newnode->data);
newnode->next;
if (head == 0)
{
head = temp = newnode;
}
else
{
temp->next = newnode;
temp = newnode;
}
printf("Do you want to continue - Press 1 to continue and 0 to terminate ");
scanf("%d", &choice);
}
}
temp = head;
while (temp != 0)
{
printf("%d\t", temp->data);/*Here it show Exception error(Segmentation fault)*/
temp = temp->next;
}
getch();
}
There is a typo in this statement
newnode->next;
It seems you mean
newnode->next = NULL;
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )

How to return lists in c functions?

As the title says I need to write a function which fill a list with int typed by the user, and later on print them, but i'm having troubles with the insert function, which does not actually put the values typed in the list. Here's the code:
the typedefs:
typedef struct list_element {
int value;
struct list_element *next;
} item;
typedef item *list;
and the functions:
list lins(list l)
{
int i;
list root = NULL;
printf("inserire dati ('0' per terminare):\n");
do
{
scanf("%d", &i);
l = (list)malloc(sizeof(item));
l->value = i;
l->next = root;
root = l;
} while (i != 0);
return l;
}
void showlist(list l)
{
printf("lista completa:\n");
while (l != NULL)
{
printf("%d ", l->value);
l = l->next;
}
printf("\n");
}
Sorry if my code is poorly written but I'm having a hard time understanding the concept of lists.
Edit: added functions calls
main()
{
lins(l);
showlist(l);
}
Edit 2: here's the output of the code:
output
Edit 3: Here's the sample of code my professor give us to work with lists:
http://www.mediafire.com/file/wj152pw1ojkxf1j/10a_-Liste-_2018.pdf
Your insertion function inserts in reverse order. That is because you assign root to l->next and l to root. Also the number 0 is included in the list when the user tries to end the insertion process.
In main(), you don't seem to assign the return value of the function lins() to a variable, and if you passed l declared as List l = NULL; to the function lins(), then a copy of it will be used, and so, the original variable won't be altered. What you really need is something like:
#include <stdio.h>
#include <stdlib.h>
typedef struct list_element {
int value;
struct list_element *next;
} item;
typedef item *list;
list lins(void)
{
list node = NULL;
list root = NULL;
list tail = NULL;
printf("inserire dati ('0' per terminare):\n");
int i;
scanf("%d", &i);
while(i != 0)
{
node = (list)malloc(sizeof(item));
node->value = i;
node->next = NULL;
if (!root)
root = node;
else
tail->next = node;
tail = node;
scanf("%d", &i);
}
return root;
}
void showlist(list l)
{
printf("lista completa:\n");
while (l != NULL)
{
printf("%d ", l->value);
l = l->next;
}
printf("\n");
}
int main(void)
{
list head = lins();
showlist(head);
system("pause");
return 0;
}
Of course, I should point out that you should free the list once you are done with it.
First of, I see no point in passing item *l as an argument to lins function.
The root or better, head of the list should not be changed once you assign something to it, unless you want to delete the list.
void lins(item **head){
item *new_node = malloc(sizeof(item));
int i;
if(!new_node){
printf("Memory allocation failed!\n");
exit(1);
}
scanf("%d", &i);
new_node->value = i;
new_node->next = NULL;
node *temp = *head;
if(!temp)
*head = new_node;
else{
while (temp->next != NULL){
temp = temp->next;
}
temp->next = new_node;
}
return ;
}
After you write lins like this, showlist can look as follow:
void showlist(item *head){
printf("List is: \n");
do{
printf("%d", head->value);
head=head->next;
}while(head!=NULL);
}
As for the main function you need to declare the head first.
int main(){
item *head = NULL;
lins(&head);
showlist(head);
return 0;
}
more detailed explanation to follow...
So from what I understand, you want to prepend to your linked-list. I will try to use your typedefs, though many comments have given better options to use, you could change the implementation later.
Realise that lins(list l) is never utilising the value of the parameter l passed to it. That is overriden by the malloc. It is prepending elements to the list, and finally returns the new head of your list. That new head has to be passed to showlist() for printing. What you might be doing is initialising one element of the list in main, and passing that to lins and showlist. lins doesnt bother with the parameter and returns a completely new list, but when you pass that old list to showlist it is interpreted as an empty list.
So you can simply change usage of lins to be used as a creator of linked-lists.
So declaring list lins() {...} and using it in main() like this should work:
int main() {
list l;
l = lins();
showlist(l);
return 0;
}
struct list_element {
int value;
struct list_element *next;};
typedef struct list_element * list;
void lins(list *l){
list tmp = NULL;
list last = *l;
int i;
if (last){
while(last->next){ // go to last child of list
last = last->next;
}
}else{
last = (list)malloc(sizeof(struct list_element));
}
printf("inserire dati ('0' per terminare):\n");
do
{
scanf("%d", &i);
last->value = i;
last->next = (list)malloc(sizeof(struct list_element));
last = last->next;
} while (i != 0);}
void show(list li){
list tmp = li;
if(li){
while(tmp){
printf("%d at %p\n",tmp->value, tmp);
tmp = tmp->next;
}
}}
int main(){
list a = (list)malloc(sizeof(struct list_element));
lins(&a);
show(a);
return 0;}

Error Cannot access memory at address in linked list

I'm creating a linked list with some insert functions.
This method work fine :
void insert_before(){
struct node *new_node, *ptr, *preptr;
int pivot;
new_node = (struct node*)malloc(sizeof(struct node));
ptr = link;
preptr = link;
printf("\n Enter the data : ");
scanf("%d", &new_node->data);
printf("\n Enter the value before which the data has to be inserted : ");
scanf("%d", &pivot);
while(ptr->data != pivot){
preptr = ptr;
ptr = ptr->next;
}
preptr->next = new_node;
new_node->next = ptr;
}
However, I got Cannot access memory at address 0x8 in this method :
void insert_after(){
struct node *new_node, *ptr, *preptr;
int pivot;
new_node = (struct node*)malloc(sizeof(struct node));
ptr = link;
preptr = link;
printf("\n Enter the data : ");
scanf("%d", &new_node->data);
printf("\n Enter the value after which the data has to be inserted : ");
scanf("%d", &pivot);
while(preptr->data != pivot){
preptr = ptr;
ptr = ptr->next;
}
preptr->next = new_node;
new_node->next = ptr;
}
Note that both of the method use the same struct* link, and the only difference is on the looping while(preptr->data != pivot).
Why does the first code working fine, but the second one broken?
Thanks for your help
PS : This is my whole project (very short), in case you need it : https://pastebin.com/wsMEicGv
I don't think that even the first method works correctly (simple proof: the code never changes the value of link, hence an insert before the first node cannot work).
Anyway, your code will produce the mentioned error message in both functions when you enter a value for pivot which does not match any data or which matches the last node in the list:
while(preptr->data != pivot){
preptr = ptr;
ptr = ptr->next;
}
The reason is that the loop above will reach the end of the list (having preptr = NULL), when condition preptr->data still accesses this null-pointer. I suppose that member data is the second one in your struct (the first one is next), right? Then you access actually (NULL + sizeof(node*)) which is (NULL + 8) which is 0x08.
You have a lot of bad practice:
You use global without reason!
You use global without reason!!
You use global without reason!!!
You cast malloc() without reason.
You don't check return value of function like scanf() or malloc().
You code several time the same feature.
fflush(stdin); is undefined behavior.
You don't initialize your variable when you could.
You declare all your variable at the beginning of the function.
For example, display() could look like this:
void display(struct node *head) { // no global it's better, isn't it ?
printf("List:");
while (head != NULL) {
printf(" %d", head->data);
head = head->next;
}
printf("\n");
}
More, in your create_ll() function, why don't you use insert beginning and reverse the list after ?
int create_ll(struct node **head) {
*head = NULL;
while (insert_beginning(head) != ERROR) {
}
return reverse_ll(head);
}
Use example:
int main(void) {
struct node *head;
if (create_ll(&head) == ERROR) {
return 1;
}
display(head);
free_ll(head);
}
For the problem of your both function, read the answer of stephan-lechner. But I make you an example:
int insert_after(struct node **head) {
printf("\n Enter the data : ");
int data;
if (scanf("%d", &data) != 1) { // If the input has no been parse.
// data is invalid here
return ERROR;
}
// data is valid here
printf("\n Enter the value after which the data has to be inserted : ");
int pivot;
if (scanf("%d", &pivot) != 1) {
return ERROR;
}
for (struct node *node = *head; node != NULL; node = node->next) {
if (node->data == pivot) {
struct node *new_node = malloc(sizeof *new_node);
if (new_node == NULL) {
return ERROR;
}
new_node->data = data;
new_node->next = node->next;
node->next = new_node;
return OK;
}
}
return ERROR;
}
Be aware that: If you use global your list functions will be:
Not thread safe.
Only usable for one list.
More info here.

storing and printing string in void pointer

I have written a linked list program which stores data member as void *.
while trying to store annd print using scanf/printf functions, I am getting segmentation fault.
node definition -->
typedef struct node {
struct node *next;
void *data;
}node;
main function -->
head=(node *)malloc(sizeof(node));
if (head==NULL){
printf("error in allocation of memory\n");
exit(EXIT_FAILURE);
}
tail=(node*)create(head);
create function -->
void *create(node *current)
{
int user_choice;
while(current){
printf("\nEnter the data:");
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
current=current->next;
}
else{
current->next=NULL;
}
}
return current;
}
can anyone tell what is the correct argument for scanf & prinf should be..?
working code after incorporating points given in answers...
void *create(node *current)
{
node *temp;
int user_choice;
while(current){
printf("\nEnter the data:");
current->data=(char*)malloc(10*sizeof(char));
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
}
else{
current->next=NULL;
temp=current;
}
current=current->next;
}
return temp;
}
In your code,
scanf("%s",current->data);
is attempt to make use of an unitialized pointer, it invokes undefined behavior.
You need to follow either of bellow approach,
make the pointer point to valid chunk of memory (using malloc() and family for dynamic allocation, for example)
use an array.
You should first initialize data member of structure because
current->data = malloc("passes size here");
For putting data you have to typecast first this data because void is not storage type. void pointer can be used to point to any data type.
Like
*(char *)(current->data) = 1;
As others have said:
scanf("%s",current->data);
Is undefined in C. current->data needs to be pointing somewhere before you can store anything in it.
You should instead:
Accept input from scanf.
Store in temporary buffer.
Insert into linked list
print out whole linked list at the end
free() linked list at the end.
I also feel that your current void *create function is doing too much, and it would be easier to split up your code into different functions, just to make it easier to handle all the pointer operations, inserting etc.
To demonstrate these points, I wrote some code a while ago which does these things, and has been modified to help you with your code. It is not the best code, but it does use these points that will help you with your code.
Here it is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRLEN 100
typedef struct node {
void *data;
struct node *next;
} node_t;
typedef struct {
node_t *head;
node_t *foot;
} list_t;
list_t *create_list(void);
node_t *generate_node(void);
list_t *insert_node(list_t *list, char *data);
void print_list(list_t *list);
void free_list(list_t *list);
int
main(int argc, char *argv[]) {
list_t *list;
char data[MAXSTRLEN];
int user_choice;
list = create_list();
while (1) {
printf("Enter the data: ");
scanf("%s", data);
printf("\nType '1' to continue, '0' to exit:\n");
if (scanf("%d",&user_choice) != 1) {
printf("Invalid input\n");
exit(EXIT_FAILURE);
}
if (user_choice == 1) {
list = insert_node(list, data);
} else {
list = insert_node(list, data);
break;
}
}
print_list(list);
free_list(list);
list = NULL;
return 0;
}
/* inserting at foot, you can insert at the head if you wish. */
list_t
*insert_node(list_t *list, char *data) {
node_t *newnode = generate_node();
newnode->data = malloc(strlen(data)+1);
strcpy(newnode->data, data);
newnode->next = NULL;
if (list->foot == NULL) {
list->head = newnode;
list->foot = newnode;
} else {
list->foot->next = newnode;
list->foot = newnode;
}
return list;
}
node_t
*generate_node(void) {
node_t *new = malloc(sizeof(*new));
new->data = NULL;
return new;
}
void
print_list(list_t *list) {
node_t *curr = list->head;
printf("\nlinked list data:\n");
while(curr != NULL) {
printf("%s\n", (char*)curr->data);
curr = curr->next;
}
}
list_t
*create_list(void) {
list_t *list = malloc(sizeof(*list));
if (list == NULL) {
fprintf(stderr, "%s\n", "Error allocating memory");
exit(EXIT_FAILURE);
}
list->head = NULL;
list->foot = NULL;
return list;
}
void
free_list(list_t *list) {
node_t *curr, *prev;
curr = list->head;
while (curr) {
prev = curr;
curr = curr->next;
free(prev);
}
free(list);
}
UPDATE:
Also note how I allocated memory for newnode->data?
Like this:
newnode->data = malloc(strlen(data)+1); //using buffer from scanf
This now means I can store data in this pointer, your current->data will need to do something similar.
working code-->
void *create(node *current)
{
node *temp;
int user_choice;
while(current){
printf("\nEnter the data:");
current->data=(char*)malloc(10*sizeof(char));
scanf("%s",current->data);
printf("stored at %p\n",(void*)current->data);
printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
}
else{
current->next=NULL;
temp=current;
}
current=current->next;
}
return temp;
}
Please try with this
void *create(node *current)
{
int user_choice;
while(true){
if(current == NULL) {
current = (node *)malloc(sizeof(node));
current->data = NULL;
current->next = NULL;
}
printf("\nEnter the data:");
scanf("%s",current->data);
printf("stored at %p\n", (void *)current->data);
printf("%s",current->data);
//printf("%s",(char*)current->data);
printf("\nType '1' to continue, '0' to exit:\n");
scanf("%d",&user_choice);
if(user_choice == 1){
current->next=(node*)malloc(sizeof(node));
current=current->next;
}
else{
current->next=NULL;
tail = current;
current=current->next;
break;
}
}
return current;
}
Note: The element has to be initialized (ie; it has to be alloted with some memory) before we are trying to make use of it.

Printing strings in linked lists

So I'm having trouble getting my program to print both the strings I input, or however many you want to put in the list, it always prints out the last string inputted multiple times. I am sorry about all the commented out code, most of it you don't need to read.
#include<stdio.h>
#include<stdlib.h>
struct node{
char *data;
struct node *next;
}*head;
typedef struct node NODE;
// Function prototypes
void append(char myStr[]);
void add( char myStr[] );
//void addafter(char myStr[], int loc);
void insert(char myStr[]);
int delete(char myStr[]);
void display(struct node *r);
int count();
// main function
int main()
{
int i;
struct node *n;
head = NULL;
char myStr[50];
while(1)
{
printf("\nList Operations\n");
printf("===============\n");
printf("1.Insert\n");
printf("2.Display\n");
printf("3.Size\n");
printf("4.Delete\n");
printf("5.Exit\n");
printf("Enter your choice : ");
if(scanf("%d", &i) <= 0)
{
printf("Enter only an Integer\n");
exit(0);
}
else
{
switch(i)
{
case 1:
printf("Enter the name to insert : ");
scanf("%50s", myStr);
insert(myStr);
break;
case 2:
if(head == NULL)
{
printf("List is Empty\n");
}
else
{
printf("Name(s) in the list are : ");
}
display(n);
break;
case 3:
printf("Size of the list is %d\n",count());
break;
case 4:
if(head == NULL)
printf("List is Empty\n");
else
{
printf("Enter the myStrber to delete : ");
scanf("%50s",myStr);
if(delete(myStr))
printf("%s deleted successfully\n",myStr);
else
printf("%s not found in the list\n",myStr);
}
break;
case 5:
return 0;
default:
printf("Invalid option\n");
}
}
}
return 0;
}
// Function definitions
void append(char myStr[])
{
struct node *temp,*right;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = myStr;
right=(struct node *)head;
while(right->next != NULL)
{
right = right->next;
}
right->next = temp;
right = temp;
right->next = NULL;
}
// adding a node to the beginning of the linked list
void add( char myStr[] )
{
struct node *temp;
temp =(struct node *)malloc(sizeof(struct node));
temp->data = myStr;
// only one node on the linked list
if (head == NULL)
{
head = temp;
head->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
void insert(char myStr[])
{
int c = 0;
struct node *temp;
temp = head;
if(temp == NULL)
{
add(myStr);
}
else
{
append(myStr);
}
}
int delete(char myStr[])
{
struct node *temp, *prev;
temp = head;
while(temp != NULL)
{
if(temp->data == myStr)
{
if(temp == head)
{
head = temp->next;
head = (*temp).next;
free(temp);
return 1;
}
else
{
prev->next = temp->next;
free(temp);
return 1;
}
}
else
{
prev = temp;
temp = temp->next;
}
}
return 0;
}
void display(struct node *r)
{
r = head;
if(r == NULL)
{
return;
}
while(r != NULL)
{
printf("%s ", r->data);
r = r->next;
if(r == NULL)
{
printf("\nOur linked list is finished!");
}
}
printf("\n");
}
int count()
{
struct node *n;
int c = 0;
n = head;
while(n != NULL)
{
n = n->next;
c++;
}
return c;
}
The problem seems to be that myStr at main function is a char[], so it's content is overritten every time you insert data. Notice that struct node data field is a char*, it's just pointing to myStr address.
Hope this help!
Your program has only one place to write your input, myStr.
With each input, myStr is erased and a something else is written to myStr.
The data member of all of the nodes, points to myStr. myStr will only contain the last input.
The display() function asks each node what is data. data points to myStr so each node prints the contents of myStr. myStr will only contain the last input so all the nodes print the last input.
To fix this, in the add() and append() functions, you need to give the data member some memory by using malloc(). Then copy the contents of myStr to the data member by using strcpy().
temp->data = malloc ( strlen ( myStr) + 1);
strcpy ( temp->data, myStr);
Do this instead of temp->data = myStr;
You will need #include<string.h>
The memory will need to be free()'d in the delete() function.
free(temp->data);
Do this before freeing temp
char *data
that variable from struct is always assigned with the address of myStr as its a pointer it would only show you the value of myStr

Resources