For homework I was given this code with the directive to implement a recursive function that calls itself on the next node in the list in main unless the current node is NULL or the value of the current node is equal to 'target'
My recent attempt is the fenced part of the code below. I can get it to print 0, but that's not the whole list. I'm not sure what I'm doing wrong as I've not had much experience with linked lists and nodes.
typedef struct node {
struct node* next;
unsigned short index;
char* value;
} node;
node* create_node(unsigned short index, char* value) {
node* n = malloc(sizeof(node));
n->value = value;
n->index = index;
n->next = NULL;
return n;
}
node* create_nodes(char* values[], unsigned short index, unsigned short num_values) {
if(num_values == 0) {
return NULL;
}
node* n = create_node(index, values[0]);
n->next = create_nodes(values + 1, index + 1, num_values - 1);
return n;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node* find_match(node* cur, char* target) {
if(cur == NULL){
return NULL;
}
if(cur->value != NULL){
node* result = create_node(cur->index, cur->value);
result->next = find_match(cur->next, cur->value);
}else{
return find_match(cur->next, cur->value);
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main() {
char* values[] = {
"foo", // 0
"bar", // 1
"baz", // 2
"duh", // 3
"dunk", // 4
"derp" // 5
};
node* head = create_nodes(values, 0, 6);
node* target = find_match(head, "dunk");
printf("%d\n", target->index);
return 0;
}
No error messages were given, except a prior segmentation fault I've already 'fixed' but I think it's supposed to print the whole list.
You can insert a single element at a time and send the each element using loop because you know the size of array.Then you have to little change in your code.
struct linkList {
int data;
linkList* next;
}node;
node create(int val){
node tmp;
tmp = (node)malloc(sizeof(struct linkList));
tmp->data = val;
return tmp;
}
node* insertNodeAtHead(linkList* llist,int data) {
node tmp;
tmp = create(data);
tmp->next = llist;
return tmp;
}
Then you can search with your Key just like printing the all element in the List
void print(linkList* head) {
while(head !=NULL){
printf("%d\n",head->data); // check here is this your key or Not
head = head->next;
}
}
But this question is known and before posting any question make sure you try and Search enough in Google !!. Hope you get the idea and implement it in your own way.
There are a few issues in the code.
The problem is in the findmatch function. In this as per the problem statement, the target node should be returned if it is present, else NULL should be returned. This can be achieved as below.
node* find_match(node* cur, char* target) {
if(cur == NULL){
return NULL;
}
if(strcmp(cur->value,target) ==0){
return (cur);
}else if (cur->value != NULL){
return find_match(cur->next, target);
}
else {
return NULL;
}
}
Additional points
In the create_node function you are directly copying the string pointer. This may work in this specific case, but you should ideally allocate memory for the value field separately.
node* create_node(unsigned short index, char* value) {
node* n = malloc(sizeof(node));
n->value = strdup(value);
n->index = index;
n->next = NULL;
return n;
}
While printing the value, you should check if the returned value from findmatch is NULL
node* target = find_match(head, "dunk");
if (target != NULL) {
printf("%d\n", target->index);
}
else {
printf (" Not found\n");
}
Related
I'm quite new to C and am still coming to grips with a lot of the syntax and idiosyncrasies. I'm not exactly sure what needs changing in order to make my code work but am open to any ideas. I understand that I need to utilize pointers in order to make this work but I am still lost on the specific implementation. I keep getting an error that my myList function is undeclared but I feel like I have declared it already. Is there something I am missing about how C works? Any help would be appreciated
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* head;
struct node* next;
}node;
node*linkedList ();
int main ()
{
struct linkedList* myList = (struct createList*)malloc(sizeof(struct node));
myList.addNode(5);
myList.addNode(10);
myList.addNode(13);
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
}
node* linkedList ()
{
node* head;
node* current;
node*next;
addNode (int x)
{
node keephead = head;
current = head;
while (current.next = NULL)
{
if (current.next = NULL)
{
current.next = node* newnode
newnode.data = x;
newnode.next = NULL;
newnode.head = keephead
}
if (head = NULL)
{
head = current;
}
}
}
int getSize ()
{
int counter = 0;
node countNodes = head;
while (countNodes.next != NULL)
{
countNodes = countNodes.next;
counter++;
}
return counter;
}
int search(int value)
{
int index = 0;
node searchNode = head;
while(searchNode.next!= NULL)
{
searchNode = searchNode.next;
index++;
if (node.value = data)
{
break;
}
else {
index = -1;
}
}
return index;
}
}
I will be simplifying the explanations, so the terms that I will use might not be the correct one.
Proper and consistent indentation would always make your code easier to read and to fix. There were missing semi-colons too, you should watch out for that.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* head;
struct node* next;
} node;
node* linkedList();
int main()
{
struct linkedList* myList = (struct createList*) malloc(sizeof(struct node));
myList.addNode(5);
myList.addNode(10);
myList.addNode(13);
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
}
node* linkedList()
{
node* head;
node* current;
node* next;
addNode (int x)
{
node keephead = head;
current = head;
while (current.next = NULL)
{
if (current.next = NULL)
{
current.next = node* newnode;
newnode.data = x;
newnode.next = NULL;
newnode.head = keephead;
}
if (head = NULL)
{
head = current;
}
}
}
int getSize ()
{
int counter = 0;
node countNodes = head;
while (countNodes.next != NULL)
{
countNodes = countNodes.next;
counter++;
}
return counter;
}
int search (int value)
{
int index = 0;
node searchNode = head;
while (searchNode.next != NULL)
{
searchNode = searchNode.next;
index++;
if(node.value = data)
{
break;
}
else
{
index = -1;
}
}
return index;
}
}
In main(), you should add the return 0; at the end of the function as it is an undefined behavior (AKA not a good thing to do). You could also change it to void main(), but it doesn't compile in clang.
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
return 0;
}
You can't put a function within a function in C (nested functions). Put addNode(), getSize(), and search() outside the linkedList() function.
node* linkedList()
{
node* head;
node* current;
node* next;
}
addNode (int x)
{
node keephead = head;
...
}
int getSize ()
{
int counter = 0;
...
return counter;
}
int search (int value)
{
int index = 0;
...
return index;
}
linkedList() does literally nothing now and should be removed.
struct node* next;
} node;
int main()
{
struct linkedList* myList = (struct createList*) malloc(sizeof(struct node));
...
printf("The linked list is this big: %d\n", myList.getSize);
return 0;
}
void addNode (int x)
{
node keephead = head;
In main(), myList is the head of the currently empty linked-list, so it should be initialized to NULL. There's no linkedList data type, only node. Change it to:
node* myList = NULL;
You seem to be applying addNode(), getSize(), and search() to a variable, but C doesn't have that feature (C++ have it though). Add the linked-list head as an argument instead. addNode() needs the & address operator since it will be changing where the head starts.
addNode(&myList, 5);
addNode(&myList, 10);
addNode(&myList, 13);
printf("%d\n", search(myList, 10));
printf("The linked list is this big: %d\n", getSize(myList));
Update the function parameters of addNode(). In the while condition current.next = NULL and if statements, you were using an assignment operator instead of a comparison operator != or ==. You used the variables current and newnode, but never declared it anywhere in the function. There were lots of logic errors here. Change it to:
void addNode (node** head, int x)
{
node* current = *head;
node* newnode = malloc(sizeof(node));
newnode->data = x;
newnode->head = *head;
newnode->next = NULL;
if (*head == NULL)
*head = newnode;
else
{
while (current->next != NULL)
current = current->next;
//current is now the last node of linked list
current->next = newnode;
}
}
Do the same for the function parameters of getSize() and search(). Use node * instead for countNodes and searchNode. -> is the operator for accessing the members of a struct pointer. if statement should be put before it goes to the next node, as it would always skip the first node if left as it is. index should be put before the if statement so the index would update before it breaks out of the loop.
int getSize (node* head)
{
int counter = 0;
node* countNodes = head;
while (countNodes != NULL)
{
countNodes = countNodes->next;
counter++;
}
return counter;
}
int search (node* head, int value)
{
int index = 0;
node* searchNode = head;
while (searchNode != NULL)
{
index++;
if(searchNode->data == value)
break;
searchNode = searchNode->next;
}
if(searchNode->data != value)
index = -1;
return index;
}
Add the function prototypes before main().
void addNode (node** head, int x);
int getSize (node* head);
int search (node* head, int value);
int main()
{
node* myList = NULL;
Everything should work properly now.
I need to create a new function when adding a new element, it places it in the list so that the list stays in sorted order. I am not sure if my implementation is correct, my first try, with my group members, gave a segmentation fault. When I tried to do it on my own, it did not do anything. Any help will be appreciated. Here is my code:
header file:
typedef struct s{
int value;
struct s *next, *previous;
} node, *node_ptr;
c file:
#include <stdio.h>
#include <stdlib.h>
#include "double.h"
void
print_list(node_ptr list) {
// walk the list to print out the contents
while (list) {
printf("%d ",list->value);
list = list->next;
}
printf("\n");
}
void delete_list(node_ptr list) {
// walk the list to delete the elements
node_ptr t;
while (list) {
t = list;
list = list->next;
free(t);
}
}
node_ptr new_node(int value) {
node_ptr t = (node_ptr)malloc(sizeof(node));
t->value = value;
t->next = t->previous = NULL;
return t;
}
node_ptr add_to_back(node_ptr list, int value) {
node_ptr t = list;
node_ptr s = new_node(value);
// special case: starting with an empty list
if (t == NULL) return s;
// at this point we know there is a least one element in
// the list
while (t->next != NULL) // walk the list looking for the last element
t = t->next;
// we are at the end so now we arrange the pointers
t->next = s;
s->previous = t;
return list;
}
// my implementation after some research
node_ptr add_sorted(node_ptr list, int value) {
node_ptr temp = list;
node_ptr newNode;
if(temp == NULL || temp->value < newNode->value)
{
newNode->next = temp;
temp = newNode;
}
else
{
while(temp != NULL && temp->value < value)
{
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
}
return newNode;
}
// second implementation with team
/*
node_ptr add_sorted2(node_ptr list, int value) {
// This is the function you need to implement
// when adding a new element place it in the list so that the list stays in sorted order.
node_ptr temp = list;
node_ptr n = new_node(value);
if(temp == NULL)
{
temp->value = value;
temp->next = NULL;
return n;
}
else if(temp->next != NULL) {
while(temp->next != NULL) {
if(temp->value <= value) {
n->next = temp->next;
temp->next = n;
return n;
}
else if(temp->value > value) {
temp = temp->next;
}
else {
temp->next = n;
return n;
}
}
}
return n;
}
*/
int
main() {
int in_val;
node_ptr my_list = NULL;
node_ptr sorted_list = NULL;
scanf("%d",&in_val);
while (in_val > 0) { // going to read input until see 0 or negative
my_list = add_to_back(my_list,in_val);
sorted_list = add_sorted(sorted_list,in_val);
scanf("%d",&in_val);
}
printf("List:\n");
print_list(my_list);
printf("Sorted List:\n");
print_list(sorted_list);
delete_list(my_list);
delete_list(sorted_list);
}
The segmentation fault is clear to me, you are using an uninitialized pointer here
if(temp == NULL || temp->value < newNode->value)
// ^
Or ANY OTHER newNode's dereference anywhere, because newNode is never initialized in your code.
If temp == NULL, and you didn't initialize newNode yet then undefined behavior.
Adding a node to a list while preserving order is easy,
Create the new node
If succeeded creating it, traverse the list until the next node is greater|smaller (depending on the ordering that you desire) than the new node.
When you find it, link current's node next to the new node and the next node should be new node's next.
And that is all.
As at the last time, suppose we have doubly linked list of nodes
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node* next;
struct Node* prev;
} Node;
typedef struct LinkedList {
Node *first;
Node *last;
} LinkedList;
void initList(LinkedList* l) {
l->first = NULL;
l->last = NULL;
}
and my task is to code search method, which should find a node with given value
Node* search(LinkedList *list, int value) { ... }
well, my attempt follows
Node* search(LinkedList *list, int value) {
Node *node = malloc(sizeof(Node));
if (node == NULL)
return NULL;
node->value = value;
node->prev = NULL;
node->next = list->first;
while((node->value != value) && (node->next != NULL)){
node->prev = node->next;
node->next = (node->next)->next;
}
return node;
}
according to the implemenatation tests (this is not my job :-)
void test_search_exist() {
printf("Test 3: ");
LinkedList l;
initList(&l);
Node n1, n2;
n1.value = 1;
n1.next = &n2;
n1.prev = NULL;
n2.value = 2;
n2.next = NULL;
n2.prev = &n1;
l.first = &n1;
l.last = &n2;
Node *i = search(&l, 2);
if (i == &n2) {
printf("OK\n");
}else{
printf("FAIL\n");
}
}
void test_search_not_exist(){
printf("Test 4: ");
LinkedList l;
initList(&l);
Node n1, n2;
n1.value = 1;
n1.next = &n2;
n1.prev = NULL;
n2.value = 2;
n2.next = NULL;
n2.prev = &n1;
l.first = &n1;
l.last = &n2;
Node *i = search(&l, 3);
if (i == NULL) {
printf("OK\n");
}else{
printf("FAIL\n");
}
}
my code breaks either for existing or non-existing nodes. So is there any logic mistake or whatever?
Firstly: Dont allocate within search. The data members already exist, since you created them ahead.
Secondly: Iterate through the list and check every node for it's value.
Node* search(LinkedList *list, int value)
{
Node *node = list->first;
Node *found = NULL;
while(node != NULL)
{
if(node->value == value)
{
found = node;
break;
}
node = node->next;
}
return found;
}
To be more specific with the error(s) you made:
You allocated a node then filled it with the pointers of the first node, but with the value you were searching for. Then you started to loop over the list with the condition to stop when node->value equals the value you were searching for. Since node->value was initialized with the value your were searching for, this comparison will always be false (since its the same), the loop will be terminated and you get a bad result.
Besides this, your original code would result in a memory leak, since you malloc a new node, but you dont free it.
I keep getting this Segmentation Fault: 11 error and I don't know why.
My Code:
typedef struct Node* NodePtr;
struct Node
{
NodePtr next;
void *val;
};
struct List
{
NodePtr head;
};
typedef struct List* ListPtr;
int compare(void *one, void *two)
{
if(*(int*)one < *(int*)two)
return -1;
else if(*(int*)one > *(int*)two)
return 1;
return 0;
}
ListPtr create()
{
ListPtr blah = malloc(sizeof(struct List));
memset(blah, 0, sizeof(struct List));
return blah;
}
NodePtr scan(NodePtr head, void *obj)
{
NodePtr previous, current;
previous = head;
current = head->next; // Segmentation fault here!!
while(current != NULL && (compare(curry->val, obj) == -1))
{
previous = current;
current = current->next;
}
return previous;
}
int insert(ListPtr llist, void *obj)
{
NodePtr newobj = malloc(sizeof(struct Node));
NodePtr prevNode, nextNode;
prevNode = search(llist->head, obj);
nextNode = prevNode->next;
if((nextNode == NULL) || (compare(nextNode->val, obj) != 0))
{
prevNode->next = newobj;
newobj->next = nextNode;
return 1;
}
else
{
free(newobj);
}
return 0;
}
I thought head was not allocated, so I added malloc in create for blah->head, but still no luck.
I think the error is here after some debugging: current = head->next.
Any help would be appreciated! Thank you for your time!
EDIT: How I call insert:
int main(int argc, char *argv[])
{
ListPtr list = create();
int x = 2;
int *p = &x;
while(*p != 0)
{
printf("\nEnter a number: ");
scanf("%d", p);
if(*p != 0)
insert(list, p);
}
return 0;
}
You don’t appear to check whether the list is empty when you scan it. However, without a Minimum Complete Verifiable Example that tells us how you called the function, it is impossible to tell for sure what you did.
Update
Now that you have, that seems to be it. You create an empty list and search it inside your insert function. The search function dereferences the zeroed-out pointer in head, causing a segfault.
Try the following: first, check that your pointer is valid in each of your functions before you do anything with it. An empty list should fail every search. Second, for maximum portability, you want to set your head pointer to NULL (since a NULL pointer is not necessarily all-bits-zero on all implementations).
i am writing a Dictionary using linked list in C, and all my functions work except my delete function, which is shown below along with all other necessary code. Every time i try to run my program as soon as it reaches a line in which it must delete a node, it gives me the error: Segmentation Fault (core dumped) which means it has something to do with the memory allocation or a null pointer i think. I know that the rest of my code works. All and any help is appreciated! :)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include"Dictionary.h"
// NodeObj
typedef struct NodeObj{
char* key;
char* value;
struct NodeObj* next;
} NodeObj;
// Node
typedef NodeObj* Node;
// newNode()
// constructor of the Node type
Node newNode(char* key, char* value)
{
Node N = malloc(sizeof(NodeObj));
assert(N!=NULL);
// if(key!=NULL && value!=NULL){
N->key = key;
N->value = value;
N->next = NULL;
// }
return(N);
}
// DictionaryObj
typedef struct DictionaryObj{
Node head;
int numItems;
} DictionaryObj;
// newDictionary()
// constructor for the Dictionary type
Dictionary newDictionary(void){
Dictionary D = malloc(sizeof(DictionaryObj));
assert(D!=NULL);
D->head = NULL;
D->numItems = 0;
return D;
}
Node findKey(Dictionary D, char*key){
Node N;
N = D->head;
while(N != NULL){
if(strcmp(N->key,key)==0){
return N;
}
N = N->next;
}
return NULL;
}
char* lookup(Dictionary D, char* k){
if(findKey(D, k)==NULL){
return NULL;
}else{
Node N;
N = findKey(D, k);
return N->value;
}
}
void delete(Dictionary D, char* k)
{
if(lookup(D,k) == NULL){
fprintf(stderr,
"KeyNotFoundException: Cannot delete non-existent key\n");
exit(EXIT_FAILURE);
}
int check = strcmp(D->head->key, k);
if(check == 1){
D->head = D->head->next;
return;
}
Node cur;
Node prev;
cur = D->head;
prev = NULL;
while( cur != NULL){
int ret1;
ret1 = strcmp(cur->key, k);
while( ret1 == 0){
prev = cur;
cur = cur->next;
}
}
prev->next = cur->next;
D->numItems--;
}
The NodeObject should store copy of the string and care for deleting it:
typedef struct Node Node;
struct Node {
Node *next;
char *key, *value;
};
Node* newNode(char* key, char* value) {
assert(key && value);
Node* node = (Node*)malloc(sizeof(Node));
assert(node);
node->next = NULL;
node->key = strdup(key);
node->value = strdup(value);
}
void delNode(Node* node) {
free(node->key);
free(node->value);
}
Consider using the original code (without that strdup) in this scenairo:
Node* prepare() {
char key_buf[20]; strcpy(key_buf, "mykey");
char val_buf[20]; strcpy(val_buf, "myval");
return newNode(key_buf, val_buf);
}
void examine(Node* node) {
printf("Node key=%s value=%s\n", node->key, node->value);
}
int main() {
examine(prepare());
}
the above code would crash because Node would have pointers to stack (in your case without that strdup), but key_buf+val_buf were only valid inside prepare() (garbage outside and therefore inside examine() - node->key points to random data).