why this search function in list doesn't work? - c

I made this easy linked list and i would like to add element in it checking if the element is already present.
If the new element to add is already present, the node won't be inserted in the list.
Well, the problem begins when a insert the second element; gdb says:
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554bda in search (name=0x5555557576d0 "alfred")
at Scrivania/test.c:*line*
*line* while(strncmp(name,temp->name,strlen(name))!=0)
Code:
typedef struct node{
char *name;
struct node *n;
} N;
N *h = NULL;
void insert(char *name){
N *temp = malloc(sizeof(N));
if (h == NULL){
h=temp;
temp->n = NULL;
temp->name = strdup(name);
} else {
N *curr = h;
while (curr->n != NULL)
curr = curr->n;
curr->n = temp;
temp->name = strdup(name);
}
}
N *search(char *name) {
N *temp = h;
if (temp == NULL)
return NULL;
else{
while (strncmp(name, temp->name, strlen(name)) != 0)
temp=temp->n;
return temp;
}
}
int main() {
char *name = N * temp=search(name); //getting input
if (temp == NULL)
insert(name);
//these four lines sequence repeat for every input
}

Related

C - How to print a string element in a pointer to struct?

I'm relearning linked list data structure and I stumbled upon this problem.
#include <stdlib.h>
#include <stdio.h>
struct Node{
char url[50];
struct Node *next;
};
typedef struct Node Node;
void add_url(Node * h, Node * c, Node * n){
Node * temp;
temp = malloc(sizeof(Node));
printf("\nType or paste your URL: ");
scanf("%s", temp->url);
if(h == NULL){
h = temp;
h->next = NULL;
c = h;
}else{
c->next = temp;
c = c->next;
n = c->next;
}
}
int main(){
Node * h = NULL; // head
Node * c; // current
Node * n; // next
add_url(h, c, n);
printf("%s", h->url);
return 0;
}
Why is the output NULL? How exactly do you get a string input from a pointer to struct?
Here is a possible solution. I have added some checks to avoid segmentation fault (access violation), buffer overflow in scanf, initialized variables and the function now returns the new head (Could instead return current node).
#include <stdlib.h>
#include <stdio.h>
struct Node {
char url[50];
struct Node* next;
};
typedef struct Node Node;
Node *add_url(Node** h, Node** c, Node** n) {
Node* temp;
if ((h == NULL) || (c == NULL) || (n == NULL))
return NULL;
if ((temp = malloc(sizeof(Node))) == NULL)
return NULL;
printf("\nType or paste your URL: ");
if (scanf("%50s", temp->url) != 1)
return NULL;
if (*h == NULL) {
temp->next = NULL;
*h = temp;
*c = *h;
}
else {
(*c)->next = temp;
*c = temp;
*n = temp;
}
return *h;
}
int main() {
Node* h = NULL; // head
Node* c = NULL; // current
Node* n = NULL; // next
if (add_url(&h, &c, &n) == NULL) {
perror("add_url failed: ");
return 1;
}
printf("%s", h->url);
return 0;
}

Stack push function using c, implemented using doubly linked list

