Circular Linked list is crashing while trying to print [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
So I'm working on a program, that will eventually simulate a lame version of duck duck goose (actually called duck duck boot by the professor). When I read the problem circular linked list is what popped out towards me. Though I am very new at using linked lists in general.
It seems like the program is creating and assigning the nodes, but I crash when I try to print them.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char name[20];
struct jimmysFriend *next;
} jimmysFriend;
jimmysFriend *createNode();
void populateList(jimmysFriend *bestFriend, int numberOfFriends);
//void duckDuckBoot();
void printList(jimmysFriend *bestFriend);
int main(void) {
int i;
int cases;
int numberOfFriends;
scanf("%d", &cases);
for (i = 0; i < cases; i++) {
scanf("%d", &numberOfFriends);
jimmysFriend *bestFriend; //head
bestFriend = NULL;
populateList(bestFriend, numberOfFriends);
printList(bestFriend);
}
return 0;
}
void populateList(jimmysFriend *bestFriend, int numberOfFriends) {
int i; //Where I actually create the circular list.
jimmysFriend *aFriend;
for (i = 0; i < numberOfFriends; i++) {
aFriend = createNode();
if (bestFriend == NULL) {
bestFriend = aFriend;
aFriend->next = aFriend;
} else
if (bestFriend != NULL) {
jimmysFriend *temptr;
aFriend->next = bestFriend;
temptr = bestFriend;
while (temptr->next != bestFriend) {
temptr = temptr->next;
}
temptr->next = aFriend;
}
}
}
jimmysFriend *createNode() { //Creates a node
jimmysFriend *aFriend;
aFriend = malloc(sizeof(jimmysFriend));
if (aFriend != NULL) {
scanf("%s", aFriend->name);
}
return aFriend;
}
void printList(jimmysFriend *bestFriend) { //Problem area?
jimmysFriend *temptr;
temptr = bestFriend;
while (temptr->next != bestFriend) {
printf("%s\n", temptr->name);
temptr = temptr->next;
}
}

There are 2 problems.
The first is that you're not passing bestFriend to populateList() by address, so it doesn't get changed. populateList() should look like this:
void populateList(jimmysFriend **bestFriend, int numberOfFriends){
int i; //Where I actually create the circular list.
jimmysFriend* aFriend;
for(i = 0; i < numberOfFriends; i++){
aFriend = createNode();
if(*bestFriend == NULL){
*bestFriend = aFriend;
aFriend->next = aFriend;
}
else if(*bestFriend != NULL){
jimmysFriend* temptr;
aFriend->next = *bestFriend;
temptr = *bestFriend;
while(temptr->next != *bestFriend){
temptr = temptr-> next;
}
temptr->next = aFriend;
}
}
}
And then you call it like this:
populateList(&bestFriend, numberOfFriends);
The second problem is that your condition for the printList() loop is wrong. There is more than one way of writing it, but this do loop works:
void printList(jimmysFriend* bestFriend){ //Problem area?
if (bestFriend != NULL) {
jimmysFriend* temptr = bestFriend;
do {
printf("%s\n", temptr->name);
temptr = temptr->next;
} while (temptr != bestFriend);
}
}
Reference: Circular Linked List

In populateList() Jimmy's best friend isn't really pointed at the head of the list when you are done with the function. The assignment that you make in populateList() is lost.
Pass jimmy's best friend as the address of the pointer to the function. So populateList() will accept jimmysFriend **bestFriend. Then when you try to store the head there you will assign the node you want to be the head to *bestFriend.
You can always validate that by checking if Jimmy's best friend is NULL right before you call printList().
populateList ( &bestFriend, numberOfFriends);

Related

