I am trying to build a simple linked list.
I have successfully built a linked list only with int variables but when I add *char variables the output is wrong.
The int values seem to be correct but the *char type are wrong.
The *char type seem to always be the last one inserted.
Sample Input
Number: 5
Character: a
Number: 4
Character: b
Sample Output
5
b
**************
4
b
#include <stdio.h>
#include <stdlib.h>
typedef struct BOOKS
{
int value;
char *char_value;
struct BOOKS *next;
} BOOKS;
BOOKS *insert_value(BOOKS *node, int n, char *char_value);
BOOKS *read_list(BOOKS *head);
int main()
{
int aux = 0;
int menu = 0;
int option;
BOOKS *head = NULL;
BOOKS *tail = NULL;
while (menu != -2)
{
int choices;
printf("1. Insert Book\n");
printf("2. Print Books\n");
printf("3. Exit\n");
scanf("%d", &choices);
switch (choices)
{
case 1:
{
int n;
char char_value[2000] = "";
printf("Number:");
scanf("%d", &n);
printf("Character: ");
scanf("%s", &char_value);
if (aux == 0)
{
/*FIRST INTERACTION*/
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
aux = 1;
}
else
{
tail->next = malloc(sizeof(BOOKS));
/*FORMING TAIL->NEXT*/
tail->next = insert_value(tail->next, n, char_value);
/*ASSIGNING TAIL->NEXT AS THE NEW TAIL */
tail = tail->next;
}
break;
}
case 2:
{ /*READ THE LIST*/
read_list(head);
break;
}
case 3:
{
menu = -2;
break;
}
default:
printf("Invalid choice\n");
break;
}
}
}
BOOKS *insert_value(BOOKS *node, int n, char *char_value)
{
node->value = n;
node->char_value = char_value;
node->next = NULL;
return node;
}
BOOKS *read_list(BOOKS *head)
{
BOOKS *a = head;
while (a != NULL)
{
printf("%d\n", a->value);
printf("%s\n", a->char_value);
printf("\n********************\n");
a = a->next;
}
}
You're passing char_value from main to your insert_books function, and then saving this pointer in your newly created node. The address of char_value from main doesn't change, so you're saving the same address to each node you create. Since all these pointers point to the same place, they will all read back whatever value was written there last. If you want to make a copy of string in each node, you can use (non standard) strdup or malloc more memory and use strcpy. But, it's an odd design choice you're using a character array to accept one character anyway. I recommend changing char_value in both main and struct BOOKS to char char_value;, then you can simply use equals assignment as with value to save copies of the char. Be sure to scanf a char the correct way.
A couple of other things:
As written, you can change scanf("%s", &char_value); to scanf("%s", char_value);. char_value is a character array, which decays to a char* in this context, there's no need to specify the address of char_value.
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
This is a memory leak. You're allocating separate memory for head and tail, but then setting both pointers equal to the memory allocated for tail (the return value of insert_value). The memory allocated for head is never freed nor used.
This will help with the errors:-
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
typedef struct BOOKS
{
int value;
char char_value[2000];
struct BOOKS *next;
} BOOKS;
BOOKS *insert_value(BOOKS *node, int n, char *char_value);
BOOKS *read_list(BOOKS *head);
int main()
{
int aux = 0;
int menu = 0;
int option;
BOOKS *head = NULL;
BOOKS *tail = NULL;
while (menu != -2)
{
int choices;
printf("1. Insert Book\n");
printf("2. Print Books\n");
printf("3. Exit\n");
scanf("%d", &choices);
switch (choices)
{
case 1:
{
int n;
char char_value[2000];
printf("Number:");
scanf("%d", &n);
printf("Character: ");
scanf("%s", char_value);
if (aux == 0)
{
/*FIRST INTERACTION*/
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
aux = 1;
}
else
{
tail->next = malloc(sizeof(BOOKS));
/*FORMING TAIL->NEXT*/
tail->next = insert_value(tail->next, n, char_value);
/*ASSIGNING TAIL->NEXT AS THE NEW TAIL */
tail = tail->next;
}
break;
}
case 2:
{ /*READ THE LIST*/
read_list(head);
break;
}
case 3:
{
menu = -2;
break;
}
default:
printf("Invalid choice\n");
break;
}
}
}
BOOKS *insert_value(BOOKS *node, int n, char *char_value)
{
node->value = n;
int size = sizeof(char_value)/sizeof(char);
strncpy(node->char_value, char_value, size);
node->next = NULL;
return node;
}
BOOKS *read_list(BOOKS *head)
{
BOOKS *a = head;
while (a != NULL)
{
printf("%d\n", a->value);
printf("%s\n", a->char_value);
printf("\n********************\n");
a = a->next;
}
}
Related
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;
}
I need to make a function that removes elements of a linked list (elements of the list are words) that contain a letter the user inputs. Basically, I have a .txt file that has random words in it, after loading the words into the linked list, I need to make several functions (this post is only dedicated for the 4th function from the menu), one of which is the function I'm having trouble with.
My idea was to make a separate function that will send 1 if the word contains the letter and 0 if it does not, then I made a function that goes through my linked list and using the first function checks if that element of the list contains the word, if it does then I remove it and move onto the next element.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Element Element;
struct Element
{
char word[50];
Element *next;
};
Element *load_file(Element *head)
{
char file[500];
scanf("%s", file);
Element *temp = head;
FILE* fp = fopen(file, "r");
if(fp == NULL)
{
printf("Error while loading file.");
return 0;
}
while(!feof(fp))
{
Element *newE = (Element*)malloc(sizeof(Element));
fscanf(fp, "%s", newE->word);
newE->next = NULL;
if(!temp)
{
head = temp = newE;
}
else
{
temp->next = newE;
temp = newE;
}
}
fclose(fp);
printf("\nFile loaded successfully\n");
return head;
}
int frequency(Element *head, char *word)
{
Element *temp = head;
int counter = 0;
while(temp != NULL)
{
if(strcmp(temp->word, word) == 0)
{
counter++;
}
temp = temp->next;
}
return counter;
}
int contains(char word[], char letter)
{
int end = strlen(word);
int flag = 0;
for(int i = 0; i < end-1; i++)
{
if(letter == word[i])
{
flag = 1;
break;
}
}
return flag;
}
Element *delete_word(Element *head, char letter)
{
Element *temp = head;
Element *before = NULL;
Element *newHead = head;
while(temp != NULL)
{
if(contains(temp->word, letter))
{
if(before == NULL)
{
newHead = temp->next;
free(temp);
temp = newHead;
}
else
{
before->next = temp->next;
free(temp);
temp = before->next;
}
}
else
{
before = temp;
temp = temp->next;
}
}
return newHead;
}
void printElement(Element *element)
{
printf("%s \n", element->word);
}
void printList(Element *head)
{
Element *temp = head;
while(temp != NULL)
{
printElement(temp);
temp = temp->next;
}
}
void meni()
{
printf("************** MENI **************\n");
printf("1. Loading text from file \n");
printf("2. Print all elements of the list \n");
printf("3. Frequency of a certain word \n");
printf("4. Delete words that contain a letter \n");
printf("5. Load the list into a file \n");
printf("6. Exit \n\n");
}
int main()
{
Element *head = NULL;
int option;
while(1)
{
meni();
scanf("%d", &option);
switch(option)
{
case 1:
{
printf("Input a name of the file: \n");
head = load_file(head);
break;
}
case 2:
{
printList(head);
break;
}
case 3:
{
char word[100];
printf("Input a word: ");
scanf("%s", word);
int num = frequency(head, word);
printf("%d\n", num);
break;
}
case 4:
{
char word[100];
printf("Input a word: ");
scanf("%s", word);
head = delete_word(head, word);
printList(head);
break;
}
case 5:
{
}
case 6:
{
return 0;
}
}
}
return 0;
}
For some reason, it makes no changes on the list whatsoever.
Your delete_word() function is declared as:
Element *delete_word(Element *head, char letter);
But you call it with a char*:
char word[100];
head = delete_word(head, word);
The menu option says Delete words that contain a letter but when the user selects that option, he/she is instructed to Input a word: (confusing).
You then send the address of the first char in word to the function. From that address one char is picked. It'll be random at best and it will most probably corrupt the stack (since you, by picking one char only, probably pick 1 byte out of 4 or 8).
You could make it work like this:
case 4:
{
char word[100];
printf("Input characters: ");
if(scanf("%s", word)==1) {
int len = strlen(word);
for(int i=0; i<len; ++i) {
head = delete_word(head, word[i]);
}
}
printList(head);
break;
}
This would allow the user to enter some characters and all words containing any of those would be removed.
My goal is to create a linked list and store elements inside that list.
struct node
{
int a;
struct node *b;
} p,*temp,*head;
void create ( struct node *temp)
{
char c;
temp = malloc (sizeof(struct node));
printf("enter data\n");
scanf(" %d",&temp->a);
printf("do you want to insert another node y/n\n");
scanf("%s", &c);
if (c=='y')
{
create(temp->b);
}
else if ( c=='n')
{
temp->b= NULL;
temp=&p;
return;
}
}
void traverse ( struct node *head)
{
while(head != NULL)
{
printf("%d ",head->a);
head=head->b;
}
}
int main ()
{
int i,j,k,l,m,n;
do{
if(i==1)
{
printf("enter data\n");
scanf("%d",&p.a);
create (p.b);
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
printf("%d",temp->a);
}
I can't recover the elements once i've stored them. When I try to traverse the list, it only gives me the first element of the list and nothing else.
In main
do {
if(i==1)
{
...
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
must be something like
do {
if (scanf("%d", &i) != 1)
break;
if(i==1)
{
...
}
else if ( i==2)
traverse(temp);
}
while(i!=3);
to know what the user want (i not initialized in your code)
in create
scanf("%s", &c);
is wrong because c is a char rather than a string
Do not mix read of int and char because you will read newline and space when reading a character, so read a string for c, for instance
char c[2];
...
scanf("%1s", &c);
if (*c == 'y')
...
else if (c == 'n')
...
the return in else branch is useless, and in case the answer is not 'y' or 'n' you do nothing so you do not set temps, probably you have to just check if 'y' and all other answers must be considered to be 'n', or you need to ask again for the choice
in create you assign the local variable temps, that has no effect on p.b in main, you need to get a node** for instance
in main temp is used but never set elsewhere, and the variables j,k,l,m,n are useless. You also ask for the data in main while you also do in create, must not be done in main. The way you manage your variables do not allow you to modify/print the list
I encourage you to not use global variables the must you can, and to not use the same name for a global and local variable like you do for temp and head because that do not help the reader of your code
A proposal solving the problems :
#include <stdlib.h>
#include <stdio.h>
struct node
{
int a;
struct node * b;
};
/* flush input up to the end of the line */
void flush()
{
int c;
while ((c = getchar()) != '\n') {
if (c == EOF)
exit(-1);
}
}
void create (struct node ** l)
{
/* go to the end of the list */
while (*l != NULL)
l = &(*l)->b;
for (;;) {
char c[2];
int v;
printf("enter data\n");
if (scanf("%d", &v) != 1) {
puts("invalid value");
flush();
}
else {
*l = malloc (sizeof(struct node));
(*l)->a = v;
(*l)->b = NULL;
l = &(*l)->b;
for (;;) {
printf("do you want to insert another node y/n\n");
scanf("%1s", c);
if (*c == 'y')
break;
else if (*c == 'n')
return;
}
}
}
}
void traverse ( struct node *head)
{
while(head != NULL)
{
printf("%d ",head->a);
head = head->b;
}
putchar('\n');
}
int main ()
{
int i;
struct node *head = NULL;
for (;;) {
puts("enter choice : 1 to create new node, 2 to print list, 3 to exit");
if (scanf("%d", &i) != 1)
flush();
switch(i) {
case 1:
create(&head);
break;
case 2:
traverse(head);
break;
case 3:
return 0;
default:
break;
}
}
}
Compilation and execution :
/tmp % gcc -pedantic -Wextra -Wall t.c
/tmp % ./a.out
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
enter choice : 1 to create new node, 2 to print list, 3 to exit
1
enter data
11
do you want to insert another node y/n
y
enter data
22
do you want to insert another node y/n
n
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
11 22
enter choice : 1 to create new node, 2 to print list, 3 to exit
1
enter data
3
do you want to insert another node y/n
n
enter choice : 1 to create new node, 2 to print list, 3 to exit
2
11 22 3
enter choice : 1 to create new node, 2 to print list, 3 to exit
4
enter choice : 1 to create new node, 2 to print list, 3 to exit
3
I encourage you to add the free of the list
There are several issues here:
struct node
{
int a;
struct node *b;
} p,*temp,*head;
Why do you declare global variables and use it as function parameters ? Global variables are available globally, there is no need to pass them into functions. On the other hand, global variables should be avoided and used with care, so it would be better to create local variables (e.g. in main function) and pass them as parameters into next functions.
void create ( struct node *temp)
{
char c;
temp = malloc (sizeof(struct node));
printf("enter data\n");
scanf(" %d",&temp->a);
printf("do you want to insert another node y/n\n");
scanf("%s", &c);
if (c=='y')
{
create(temp->b);
}
else if ( c=='n')
{
temp->b= NULL;
temp=&p;
return;
}
}
This function looks wrong. temp function parameter is actually an internal function's variable, that is not an in/out parameter. In that case you can assign to the temp variable, but it will not for a list. Also temp function parameter shadows temp global variable. It is also a good think to return status of operation, usually '0' means no error, any other error value.
Another thing is to keep things as simple as possible. This will allow for more reuseability and goes with single responsibility principle. If function actually performs two tasks it should be split into two functions.
One more thing, you allocate memory dynamically but never free the memory. This will lead into memory losses.
A possible implementation of your list could be:
#include <stdio.h>
#include <stdlib.h>
typedef struct _node_t
{
int a;
struct _node_t * next;
} node_t;
static node_t * head = NULL;
static node_t * tail = NULL;
node_t * create(void)
{
node_t * temp = malloc(sizeof(node_t));
if (NULL == temp)
{
return NULL;
}
printf("Enter data\n");
scanf("%d", & temp->a);
return temp;
}
void append(node_t * data)
{
if (NULL == head)
{
head = tail = data;
}
else
{
tail->next = data;
tail = tail->next;
}
tail->next = NULL;
return;
}
int add_data(void)
{
node_t * data = NULL;
char answer = 'y';
data = create();
if (NULL == data)
{
return 1;
}
append(data);
return 0;
}
void traverse(void)
{
node_t * current = NULL;
for (current = head; current != NULL; current = current->next)
{
printf("%d ", current->a);
}
printf("\n");
return;
}
void cleanup(void)
{
node_t * current = head;
while (NULL != current)
{
head = head->next;
free(current);
current = head;
}
return;
}
int main(int argc, char ** argv)
{
int option = 3;
do
{
printf("Enter option:\n 1 - add data\n 2 - traverse list\n 3 - exit\n\n");
scanf("%i", & option);
switch (option)
{
case 1:
if (0 != add_data())
{
printf("ERROR:: Cannot allocate memory.\n");
cleanup();
return 1;
}
break;
case 2:
traverse();
break;
default:
if (option > 3)
{
printf("ERROR:: Improper option, try again.\n");
}
break;
}
}
while (option != 3);
cleanup();
return 0;
}
I tried making it as simple as possible and keeping your logic there.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// create a new node
struct node* create(int data)
{
struct node *n = malloc(sizeof(struct node));
n->data = data;
n->next = NULL; // by default its not NULL, so we must set it
return n;
}
void traverse(struct node *head)
{
struct node *tmp = head;
while(tmp != NULL)
{
printf("%d\t",tmp->data);
tmp = tmp->next;
}
}
void cleanup(struct node *head)
{
struct node *cur = head;
struct node *next;
while(cur != NULL)
{
next = cur->next;
free(cur);
cur = next;
}
}
int main ()
{
int data;
struct node *head, *tmp;
// head node is always created
printf("enter data\n");
scanf("%d",&data);
head = tmp = create(data);
if(head == NULL) return -1;
// now we loop until we don't want to create any more nodes
while(1)
{
char another;
printf("do you want to insert another node y/n\n");
scanf(" %c", &another); // ignore all the previous whitespace
if(another == 'y')
{
printf("enter data\n");
scanf("%d",&data);
tmp->next = create(data);
tmp = tmp->next;
}
else break;
/*
// anything but 'y' breaks the loop, but it can be set to continue if neither 'y' nor 'n' was read:
else if(another == 'n') break;
else continue;
*/
}
traverse(head);
cleanup(head);
}
EDIT: as #Diodacus stated, i added cleanup and checking if malloc returned NULL
#include <stdio.h>
#include <stdlib.h>
typedef struct nodeNum
{
int num;
struct nodeNum *next;
} t_nodeNum;
// Functions declaration ----------------------------
int menu(); // display menu and return choice
t_nodeNum* addition(t_nodeNum *node, int n);
void print_list(t_nodeNum *node);
// ----------------------------------------------------
// Main program to test link list functions
int main()
{
int choice;
t_nodeNum *pnode = NULL;
t_nodeNum *head = NULL;
t_nodeNum *temp = NULL;
int numAdd = 0;
int len = 0;
int first = 1;
do
{
choice = menu();
switch (choice)
{
case 1:
{
printf("Please enter number : \n");
scanf("%d", &numAdd);
if (first)
{
pnode = (t_nodeNum *)malloc(sizeof(t_nodeNum));
if (pnode == NULL)
{
printf("\n Error in allocation\n");
exit(0);
}
pnode->num = numAdd;
pnode->next = NULL;
first = 0;
head = pnode;
}
pnode = addition(pnode, numAdd);
break;
}
case 4:
{
printf("\n Print List: ");
print_list(head);
break;
}
}
}
while (choice != 5);
return 0;
}
// function menu display menu and return choice
int menu()
{
int choice = 0;
do
{
printf("Please choose option to do: \n");
printf("1. addition\n");
printf("2. deletion\n");
printf("3. search\n");
printf("4. print\n");
printf("5. exit\n");
printf("\n option = ");
scanf("%d", &choice);
}
while (choice < 1 || choice > 5);
return choice;
}
// function addition to add item to linked list in recursion
t_nodeNum* addition(t_nodeNum *p, int numAdd)
{
int len = 0;
if (p == NULL)
{
p = (t_nodeNum *)malloc(sizeof(t_nodeNum));
if (p == NULL)
{
printf("\n Error in allocation\n");
exit(0);
}
p->num = numAdd;
p->next = NULL;
}
else
{
p = addition(p->next, numAdd);
}
return (p);
}
// function print_list to print linked list in recursion
void print_list(t_nodeNum *head)
{
printf("%d ", head->num);
if (head->next == NULL)
{
printf("\n");
return;
}
print_list(head->next);
}
There is problem with the addition function it does not work correctly to add new item to the linked list and I does not know what is wrong please help
After adding new items and do print list it display only the first item
In you main function -
pnode = addition(pnode, numAdd);
instead of pnode you need to pass pnode->next -
pnode = addition(pnode->next, numAdd);
Problem with first call is that pnode is not NULL so it just adds new element at head position replacing previous value and returns.
Therefore, new node is not being created.
I can't figure out why my code breaks. Every thing works, except when I try to reverse the linked list. It "stops working." (This function; void reverseList(struct produceItem** inHead)) Any ideas? I've been stuck on this for some time now. I think the issue might be that it doesn't read a NULL some where, but I cannot figure it out.
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
struct produceItem{
char produce[20];
char type[20];
char soldBy[20];
float price;
int quantityInStock;
struct produceItem *next;
};
struct produceItem* append(struct produceItem *inHead, char *nextProduce, char *nextType, char *nextSoldBy, char *nextPrice, char *nextQuantityInStock){
struct produceItem *temp;
temp =(struct produceItem *)malloc(sizeof(struct produceItem));
strcpy(temp->produce, nextProduce);
strcpy(temp->type, nextType);
strcpy(temp->soldBy, nextSoldBy);
temp->price = atof(nextPrice);
temp->quantityInStock = atoi(nextQuantityInStock);
if(inHead == NULL){
inHead = temp;
temp->next = NULL;
}
else{
temp->next = inHead;
inHead = temp;
}
return inHead;
}
struct produceItem* readData(struct produceItem *inHead){
const char comma[2] = ",";
char *produceTemp;
char *typeTemp;
char *soldByTemp;
char *priceTemp;
char *quantityInStockTemp;
char dataLine[100];
char fileName[] = "AssignmentTwoInput.txt";
FILE *inputFile;
printf("\nFile %s has been read.\n\n", fileName);
inputFile = fopen(fileName, "r");
if( inputFile == NULL){
printf("%sList Does not exist\n", fileName);
return;
}
while((fgets(dataLine, 100, inputFile)) != NULL){
produceTemp = strtok(dataLine, comma);
typeTemp = strtok(NULL, comma);
soldByTemp = strtok(NULL, comma);
priceTemp = strtok(NULL, comma);
quantityInStockTemp = strtok(NULL, comma);
inHead = append(inHead, produceTemp,typeTemp,soldByTemp,priceTemp,quantityInStockTemp);
}
fclose(inputFile);
return inHead;
}
void display(struct produceItem *inHead){
int i = 1;
if(inHead == NULL){
printf("List does not exist.\n");
return;
}
printf("=========================================================================\n");
printf("Item # Produce Type Sold By Price In Stock\n");
printf("==========================================================================\n");
for(i=1; i<27; i++){
//while(inHead != NULL){
printf("\n%5d", i);
printf(" %-12s ", inHead->produce);
printf("%-16s ", inHead->type);
printf("%-16s ", inHead->soldBy);
printf("%3.2f ", inHead->price);
printf("%8d", inHead->quantityInStock);
inHead = inHead->next;
//i++;
}
printf("\n\n");
}
exportData(struct produceItem *n){
char fileName[] = "AssignmentTwoOutput.txt";
FILE *exportFile;
int i =1;
if(n == NULL){
printf("List does not exist.\n");
return;
}
exportFile = fopen(fileName, "w");
//printf("hi");
fprintf(exportFile,"================================================================\n");
//printf("hi");
fprintf(exportFile,"Item# Produce Type Sold By Price In Stock\n");
fprintf(exportFile,"================================================================\n");
for(i=1; i<27; i++){
//while(n->next != NULL){
//printf("hi");
fprintf(exportFile,"\n%3d", i);
fprintf(exportFile," %-12s ", n->produce);
fprintf(exportFile,"%-15s ", n->type);
fprintf(exportFile,"%-15s ", n->soldBy);
fprintf(exportFile,"%3.2f ", n->price);
fprintf(exportFile,"%8d", n->quantityInStock);
n = n->next;
}
printf("\nYour data has been written to AssignmentTwoOutput.txt, thank you.\n\n");
fclose(exportFile);
}
//void recursiveReverse(struct node** head_ref)
//{
//struct node* first;
// struct node* rest;
/* empty list */
// if (*head_ref == NULL)
//return;
/* suppose first = {1, 2, 3}, rest = {2, 3} */
//first = *head_ref;
//rest = first->next;
/* List has only one node */
//if (rest == NULL)
//return;
/* reverse the rest list and put the first element at the end */
//recursiveReverse(&rest);
//first->next->next = first;
/* tricky step -- see the diagram */
//first->next = NULL;
/* fix the head pointer */
//*head_ref = rest;
//}
void reverseList(struct produceItem** inHead){
//printf("1");
struct produceItem* first;
struct produceItem* follow;
//printf("2");
if (*inHead==NULL){
// printf("3");
printf("List does not exist.\n");
return;}
first = *inHead;
//printf("4");
follow = first->next;
if(follow==NULL)
//printf("5");
return;
reverseList(&follow);
first->next->next = first;
first->next = NULL;
*inHead = follow;
}
int main (void){
int choice;
struct produceItem *head;
while(1){
printf("List of Operations\n");
printf("===============\n");
printf("1. Stock Produce Department\n");
printf("2. Display Produce Inventory\n");
printf("3. Reverse Order of Produce Inventory\n");
printf("4. Export Produce Inventory\n");
printf("5. Exit\n");
printf("Enter you choice: ");
scanf("%d", &choice);
if(choice <= 0 || choice > 5){
printf("Enter a valid response please: \n");
exit(0);
}
switch(choice){
case 1:
//reading from thefile
head = readData(head);
break;
case 2:
//displays the list
display(head);
break;
case 3:
//reverse the list
reverseList(&head);
break;
case 4:
exportData(head);
break;
case 5:
//Exits the operation
printf("Exiting, Thank you.");
exit(0);
break;
}
}
}
in this recursive function:
void reverseList(struct produceItem** inHead){
//printf("1");
struct produceItem* first;
struct produceItem* follow;
//printf("2");
if (*inHead==NULL){
// printf("3");
printf("List does not exist.\n");
return;}
first = *inHead;
//printf("4");
follow = first->next;
if(follow==NULL)
//printf("5");
return;
reverseList(&follow);
first->next->next = first;
first->next = NULL;
*inHead = follow;
}
This function will run recursively through the list.
Ok lets look at your code:
2 local variables (does nothing really)
code to exit if input is null (mostly for safety)
You set your local variables to the current and next node.
code to exit if this is the last node in the list.
You call your function recursively.
Note that at this stage actually nothing has happened.
This means that your processing (the lines at the end of your function) will happen in reverse order of the list. From back to front.
This seems correct for what you want to do.
Next line:
first->next->next = first;
This seems correct as it would set the next of the "following" node to point to this one. As in change the direction of the next pointer within the list.
Now you have this line:
first->next = NULL;
Remember that we said your "processing" of the nodes will happen in the reverse order. So effectively one by one you will set all your next pointers to NULL. Which I think will completely disconnect your queue completely?
The last line I understand is simply to enable you to find the new head pointer for your queue and that seems fine.
btw doing this kind of algorithm with recursion is a bad idea normally.
As you can easily cause stack overflow problems if your list is getting long.
Also if for some reason your list has a problem and it is circular then it is difficult to detect that and not cause problems.
Also generally in terms of performance this type of recursive algorithm will be slower than just a proper loop implementation.
Pseudo code to "reverse" list:
reverseList(** head)
{
current = head
prev = null
next = null
int i = 0;
while (current)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
i++;
if (i > MAX) reportError();
}
head = prev;
}