I am trying to implement Hierholzer's algorithm using C.
I have made a push function for a simple stack implemented using doubly linked list but the pointer always moves on to the else condition, even when the starting node is empty.
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<stddef.h>
typedef struct node
{
int source;
int num;
struct node *l, *r;
int done;
}node;
void push(int source, int num, struct node *head)
{
node *n = malloc(sizeof(node));
n->num = num;
n->l = NULL;
n->done = 0;
n->source = source;
if (*head == NULL)
{
head = n;
head -> r = NULL;
}
else
{
n -> r = head;
head->l = n;
head = n;
}
}
int pop(node *head)
{
if(head == NULL)
{
return -1;
}
else
{
node *temp = head;
head = head->r;
int num = temp->num;
free(temp);
return num;
}
}
void append(node *extra, node *head)
{
node *temp = extra;
while(temp->r != NULL)
{
temp = temp->r;
}
temp->r = head;
head->l = temp;
head = extra;
}
node** read(int num)
{
char a[2000] = "Assignment1.txt" ,c[1000];
FILE *f = fopen(a,"r");
printf("Got file\n");
node *adj[num];
int i=0;
node *l;
printf("l: %d\n", l);
while(fscanf(f,"%s",c))
{
char *p = strtok(c, ",");
while(p!=NULL)
{
push(i, atoi(p), l);
p = strtok (NULL, ",");
}
adj[i++] = l;
}
printf("Adjacency list created\n");
return adj;
}
node* euler(node *adj[],int n, int i)
{
node *cpath = NULL;
node *fin = NULL;
node *extra;
node *temp = adj[i];
node *tempi;
while(temp!=NULL)
{
if(temp->r->r == NULL)
{
tempi = temp;
}
if(temp->done == 0)
{
temp->done = 1;
push(i, temp->num, cpath);
extra = euler(adj, n, temp->num);
append(extra, cpath);
}
else
{
temp = temp->r;
}
}
while(tempi->l != NULL)
{
push(i,tempi->num, fin);
extra = euler(adj, n, tempi->num);
append(tempi, fin);
tempi = tempi->l;
}
if(tempi != NULL)
{
push(i,tempi->num, fin);
extra = euler(adj, n, tempi->num);
append(tempi, fin);
}
return fin;
}
int main()
{
int n;
printf("Enter the number of vertices: ");
scanf("%d", &n);
node **adj = read(n);
node *fin = euler(adj, n, 0);
node *temp = fin;
while(temp!=NULL)
{
printf("%d ", temp->num);
temp = temp->r;
}
return 0;
}
I am yet to debug the entire code but I am getting stuck at the read() function where the input is an Assignment1.txt which includes:
2,3
3,1
1,2
I am not able to understand why I am getting a segmentation fault.
The function deals with a copy of the value of the passed to it pointer to the head node. So the original pointer itself is not changed in the function. It is the copy of the value of the passed pointer that is changed within the function.
You need to pass the pointer by reference that is indirectly through pointer to the pointer.
The function can be declared and defined the following way.
int push( struct node **head, int source, int num )
{
node *n = malloc(sizeof(node));
int success = n != NULL;
if ( success )
{
n->source = source;
n->num = num;
n->done = 0;
n->l = NULL;
n->r = *head;
if ( *head != NULL ) ( *head )->l = n;
*head = n;
}
return success;
}
In read function you are returning adj. However, it is a local variable. You are not using malloc type function. So, local variables destroy after function returned. Therefore, you are trying to access a random place when you try to access adj in main. I guess the problem is caused by this reason.

Implementing mergesort on a linked list

