I've been stuck on a segmentation fault of a long time. I declared a struct with a pointer to a string. I wrote two functions, create and remove to manipulate values. The struct is as follows:
#include "filename.h"
//*in filename.h:* typedef struct linkNode linkNode_t;
struct linkNode{
struct linkNode *next;
char *value;
};
The create function will first allocate memory for the node, then allocate memory for the value, and then copy the input value into the value field:
linkNode_t* create(char* stuff){
linkNode_t *ptr=malloc(sizeof(linkNode_t));
if(ptr==NULL){
printf("malloc failure");
return NULL;
}
char* tempvalu=malloc(sizeof(char)*strlen(stuff)+1);
if(tempvalu==NULL){
printf("malloc failure");
return NULL;
}
strcpy(tempvalu,stuff);
ptr->next=NULL;
ptr->value=tempvalu;
return ptr;
}
A function is used to insert a node into the linked list:
linkNode_t* insertLast(linkNode_t* start, linkNode_t* newNode){
linkNode_t* current=start;
while(current->next!=NULL){
current=current->next;
}
//now current points to the last element in the linked list
current->next=newNode;
return start;
}
The part causing me problem is as follows:
linkNode_t* removebyValue(linkNode_t* start, char* valu){
/**removes the first instance of a node with a certain value. Return *start after removing.
if linked list becomes empty, return NULL*/
linkNode_t *current=start;
linkNode_t *previous=start;
while(current!=NULL){
if(strcmp(valu,current->value)==0) {//found the node to delete
if(current==start){//removing the head
linkNode_t* retvalue= current->next;
free(current->value);
free(current);
return retvalue;
}
else{ //removing other elements in the linked list
previous->next=current->next;
free(current->value);
free(current);
return start;
}
}
else{
previous=current;
current=current->next;
}
}
return start;
}
In the Main I created a linked list of two elements,1 and 2, and tried to free element 1 when segmentation fault occured.
int main(){
linkNode_t *pt1=create("1");
pt1=insertLast(pt1,create("2"));
removebyValue(pt1,"1"); //Causes seg fault. If I replace "1" by "2" nothing happens
Can someone give some suggestions on this? Thanks in advance
EDIT: I put all the code that could be related since someone said the sections I put on didn't have an error
I think you're over-thinking the removal of a node while maintaining the start pointer properly. Consider a hopefully simpler approach.
typedef struct node_t
{
struct node_t* next;
char* value;
} node_t;
node_t* remove(node_t *start, const char* valu)
{
node_t* current=start;
node_t* prev=NULL;
while(current && strcmp(current->value, valu))
{
prev = current;
current = current->next;
}
if (current)
{
if (prev) // we're not deleting start node
prev->next = current->next;
else // we *are* deleting start node
start = current->next;
// now the node is unlinked. remove it.
free(current->value);
free(current);
}
return start;
}
here's an alternative test code that works fine, take a loot at it and see if it helps.
in addition, you can add
typedef struct node_t {
struct node_t* next;
char* value;
} node;
this may appear simpler to understand, but it isn't because nature of typedef is confusing.
I STRONGLY suggest you take a look at https://github.com/torvalds/linux/blob/master/Documentation/CodingStyle
This is the coding style of the linux kernel, it is very short and simple, not particularly a law, but it is worth noting...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node_t {
struct node_t* next;
char* value;
};
struct node_t* create(const char* istr)
{
struct node_t* ptr = (struct node_t*)malloc(sizeof(struct node_t));
char* tmp = (char*)malloc(sizeof(char) * (strlen(istr) + 1));
strcpy(tmp, istr);
ptr->next = 0;
ptr->value = tmp;
return ptr;
}
struct node_t* remove(struct node_t* start, const char* value)
{
struct node_t* current = start;
struct node_t* prev = start;
while (current != 0) {
if (!strcmp(value, current->value)) {
if (current == start) {
struct node_t* retval = current->next;
free(current->value);
free(current);
return retval;
} else {
/* nothing happens */
return 0;
}
}
}
}
int main(const int argc, const char** argv)
{
struct node_t* pt = create("1");
printf("%s\n", pt->value);
pt->next = create("2");
printf("%s\n", pt->next->value);
remove(pt, "1");
return 0;
}
Related
I had a singly linked list that took in integers successfully, but now I want to use strings. However it is not working. I am getting so many different errors about "casting". I am finding conflicting information online as well. One comment here, Creating linked list of strings, said not to use strcpy, but I see strcpy used in a few examples online.
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
struct node {
char value[];
struct node* next; // pointer of structure type
};
// set existing type, node, to the alias, node_t
typedef struct node node_t;
node_t *create_new_node(char value) {
// create space for node with malloc
node_t *result = malloc(sizeof(node_t));
// set the value of the new node
result->value = value;
//strcpy(result->value, value);
// set the value's next pointer to null
result->next = NULL;
return result;
}
node_t *insert_at_head(node_t **head, node_t *node_to_insert) {
node_to_insert->next = *head;
*head = node_to_insert;
return node_to_insert;
}
//Prints linked list
void printlist(node_t* head) {
node_t *temporary = head;
while (temporary != NULL) {
//print out the value of the node that temporary points to
// printf("%d - ", temporary->value);
// to move along the list
temporary = temporary->next;
}
printf("\n");
}
int main() {
node_t *tmp;
// declaring head pointer
node_t *head = NULL;
// CREATING LINKED LIST
// for (int i = 0; i < 25; i++) {
// tmp = create_new_node(i);
// // sending the address of the head variable
// //calling by reference
// //SINCE HEAD IS ALREADY A NODE POINTER
// insert_at_head(&head, tmp);
// }
printlist(head);
tmp = create_new_node("I like food");
insert_at_head(&head, tmp);
}
How can I get this Linked List of string to work?
Thank you.
If you reorganize it a bit, you will be able to allocate the space the struct & the place for the string in the single malloc.
struct node
{
struct node* next; // pointer of structure type
char value[];
};
// set existing type, node, to the alias, node_t
typedef struct node node_t;
node_t *create_new_node(const char *value)
{
// create space for node with malloc
node_t *result = malloc(sizeof(*result) + strlen(value) + 1);
if(result)
{
strcpy(result->value, value);
result->next = NULL;
}
return result;
}
Please use your compiler! I ran $gcc -Wall a.c on this code and got:
a.c:7:10: error: flexible array member not at end of struct
char value[];
^
a.c: In function ‘main’:
a.c:67:5: warning: passing argument 1 of ‘create_new_node’ makes integer from pointer without a cast [enabled by default]
tmp = create_new_node("I like food");
^
a.c:15:9: note: expected ‘char’ but argument is of type ‘char *’
node_t *create_new_node(char value) {
^
a.c:70:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Now we know what the problems are. Firstly, char value[] should be char *value since it's a pointer rather than a flexible array member (FAM). You could also move the FAM to the end of the struct if you want as shown here.
Next, node_t *create_new_node(char value) is relying on a char value when you really want a string, char *value for the parameter. There are issues beyond this: you'll likely want to make a copy of the string for the node in case it disappears from the stack. This memory should be cleaned up after use.
Other tips:
Avoid noisy, redundant comments like:
// declaring head pointer
node_t *head = NULL;
malloc(sizeof(*name_of_the_var)); is safer than malloc(sizeof(node_t)); if the data changes.
node_t *insert_at_head(node_t **head, node_t *node_to_insert) modifying its parameter and returning it is a little unusual. I'd make it void to make the in-place contract explicit.
Alphabetize and remove unused imports.
Check that malloc calls succeeded.
Remember to return 0; from main.
typedef struct node node_t; is okay but also hides info--I prefer keeping the struct there.
Here's a possible rewrite:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *value;
struct node* next;
};
struct node *create_new_node(char *value) {
struct node *node = malloc(sizeof(*node));
if (!node) {
fprintf(stderr, "%s:%d malloc failed\n", __FILE__, __LINE__);
exit(1);
}
node->next = NULL;
node->value = strdup(value);
if (!node->value) {
fprintf(stderr, "%s:%d malloc failed\n", __FILE__, __LINE__);
exit(1);
}
return node;
}
void insert_at_head(struct node **head, struct node *node_to_insert) {
node_to_insert->next = *head;
*head = node_to_insert;
}
void print_list(struct node *head) {
for (; head; head = head->next) {
printf("%s->", head->value);
}
puts("");
}
void free_list(struct node *head) {
while (head) {
struct node *tmp = head;
head = head->next;
free(tmp->value);
free(tmp);
}
}
int main() {
struct node *head = NULL;
for (int i = 0; i < 10; i++) {
char n[16];
sprintf(n, "%d", i);
insert_at_head(&head, create_new_node(n));
}
print_list(head);
free_list(head);
return 0;
}
Output:
9->8->7->6->5->4->3->2->1->0->
"I'm trying to implement a Linked List that will later make uses of a lexicographical sort function, but I keep getting an error concerning conflicting types in listnode.
I don't know what the cause of this issue is. Previously I had issues trying to malloc using sizeof and I found that the solution was declaring next as listnode* pointer. It solved that issue, but it still has conflicting types. When I try to compile I get this error message:
ls.c:18:3: error: conflicting types for 'listnode'
} listnode:
ls.c:12:14: note previous declaration of 'listnode' was here
typedef node listnode;
My code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
int strcmp(const char *str1, const char *str2);
//This chunk of code is dedicated to the formation and functions of Linked list
//which will be used to store and sort file names.
typedef struct node node;
typedef node listnode;
#define EMPTY NULL;
typedef struct listnode{
struct listnode* next;
char* string;
} listnode;
struct listnode* head;
//This function will print the entire list
void printlist(listnode* head){
struct listnode* current = head;
while(current != NULL){
printf("%s \n", current->string);
current = current->next;
}
}
//This function creates a new node
listnode* newNode(char* str, listnode* node){
listnode* new = (listnode*)malloc(sizeof(listnode*));
if(new == NULL){
printf("Error creating new listnode.\n");
exit(0);
}
new->string = str;
new->next = node;
return new;
}
//This function will append a new node onto the list
listnode* list_append(listnode* head, char* str){
if (head == NULL){
listnode* new = newNode(str, head);
head = new;
return head;
}
else{
listnode* current = head;
while(current-> next != NULL){
current = current->next;
}
listnode* new = newNode(str,NULL);
current -> next = new;
}
return head;
}
//This function earses the list freeing up space
void list_free(listnode* head){
listnode* current;
listnode* temp;
if(head != NULL){
current = head->next;
if(head !=NULL){
current = head -> next;
head ->next = NULL;
while(current != NULL){
temp = current -> next;
free(current);
current = temp;
}
}
}
free(head);
}
//This is the end of the linked list code
int main(int argc, char **argv){
char *current_dir = NULL;
DIR *direct_ptr = NULL;
struct dirent *dir_ptr = NULL;
unsigned int fileNum = 0;
int c;
listnode* head = NULL;
current_dir = getenv("PWD");
if(NULL == current_dir){
printf("\n Error: Couldn't grab current directory.\n");
return -1;
}
direct_ptr = opendir((const char*)current_dir);
if(NULL == direct_ptr){
printf("\n Error: couldn't open current directory\n");
return -1;
}
if(argc == 1){
for(fileNum=0; NULL != (dir_ptr = readdir(direct_ptr)); fileNum++){
if(dir_ptr->d_name[0] != '.'){
head = list_append(head, dir_ptr->d_name);
}
}
}
else{
if(strcmp(argv[1], "-a") || strcmp(argv[1], "[-a]")){
for(fileNum=0; NULL != (dir_ptr = readdir(direct_ptr)); fileNum++){
head = list_append(head, dir_ptr->d_name);
}
}
else{
printf("\n Unrecognized argument in command line.\n");
return -1;
}
}
return 0;
}
You do in fact have conflicting definitions for listnode. You first define the type here:
typedef struct node node;
typedef node listnode;
Then define it again here:
typedef struct listnode{
struct listnode* next;
char* string;
} listnode;
In one case it's an alias for struct node and in the other it's an alias for struct listnode.
Get rid of the first one as well as typedef struct node node;
You have two definitions of listnode:
typedef node listnode;
and
typedef struct listnode{
struct listnode* next;
char* string;
} listnode;
The first one is unnecessary, and won't work, because it uses node, which is defined as
typedef struct node node;
but you never defined struct node anywhere.
I keep getting Segmentation Fault (core dumped) run time error and I can't figure out why.
My code:
struct Node
{
void *next;
void *val;
};
typedef struct Node* NodePtr;
struct List
{
NodePtr head;
};
typedef struct List* ListPtr;
ListPtr create()
{
ListPtr ptr = malloc(sizeof(struct List));
return ptr;
}
int insert(ListPtr list, void *obj)
{
NodePtr newObj = malloc(sizeof(struct Node));
//Cast next as a self referencing Node
newObj->next = (NodePtr) newObj->next;
//Point to beginning of list
NodePtr current = list->head;
if(list->head == NULL)
{
newObj->val = obj;
list->head->next = newObj;
newObj->next = NULL;
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
int x = 2;
int *p = &x;
ListPtr thing = create();
insert(thing, p);
return 0;
}
The error is here: list->head->next = newObj after some debugging. I thought I had to allocate memory for list->head->next, but when I added the code in for that it still gave me the same error. Am I casting it wrong or not allocating memory correctly? Any help would be appreciated, thanks!
Just put this together, runs fine.
#include <stdlib.h>
#include <stdio.h>
struct Node {
void *next;
void *val;
};
typedef struct Node* NodePtr;
struct List {
NodePtr head;
};
typedef struct List* ListPtr;
ListPtr CreateList() {
ListPtr ptr = malloc(sizeof(struct List));
return ptr;
}
void Insert(ListPtr list, void *obj) {
// create and initialize new node
NodePtr newObj = malloc(sizeof(struct Node));
newObj->val = obj;
newObj->next = NULL;
//Point to beginning of list
NodePtr curr = list->head;
// Add node to the list
if(curr == NULL) // if no head node, make newObj the head node
{
list->head = newObj;
}
else{ // otherwise traverse the list until you find the last node (the one that points to a null as the next)
while(1) {
if(curr->next != NULL) {
curr = curr -> next;
} else {
curr->next = newObj;
}
list->head = newObj;
newObj->val = obj;
list->head->next = newObj;
newObj->next = NULL;
}
}
}
int main() {
int x = 2;
int *p = &x;
ListPtr thing = CreateList();
Insert(thing, p);
return 0;
}
You check if list->head is NULL and then do some operations with that. Change that to if(list->head != NULL)
{
...
}
At a thought, malloc does not guarantee allocated memory is empty. It's good practice to set all values where they matter after allocation.
list->head is probably not null
also : newObj->next = (NodePtr) newObj->next;
doesn't set to a rational value, it sets to whatever memory was set - were you intending newObj->next = (NodePtr) newObj; ?
list->head should not be referenced if null. list->head->next will only be valid if it's not null.
if you actually want to build a list,
newObj->val = obj;
if (list->head == NULL) { newObj->next = list->head; }
list->head = newObj;
either that or travel down list->head->next chain until next is null, and set that to be newObj->next. If that way then it's possibly a good idea, newObj->next should be set to NULL and not itself.
Might want to figure out how your list will behave - is it circular? does it grow from the head (list->head) or tail (last ->next) ? Do you spot the tail when listObject->next == NULL or when listObject->next == listObject ?
I realize that this answer is mostly stylistic. But I do think that (bad) style and (bad) habits are an (important) part of (bad) programming. Summing it up ...
(in most cases) typedefs are not needed; they just introduce an alias for something that already existed.
[rule of seven] human readers have a limited amount of identifiers ("names") that they can keep track of. This could be 7. Minimising the number of distinct words makes reading easier.
also, the reader has to remember that xPtr and xNode are related (typeof *xPtr === typeof xNode)
when reading source code, keywords and special character tokens (such as operators) don't count as an identifier, since you do not have to remember them. (Syntax-highligting helps, too)
if there is only one way of expressing your program, there is no possibility for errors like iPtr *p; p = (qPtr) malloc (sizeof xNode);
creating yet another struct (+typedefs for it), just to accomodate a root pointer will clobber up your mental namespace even more.
Now a rework of the (intended) code:
#include <stdio.h>
#include <stdlib.h>
struct node {
struct node *next;
void *payload;
};
struct node *root=NULL;
void initialize() { /* nothing .... */ }
int insert(struct node **pp, void *pv) {
struct node *p;
p = malloc(sizeof *p);
if (!p) { /* handle error */ return -1; }
p->payload = pv;
p->next = *pp;
*pp = p;
return 1; /* inserted one element */
}
int main(void)
{
int i;
i=666;
/* note: this function call will pass a pointer to a local variable `i`
** to the insert() function, which will remember it.
** This is generally a bad idea, to say the least.
*/
insert( &root, &i);
return 0;
}
I am having trouble with inserting items in linked list. All the elements end up having the same *data content that is inserted in the last. The program compiles successfully. I use gcc and gdb.
I am new to coding so please mention troubles if any that you see in my programming style.
typedef struct Node{
void* data;
struct Node* next;
} *node;
node allocate(){
node current = malloc(sizeof(struct Node));
current->data = NULL;
current->next = NULL;
return current;
}
void insert(node *head, void *data){
// if head has no data then set the data on head and return
if(((*head)->data == NULL)&&((*head)->next == NULL)){
(*head)->data = data;
return;
}
node newHead = allocate();
newHead->data = data;
newHead->next = *head;
*head = newHead;
//printf("Node Data : %d\tNext Node Data : %d",
//*(int *)((*head)->data), *(int *)((*head)->data));
}
int main(int argc, char *argv[]){
node head = allocate();
int count = inputSequence(&head);
int *aod = calloc((size_t) count, sizeof(int));
generateAOD(head, aod);
if(checkJolly(aod, count) == TRUE)
printf("Jolly\n");
else
printf("Not Jolly\n");
return 0;
}
int inputSequence(node *input){
int *num = malloc(sizeof(int));
int count = 0;
while((scanf("%d", num) != EOF)){
insert(input, (void *)num);
count++;
}
traverse(*input, fn);
return count;
}
Your insert logic is non-existant. And you're literally making your life harder by attempting to manage a linked list in the fashion you're using.
The head pointer itself should indicate whether the list is empty. If it is NULL, its empty. If it isn't, there's data. Code the insertion logic accordingly.
And your inputSequence is utterly broken. It only allocates ONE data point, then uses the same data allocation for every insertion. You need one for each insertion.
First, change allocate() to accept the data being inserted. It will make the remaining code less cluttered:
node allocate(void *data)
{
node current = malloc(sizeof(*current));
current->data = data;
current->next = NULL;
return current;
}
Second, insert by allocating a new node as needed.
void insert(node *head, void *data)
{
node p = allocate(data);
p->next = *head;
*head = p;
}
Next, fix inputSequence() to properly allocate memory for each entry:
int inputSequence(node *input)
{
int count = 0;
int num = 0;
// note: check for number of params *successfully* parsed.
// if it isn't 1, its time to leave the loop.
while(scanf("%d", &num) == 1)
{
int *data = malloc(sizeof(num));
*data = num;
insert(input, data);
++count;
}
return count;
}
And lastly, make sure your head pointer is initially NULL in main().
int main(int argc, char *argv[])
{
node head = NULL;
// load linked list
inputSequence(&head);
// ... the rest of your code....;
return 0;
}
With the above, the logical answer of "Is my list empty" is simply if (!head) Further, this makes things like traversal trivial.
void traverse(node ptr, void (*pfn)(void *))
{
while (ptr)
{
pfn(ptr->data);
ptr = ptr->next;
}
}
Freeing the list is equally trivial:
void destroy(node *head)
{
while (*head)
{
node p = *head;
*head = p->next;
free(p->data);
free(p);
}
}
typedef struct Node{
void* data; // Make it as int or any other data type
struct Node* next;
} *node;
In function inputSequence() you are allocating memory for num at the very beginning and making node->data point to this memory each time you are adding a node. Hence data pointer of each node of your linked list points to the same memory location and hence contains the same value.
If you still want to continue with data as a void pointer, allocate num for each iteration of the while loop and pass this to insert function.
while((scanf("%d", num) != EOF)){
num = malloc(sizeof(int);
insert(input, (void *)num);
count++;
}
I am having some problems creating a linked list and also some helper functions that I am trying to make. My code is as follows:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "getNextWord.h"
#define MAX_WORD_SIZE 256
typedef struct{
int counter;
char* key;
struct node* next;
} node;
node* createNode(char* words){
node* head;
if(!(head=malloc(sizeof(node)))) return NULL;
head->key=words;
head->next=NULL;
return head;
}
node* addToList(node* head, char* words){
node* newNode;
newNode=createNode(words);
newNode->next = head;
return newNode;
}
int find(node* head){
if (head->next != NULL){
node* next = head->next;
while(head != NULL){
if (strcmp(head->key,next->key)==0){
head->counter++;
head=head->next;
return 1;
}
else{
head=head->next;
}
}
}
return 0;
}
void printList(node* head){
node* pointer = head;
while (pointer != NULL){
printf("%s",pointer->key);
pointer=pointer->next;
}
printf("\n");
}
int main(int argc, char* argv[]){
if(argc<2){
fprintf(stderr, "Not enough arguments given\n");
}
for(int i=1; i< argc; i++){
FILE* fd=fopen(argv[i], "r");
if(fd != NULL){
char* words;
node* head = NULL;
while((words=getNextWord(fd)) != NULL){
find(head);
if (find(head) == 0){
createNode(words);
}
printList(head);
fprintf(stdout,"%s\n",words);
}
}
else(printf("No such file exists"));
fclose(fd);
}
return 0;
}
I looked around on the Internet and it would seem I am following what most people are doing in regards to the linked list. I wasn't getting any errors before, just a bunch of "warning: assignment from incompatible pointer type" in the following functions:
addtolist (the line before the return)
find (before return one and the else line)
printlist (the last line in the while loop)
I know it's not that great of code, I'm not the best programmer, but just trying to learn. Also, my getnextword does work, but if it's needed for something I can post that too.
Your are mixing up two different "namespaces" the "tag" namespace for struct and alike and the identifier namespace for typedef. The easiest to get along with this is to forward declare the types you are going to use:
typedef struct node node;
Then afterwards you can use node or struct node interchangeably. Even inside
struct node {
// something
node * next;
};
typedef struct tag_node {
int counter;
char* key;
struct tag_node* next;
} node;
for starters.
As a side-note, I can't imagine how you free() words within main (careful, it might leak).
edit - I accidentally some styles
Try this:
struct node {
int counter;
char* key;
struct node* next;
};
You may need to replace node with struct node in other places in the code.
multiple issues:
int find(node* node){
node* next = node->next; // what if next is NULL ?
while(node != NULL){
if (strcmp(node->key,next->key)==0){ // if next is NULL this will crash
node->counter++;
return 1;
node=node->next; // never reached since return 1 above.
}
else{
node=node->next;
}
}
return 0;
}
....
probably good to rename createlist to createnode since that seems to be the function.
node* createList(char* words){
node* node;
if(!(node=malloc(sizeof(node)))) return NULL;
node->key=words;
node->next=NULL;
return node;
}
the string that comes in 'words' is never stored, you need to create a copy of the words and store it e.g.:
node->key = strdup(words);