Im trying to process multiple names from the command line argv[] and then add or remove said names if they were prefaced by a ' ' or '-'. IE bill ted -ted would add bill and ted then remove ted. I can add names to this list no problem but my removeNode() function call results in a segmentation fault. In my main() when I go to process names to be removed I set char * name to be equal to the return pointer of removeNode(), which should be the string from the node being freed. What would the correct way to return this pointer be so I can remove the name I reference from the command line? Ive also included my insert function.
int insert(struct node ** head, char * name) {
struct node * newNode = (struct node * ) malloc(sizeof(struct node));
newNode -> data = name;
newNode -> next = NULL;
struct node * current = * head;
if ( * head == NULL) {
* head = newNode;
return 1;
}
while (current -> next != NULL) {
current = current -> next;
}
current -> next = newNode;
return 1;
}
char * removeNode(struct node ** head, char * name) {
struct node * current = * head;
struct node * previous;
if (current == NULL) {
return "error0";
}
if (strcmp(current -> data, name) == 0) {
char * data = current -> data;
* head = current -> next;
free(current);
printf("Removed %s \n", name);
return data;
}
while (current != NULL) {
previous = current;
current = current -> next;
if (strcmp(current -> data, name) == 0) {
char * data = current -> data;
previous -> next = current -> next;
free(current);
printf("Removed %s \n", name);
return data;
}
}
return "error0";
}
int main(int argc, char * argv[]) {
printf("Author : Torin Costales \n");
struct node * head = NULL;
for (int x = 1; x < argc; x ) {
if (argv[x][0] == ' ') {
char * name = malloc((strlen(argv[x] 1) 1));
if (name == NULL) return EXIT_FAILURE;
strcpy(name, argv[x]);
printf("adding %s \n", name);
insert( & head, name);
printf("List: ");
printList( & head);
} else if (argv[x][0] == '-') {
printf("removing %s \n", argv[x] 1);
char * name = removeNode( & head, argv[x] 1);
free(name);
printList( & head);
}
}
}
CodePudding user response:
The problem leading the to fault is that you were using
strcpy(name, argv[x]);
where you should have been using
strcpy(name, argv[x] 1);
This caused a string produced by "error0" to be returned when trying to remove ted since the list contained bill and ted.
Fixed and cleaned up:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node {
char *data;
struct node *next;
} node;
void printList(struct node *node) { // Don't need a pointer to a pointer.
printf("List:");
for (; node; node = node->next)
printf(" %s", node->data);
printf("\n");
}
// Returns 0 on success.
// Returns -1 and sets errno on error.
int append(struct node **node_pp, char *name) { // Better name
while (*node_pp)
node_pp = &( (*node_pp)->next );
struct node *newNode = malloc(sizeof(struct node));
if (!newNode)
return -1;
newNode->data = name;
newNode->next = NULL;
*node_pp = newNode;
return 0;
}
// Returns NULL if not found.
char *removeNode(struct node **node_pp, const char *name) { // Added `const`
for (; *node_pp; next_p = &( (*node_pp)->next )) {
if (strcmp((*node_pp) -> data, name) == 0) {
struct node * oldNode = *next_p;
*node_pp = oldNode->next;
char *data = oldNode->data;
free(oldNode);
return data;
}
}
return NULL; // NULL is a far better value to return on error.
}
int main(int argc, char * argv[]) {
struct node *head = NULL;
for (int x = 1; x < argc; x ) {
if (argv[x][0] == ' ') {
char *name = strdup(argv[x] 1); // Simpler
if (name == NULL) {
perror("Can't allocate memory"); // Error message is good
exit(EXIT_FAILURE);
}
printf("Appending %s.\n", name);
if (append(&head, name) < 0) {
perror("Can't append node to list");
exit(EXIT_FAILURE);
}
} else if (argv[x][0] == '-') {
const char *name_to_find = argv[x] 1;
printf("Removing %s.\n", name_to_find);
char *name = removeNode(&head, name_to_find);
if (name) { // Do check if it was found!
free(name);
} else {
printf("%s not found\n", name_to_find);
}
}
printList(head);
printf("\n");
}
}
Output for foo bar -baz -foo:
Appending foo.
List: foo
Appending bar.
List: foo bar
Removing baz.
baz not found
List: foo bar
Removing foo.
List: bar