Linked list — deletion of nodes which contain prime numbers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have written a code in the C language which will create a linked list. The linked list structre has two fields, namely data and next; data contains integer data, next is a structure pointer.
The program asks the user to input data into the list. Once the data has been entered, the program will go through the list and check which data in the node contains a prime number. If it finds one such node, it will delete it and link the next node to the previous node, but I am getting a segmentation fault error and I am unable to solve.
I am putting below the code. Can you please be kind enough to help me solve it as I do not know how to find the problem?
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node *nptr;
nptr H, h, n;
void deletetheprime(struct node**);
void display();
int prime(int);
int main() {
nptr temp1, temp;
int i, N, p;
printf("\n if list is completed enter 999\n");
for (;;) {
printf("\n enter the data \n");
scanf("%d", &i);
if (i == 999)
break;
else
if (H == NULL) {
H = h = (nptr)malloc(sizeof(struct node));
H->data = i;
H->next = NULL;
} else {
n = (nptr)malloc(sizeof(struct node));
n->data = i;
n->next = NULL;
h->next = n;
h = n;
}
}
printf("\n data before deletion\n");
display();
temp = H;
while (temp != NULL) {
N = temp->next->data;
p = prime(N);
if (p == 1) {
deletetheprime(&temp);
} else {
temp = temp->next;
}
}
printf("\n the data after deletion is\n");
display();
return 0;
}
void deletetheprime(struct node **temp2) {
nptr temp, temp1;
temp = *temp2;
temp1 = temp->next;
temp->next = temp->next->next;
free(temp1);
temp = temp->next;
}
int prime(int i) {
int j, p = 0;
for (j = 2; j <= i / 2; i++) {
if (i % j == 0) {
break;
}
}
if (j > i / 2) {
p = 1;
}
return p;
}
void display() {
nptr temp;
temp = H;
while (temp != NULL) {
printf("\n %d", temp->data);
temp = temp->next;
}
}
The problem is here:
while (temp != NULL) {
N = temp->next->data;
When you reach the last element of the list, temp is not NULL, but temp->next is so temp->next->data has undefined behavior.
There are other problems:
your prime() function is inefficient and will return 1 for 0 and 1.
you deletetheprime() function deletes the node and updates the pointer in the callers scope, but the caller does not update the link in the previous node nor the H pointer if the deleted node is the first.
you use global variables for no good reason, you should pass H to display() and make all variables local in main().
you never free the allocated objects, it is good style to free everything you allocate.
you should not hide pointers behind typedefs, make node a typedef for struct node but keep pointers visible, it is a good habit to avoid confusing both the reader and the programmer.
To delete the node, you should use the pointer to link trick:
for (struct node **p = &H; *p;) {
if (prime((*p)->data) {
nptr np = *p;
*p = np->next;
free(np);
} else {
p = &(*p)->next;
}
}
p initially points to the head pointer H and subsequently points to the next member of the previous node. It can be used to update the head pointer or the link in the previous node when a node to be deleted is found.
Here is a corrected and simplified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
int isprime(int n) {
if (n < 2)
return 0;
if (n % 2 == 0)
return n == 2;
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
void display(const node *temp) {
while (temp != NULL) {
printf(" %d", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(void) {
node *H = NULL;
node **lastp = &H;
node *n;
int i;
printf("Enter values, when list is completed enter 999\n");
for (;;) {
printf("\n enter the data: ");
if (scanf("%d", &i) != 1 || i == 999)
break;
n = malloc(sizeof(*n));
if (n == NULL)
break;
n->data = i;
n->next = NULL;
*lastp = n;
lastp = &n->next;
}
printf("\n data before deletion: ");
display(H);
for (node **p = &H; *p;) {
if (isprime((*p)->data)) {
n = *p;
*p = n->next;
free(n);
} else {
p = &(*p)->next;
}
}
printf("\n the data after deletion is: ");
display(H);
/* free the list */
while (H != NULL) {
n = H;
H = n->next;
free(n);
}
return 0;
}
I shall attribute your please solve it! stance to your poor command of the English language. Please learn to improve both your communications and your programming skills by carefully studying answers on this site.
The problem occurs here, in main
while(temp!=NULL)
{
N=temp->next->data;
...
You are checking if temp is not NULL, which is correct, but accessing data of next node, which can be NULL, and has to be NULL near the end of the list, which leads to undefined behavior.
Simply modify it to
while(temp!=NULL)
{
N=temp->data;
...
Where you are sure that temp isn't NULL and you won't get segmentation error here. And it'll work.
Or if you need to access data of temp->next->next node, you've got to check if next->next isn't NULL as well.
while(temp!=NULL)
{
if (temp->next->next != NULL)
{
N=temp->next->data;
}
else // temp->next->next is NULL so you can't access the data
...

Pointer to pointer to Struct [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to do a C program that receives Strings and store them into structs dynamically, and after the passing strings part, I will show witch of them was written most. But I'm having trouble coding the pointers to pointers to structs. I'm trying to do something like the image that I draw here.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Word{
char* palavra;
int aparicoes;
} ;
struct word createWord(char* str){
struct Word *newWord = malloc(sizeof(struct Word));
assert(newWord != NULL);
newWord->palavra = strdup(str);
newWord->aparicoes = 1;
return newWord;
}
int main (){
char* tempString;
struct Word** lista;
int triggrer = 1;
int i = 0;
while (triggrer == 1)
{
scanf("%s", tempString);
if (strcmp(tempString , "fui") == 0)
triggrer = 0;
else
{
while(*(&lista+i*sizeof(lista)) != NULL){
i++;
}
if(i == 0){
lista = malloc(sizeof(struct Word));
}
else{
lista = (struct Word*) realloc(lista, sizeof(struct Word) + i*sizeof(struct Word));
}
}
}
return 0;
}
There is no allocation of the pointers anywhere.
You need something like this:
lista = (struct Word**) malloc(sizeof(struct Word*));
*lista = NULL;
the above allocate one pointer to pointer to struct. the pointer to struct itself is null.
Now, not sure what you want to achieve by
while(*(&lista+i*sizeof(lista)) != NULL){
i++;
}
If you want to find the end of you array of pointers, presuming that the last pointer is NULL, then this is the code to do it:
while (*(lista + i) != NULL) i++;
Also, there are some typos in the code. This would compile and work. But I personally, recommend to use normal array of pointers (i.e. just keep the size of the array in another variable).
struct Word{
char* palavra;
int aparicoes;
} ;
struct Word * createWord(char* str){
struct Word *newWord = (struct Word *)malloc(sizeof(struct Word));
newWord->palavra = strdup(str);
newWord->aparicoes = 1;
return newWord;
}
int main()
{
char tempString[1024];
struct Word** lista;
int triggrer = 1;
int i = 0;
lista = (struct Word**)malloc(sizeof(struct Word*));
*lista = NULL;
while (triggrer == 1)
{
scanf("%s", tempString);
if (strcmp(tempString , "fui") == 0)
triggrer = 0;
else
{
while(*(lista+i) != NULL){
i++;
}
lista = (struct Word**)realloc(lista, (i+1) * sizeof(struct Word*));
*(lista+i) = createWord(tempString);
*(lista+i+1) = NULL;
}
}
return 0;
}

Simple C trie program goes wrong (segmentation fault) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
In order to understand tries I am creating this very simple C program that takes from user 10 nums from 0 to 9 as children of the trie. The final step is to print this nums with the function print, but I am getting a segmentation fault:
#include <stdio.h>
#include <stdlib.h>
typedef struct list
{
int data;
struct list *ar[10];
} list;
void insert(list *head);
void print(list *head);
int main(void)
{
printf("hello\n");
list *root = malloc(sizeof(list));
insert(root);
print(root);
}
void insert(list *head)
{
int a, i;
if (head == NULL) {
return;
}
for (i = 0; i < 10; i++) {
printf("Give Num 0-9\n");
scanf("%i", &a);
head->ar[a] = malloc(sizeof(head));
head = head->ar[a];
head->data = a;
}
}
void print(list *head)
{
if (head == NULL) {
return;
}
while (head != NULL) {
for (int i = 1; i < 10; i++) {
if (head->ar[i] != NULL) {
printf("%i", i);
head = head->ar[i];
break;
}
}
}
printf("\n");
}
There are several issues with your code:
The first mention of malloc doesn't actually initialize the memory (the ar field). You should initialize it properly
list *root = malloc(sizeof(list));
Is missing initialization, e.g.
root->data = 0;
for (size_t ii = 0; ii < 10; ii++) {
root->ar[ii] = NULL;
}
When you are actually gathering input, you allocate only enough memory for the pointer, not for the actual list itself.
head->ar[a] = malloc(sizeof(head));
should be initialized as above (head = malloc(sizeof(list)); for (size_t ...
There seems to be an infinite loop when actually running your program (after correcting all these issues).
EDIT: Remove calloc...

I have a segmentation error in C

I have a Segmentation error, maybe a lot more after I run it, but I can't check anything else now because of that.
The program should work like this:
When user types in 5 numbers, they should print out in ascending order
If the user enter the number already exit, then remove the original value
If the user enter a native value, print List Backwards
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
struct element {
int i;
struct element *next;
};
void insert (struct element **head, struct element *new)
{
struct element *temp;
temp = *head;
while(temp->next != NULL)
{
if((*head==NULL))
{
head = malloc(sizeof(struct element));
//temp->i = i;
temp->next = new;
new = temp;
}
else if(temp->i == new->i)
{
new = malloc(sizeof(struct element));
free(new);
//purge(&head,&new);
}
else if(temp->i < new->i)
{
temp->i = new->i;
}
else if(temp->i > new->i)
{
new = new->next;
}
}
}
void purge (struct element *current, struct element *predecessor)
{
predecessor->next = current -> next;
free(current);
}
void printList (struct element *head)
{
while(head)
{
printf("%d", head -> i);
head = head->next;
}
}
void printListBackwards (struct element *ptr)
{
if(ptr == NULL)
{
printf("list is empty \n");
return;
}
if(ptr->next != NULL)
{
printListBackwards(ptr->next);
}
printf("print %p %p %d\n", ptr, ptr->next, ptr->i);
}
int main()
{
int n = 0;
int count = 5;
printf("enter a Number: \n");
scanf("%d",&n);
struct element *new;
new = malloc(sizeof(struct element));
struct element *head = NULL;
new->i = n;
while(count!=0)
{
insert(&head,new);
printList(head);
count++;
}
}
In the main() function, you only allocate and create one element with malloc(); you then try to add it to your list 5 times. This is going to cause confusion. You should allocate a node once for each element you add to the list.
struct element *head = NULL;
while (count!=0)
{
printf("enter a Number: \n");
if (scanf("%d", &n) != 1)
break;
struct element *new = malloc(sizeof(struct element));
if (new == 0)
break;
new->i = n;
new->next = NULL;
insert(&head, new);
printList(head);
count--;
}
Note that the revised code checks the result of both scanf() and malloc(). It also sets the new element's next pointer to NULL. And it counts down rather than up; this is likely to use less memory.
I've not tested this so there could be (and very probably are) other problems, but this is likely to work better (fix some of the problems, but not all of the problems).
You do need to learn how to use a debugger, at least enough to get the stack trace so you know which line of code is causing the crash.
Do you really need a linked list? It seems the problem statement says that user can enter only 5 numbers... if so, why not just use an array of 5 elements? Following are some ideas.
enum { N = 5 };
typedef struct Element {
int number;
bool present;
} Element;
Element elements[ N ];
Init:
for( i = 0; i != N; ++i ) {
elements[i].number = 0;
elements[i].present = false;
}
Insert "inputNumber":
for( i = 0; i != N; ++i ) {
if( elements[i].present == false ) {
elements[i].number = inputNumber;
elements[i].present = true;
}
}
Remove "removeNumber":
for( i = 0; i != N; ++i ) {
if( elements[i].number == removeNumber ) {
elements[i].present = false;
}
}
Print Backwards:
for( i = N; i != 0; --i ) {
printf( "%d\n", elements[i].number );
}
In main, you should set new->next = NULL; [or somewhere in the beginning of insert]
This bit of code is just messed up:
head = malloc(sizeof(struct element));
//temp->i = i;
temp->next = new;
new = temp;
You should, probably, set
*head = new;
But you also need to set *head->next = NULL;
This bit is complete nonsense:
new = malloc(sizeof(struct element));
free(new);
//purge(&head,&new);
You would want to free new.
else if(temp->i < new->i)
{
temp->i = new->i;
}
else if(temp->i > new->i)
{
new = new->next;
}
This is also quite wrong. I think the last one should do
temp = temp->next;
Do yourself a favour, draw up on a piece of paper, boxes
HEAD
!
v
+-----+
! i=3 !
+-----+ +-----+
!------->! i=4 !
+-----+
!-------->NULL
And then walk through it and see how your code inserts, removes, etc.
[Can I also suggest that you don't use C++ reserved words in your code - new is a C++ reserved word. It means that your code CERTAINLY won't compile in a C++ compiler, which is a bad thing to prevent. Sure, there are several other things that may need changing, but a simple thing like "not calling a variable new" shouldn't be one of the things it fails on].

Can't printf contents of a single-linked-list of strings

I have written this piece of code here and I have linked it alright with a couple of other functions and a main and it is working no problem and compiling without warnings (I am using the gcc compiler).
I use an array of pointers (archive.products[]) as an entrance point to multiple lists of strings. I'm still at the beginning so the lists have only one node each.
The problem I've got is that I can't get the function lprintf to show on screen the components of the one-node lists of strings I have created. Note that the printf located inside the push function prints alright. So I know that push is doing it's job...
If anyone has any idea about what might I be doing wrong please drop a reply below.
Thank-you in advance!
#define line_length 61
#define max_products 10
struct terminal_list {
char terminal[line_length];
struct terminal_list *next;
}*newnode, *browser;
typedef struct terminal_list tlst;
struct hilevel_data {
char category[line_length];
tlst *products[max_products];
};
typedef struct hilevel_data hld;
void import_terms(FILE *fp, hld archive){
char buffer[line_length];
char filter_t[3] = "}\n";
int i = 0, j = 0;
while (!feof(fp)) {
fgets(buffer, line_length, fp);
if (strcmp(buffer, filter_t) == 0) {
return;
}
head_initiator(archive, i);
push(buffer,archive, i);
lprintf();
i++;
}
}
void head_initiator(hld archive, int i){
browser = NULL;
archive.products[i] = NULL;
}
void push(char buffer[],hld archive, int i){
newnode = (tlst *)malloc(sizeof(tlst));
strcpy(newnode->terminal, buffer);
// printf("%s", newnode->terminal);
archive.products[i] = browser;
newnode->next = browser;
browser = newnode;
}
void lprintf(){
tlst *p;
p = browser;
if (p = NULL){
printf("empty\n");
}
while(p!=NULL){
printf("%s\n", p->terminal);
p=p->next;
}
}
On : void lprintf()
if (p = NULL)
should be
if (p == NULL)
if (p = NULL){
printf("empty\n");
}
I think you mean
if (p == NULL){
printf("empty\n");
}
You're effectively emptying the list with p = NULL.

Resources