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