I was tasked with implementing a merge sort algorithm on a list written in C/C++. I have the general idea down, wrote my code and have successfully compiled it. However, when I run it, it will begin fine but then hang on "prepared list, now starting sort" without giving any kind of error. I have tried to look through my code but I am at a complete loss as to what the issue could be. I am also pretty amateurish with debugging, so using gdb to the best of my abilities has lead me no where. Any advice or tips would be a tremendous help, thank you all!
#include <stdio.h>
#include <stdlib.h>
struct listnode
{
struct listnode *next;
int key;
};
//Finds length of listnode
int
findLength (struct listnode *a)
{
struct listnode *temp = a;
int i = 0;
while (temp != NULL)
{
i++;
temp = temp->next;
}
return i;
}
struct listnode *
sort (struct listnode *a)
{
// Scenario when listnode is NULL
if (findLength (a) <= 1)
return a;
//Find middle
int mid = findLength (a) / 2;
struct listnode *temp = a;
struct listnode *first = a;
struct listnode *second;
for (int i = 0; i < mid - 1; i++)
{
temp = a->next;
}
second = temp->next;
temp->next = NULL;
//Recursive calls to sort lists
first = sort (first);
second = sort (second);
if (first != NULL && second != NULL)
{
if (first->key < second->key)
{
a = first;
first = first->next;
}
else
{
a = second;
second = second->next;
}
}
struct listnode *head = a;
struct listnode *tail = a;
while (first != NULL && second != NULL)
{
if (first->key < second->key)
{
tail = first;
first = first->next;
tail = tail->next;
}
else
{
tail = second;
second = second->next;
tail = tail->next;
}
}
if (first == NULL)
{
while (second != NULL)
{
tail = second;
second = second->next;
tail = tail->next;
}
}
while (first != NULL)
{
tail = first;
first = first->next;
tail = tail->next;
}
return a;
}
Here is the test code provided, written in C:int
main (void)
{
long i;
struct listnode *node, *tmpnode, *space;
space = (struct listnode *) malloc (500000 * sizeof (struct listnode));
for (i = 0; i < 500000; i++)
{
(space + i)->key = 2 * ((17 * i) % 500000);
(space + i)->next = space + (i + 1);
}
(space + 499999)->next = NULL;
node = space;
printf ("\n prepared list, now starting sort\n");
node = sort (node);
printf ("\n checking sorted list\n");
for (i = 0; i < 500000; i++)
{
if (node == NULL)
{
printf ("List ended early\n");
exit (0);
}
if (node->key != 2 * i)
{
printf ("Node contains wrong value\n");
exit (0);
}
node = node->next;
}
printf ("Sort successful\n");
exit (0);
}
You're close, but with some silly errors. Check the append operations in the merge step. They're not doing what you think they are. And of course you meant temp = temp->next; in the splitting loop.
If gdb is overwhelming, adding printf's is a perfectly fine way to go about debugging code like this. Actually you want to write a list printing function and print the sublists at each level of recursion plus the results of the merge step. It's fun to watch. Just be neat and delete all that when you're done.
Here's code that works for reference:
struct listnode *sort(struct listnode *lst) {
if (!lst || !lst->next) return lst;
struct listnode *q = lst, *p = lst->next->next;
while (p && p->next) {
q = q->next;
p = p->next->next;
}
struct listnode *mid = q->next;
q->next = NULL;
struct listnode *fst = sort(lst), *snd = sort(mid);
struct listnode rtn[1], *tail = rtn;
while (fst && snd) {
if (fst->key < snd->key) {
tail->next = fst;
tail = fst;
fst = fst->next;
} else {
tail->next = snd;
tail = snd;
snd = snd->next;
}
}
while (fst) {
tail->next = fst;
tail = fst;
fst = fst->next;
}
while (snd) {
tail->next = snd;
tail = snd;
snd = snd->next;
}
tail->next = NULL;
return rtn->next;
}
On my old MacBook this sorts 10 million random integers in a bit over 4 seconds, which doesn't seem too bad.
You can also put the append operation in a macro and make this quite concise:
struct listnode *sort(struct listnode *lst) {
if (!lst || !lst->next) return lst;
struct listnode *q = lst, *p = lst->next->next;
while (p && p->next) {
q = q->next;
p = p->next->next;
}
struct listnode *mid = q->next;
q->next = NULL;
struct listnode *fst = sort(lst), *snd = sort(mid);
struct listnode rtn[1], *tail = rtn;
#define APPEND(X) do { tail->next = X; tail = X; X = X->next; } while (0)
while (fst && snd) if (fst->key < snd->key) APPEND(fst); else APPEND(snd);
while (fst) APPEND(fst);
while (snd) APPEND(snd);
tail->next = NULL;
return rtn->next;
}
Does it have to be a top down merge sort? To get you started, here's a partial fix, didn't check for other stuff. The | if (first != NULL && second != NULL) | check isn't needed since the prior check for length <= 1 takes care of this, but it won't cause a problem.
while (first != NULL && second != NULL)
{
if (first->key < second->key)
{
tail->next = first;
tail = first;
first = first->next;
}
else
{
tail->next = second;
tail = second;
second = second->next;
}
}
if (first == NULL)
{
tail->next = second;
}
else
{
tail->next = first;
}
}

Linked list only prints the first value of first list

I have a program where three values are inserted into linked lists. When I try to iterate through the list I only get the first value printed. Sorry if the function names are confusing I'm still new to c and I'm trying to use the function and variable names gave me just to make my life easier when taking a test. I'm also pretty unfamiliar with debugger and how I would use it to find out what is going on here. Thanks in advance.
void program_header(char i[]);
Node *allocateNode(int iNewInfo);
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes);
Node *insertLL(Node **ppHead, int iNewInfo);
void printLL(Node *pHead);
int main(int argc, char *argv[])
{
program_header(argv[0]);
insertLL(&pHead, 84);
insertLL(&pHead, 45);
insertLL(&pHead, 81);
printLL(pHead);
return 0;
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct Node
{
int iInfo;
struct Node *pNext;
}Node;
Node *pHead = NULL;
Node *pNew = NULL;
Node *pPrecedes = NULL;
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew == NULL)
printf("Memory allocation error");
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
return pNew;
}
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
printf("Found! %d\n", iMatch);
return p;
if (iMatch < p->iInfo)
return NULL;
*ppPrecedes = p;
}
return NULL;
}
Node *insertLL(Node **ppHead, int iNewInfo)
{
Node *pFind;
// see if it already exists
pFind = searchLL(*ppHead, iNewInfo, &pPrecedes);
if(pFind != NULL)
return pFind;
// Doesn't already exist. Allocate a node and insert it
pNew = allocateNode(iNewInfo);
if(pPrecedes == NULL)
{ //insert at head
pNew->pNext = *ppHead;
*ppHead = pNew;
}
else
{ //insert after a node
pNew->pNext = pPrecedes->pNext;
pPrecedes->pNext = pNew;
}
return pNew;
}
void printLL(Node *pHead)
{
Node *p;
printf("iInfo Values\n");
for (p = pHead; p != NULL; p = p->pNext)
{
printf("%d\n", p->iInfo);
}
p = pHead;
}
void program_header(char i[])
{
int j, n = strlen(&i[2]);
char *name = &i[2], border[n], dash = '-';
// loads dashes into array
for(j = 0; j < n; j++)
border[j] = dash;
border[j] = '\0';
// print header
printf("\n~%s~\n~%s~\n~%s~\n\n"
, border, name, border);
}
I believe your problem is in your search method. I have reformatted it to show the way that it is currently behaving. To help in making your code more readable and to avoid these type of errors you should get in the habit of using braces in your if statements even if they are only one line.
This is your current code
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
{
printf("Found! %d\n", iMatch);
}
return p;
if (iMatch < p->iInfo)
{
return NULL;
}
*ppPrecedes = p;
}
return NULL;
}
Notice in the for loop that no matter if a match is found or not you are always returning p which is really pHead. Then in your insert code you are checking to see if the item is found in the list. Since you always return head it thinks that the item is in the list and never adds a new item.
I haven't tested this, but I believe this is the change you would need to make. You are expecting the search to return a node if the value is already in the list. So you want to return p if there is a match, otherwise you want to return NULL:
Node *searchLL(Node *pHead, int iMatch, Node **ppPrecedes)
{
Node *p;
for (p = pHead; p != NULL; p = p->pNext)
{
if (iMatch == p->iInfo)
{
printf("Found! %d\n", iMatch);
return p;
}
if (iMatch < p->iInfo)
{
return NULL;
}
*ppPrecedes = p;
}
return NULL;
}
correct this
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew == NULL)
printf("Memory allocation error");
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
return pNew;
}
to this
Node *allocateNode(int iNewInfo)
{
// to allocate a new node
pNew = malloc(sizeof(Node));
if (pNew){
pNew->iInfo = iNewInfo;
pNew->pNext = NULL;
}else{
printf("Memory allocation error");
}
return pNew;
}

Simplest Linked List Creation and Printing Data

The following is a simple code segment in C to create a linked list and print all elements contained in the list.
User is asked to input integer data till a zero is entered which marks the termination of user input; Once data is saved in the linked list, the program prints all elements stored in the list and then completes its execution.
I can't make it run, every time it gives a "Segmentation fault" error, please check and tell me where I'm wrong (using gcc 4.8.2)
Code :
struct node
{
int data;
struct node * next;
};
struct node * createLinkedList()
{
int x;
struct node * start;
start = NULL;
printf("Input 0 to end, Insert elements :\n");
for(scanf("%d", &x); x ;scanf("%d", &x))
{
struct node * temp = (struct node *) malloc(sizeof(struct node));
if (temp)
{
temp->data = x;
temp->next = NULL;
if(start == NULL) {
start = temp;
} else {
start->next = temp;
start = temp;
}
}
}
return start;
}
void printLinkedList(struct node * start)
{
if (start == NULL) {
printf("Linked List is empty!\n");
} else {
printf("\nPrinting Linked List : \n");
struct node * s;
s = start;
while(s != NULL)
{
printf("%d\n", s->data);
s = s->next;
}
}
}
int main(int argc, char const *argv[])
{
struct node * start;
start = NULL;
start = createLinkedList();
printLinkedList(start);
return 0;
}
This part of code
if(start == NULL) {
start = temp;
} else {
start->next = temp;
start = temp;
}
is invalid. There has to be
if(start == NULL) {
start = temp;
} else {
temp->next = start;
start = temp;
}
Also you need to have a function that deletes all nodes of the list.

Resources