user3213732 user3213732 - 1 month ago 12
C Question

The program crashes if linked last node of linked list is deleted

I am having an issue while deleting the vowel from a linked List. The program accept command line arguments, combines them in a single string and add each character to a linked list as node.

when the program is executed with command line argument whose ending character is not vowel, the program works perfectly. But when the the argument ends with vowel, the program crashes with message Segmentation fault(core dumped).. I am not getting any idea how to handle this..

The program must not create any global variables so i've used double pointer.The program must not use any other header files than stdio.h string.h stdlib.h
All the functions are working properly this problem may have occured due to some mistakes in locateVowels() and removeVowels() function but i cannot figure out what the mistake is.


can this problem be solved using double pointer??
I cannot figure out what is wrong in this program.. I am new to c programming, please help me with this.. Please rectify me..
Thanks in advance.


The complete code is given below:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct linkedList {
char ch;
struct linkedList *node;
};
void printMenu(void);
char* combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int *);
void printLinkedList(struct linkedList **);
struct linkedList *locateVowel(struct linkedList *s);
int delHead(struct linkedList **);
void removeVowels(struct linkedList *);
int isEmpty(struct linkedList **);
int isVowel(char);
void freeLinkedList(struct linkedList *);

int main(int argc, char *argv[]) {
int choice, indexer = 0;
struct linkedList *s;
char *string;
if (argc == 1) {
printf("Parse a sentence");
} else {
s = (struct linkedList *) malloc(sizeof(struct linkedList));
string = combineWithNoSpaces(argc, argv);
addTolinkedList(string, &s, &indexer);
while (1) {
printMenu();
scanf("%d", &choice);
if (choice == 1) {
printLinkedList(&s);
} else if (choice == 2) {
if (!delHead(&s))
printf("Failed.Empty linked list");
} else if (choice == 3) {
removeVowels(s);

} else if (choice == 4) {
if (isEmpty(&s)) {
printf("Empty LinkedList");
} else
printf("Not Empty");
} else if (choice == 5) {
freeLinkedList(s);
break;
} else
printf("Invalic choice");
printf("\n");
}
}
return 0;
}
int isVowel(char ch) {
return (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u'
|| ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U');
}
void removeVowels(struct linkedList *s) {

s = locateVowel(s);

while (s != NULL) {
struct linkedList *temporary = s->node;

s->ch = temporary->ch;
s->node = temporary->node;

free(temporary);

s = locateVowel(s);
}
}
struct linkedList *locateVowel(struct linkedList *s) {

if (s == NULL) {
return s;
}

char ch = s->ch;

if (isVowel(ch)) {
return s;
}

if (s->node == NULL) {
return NULL;
}

return locateVowel(s->node);
}

int isEmpty(struct linkedList **s) {
if (*s == NULL)
return 1;
else
return 0;
}


int delHead(struct linkedList **s) {
struct linkedList *temp;
if ((*s) == NULL) {
return 0;
} else {
temp = (*s)->node;
free(*s);
*s = temp;
return 1;
}
}
void printLinkedList(struct linkedList **s) {
if ((*s) != NULL) {
printf("%c", (*s)->ch);
printLinkedList(&(*s)->node);
}
return;
}
void addTolinkedList(char *str, struct linkedList **s, int *indexer) {
if (*indexer == strlen(str)) {
*s = NULL;
return;
} else {
(*s)->ch = *(str + *indexer);
(*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList));
++*indexer;
addTolinkedList(str, &(*s)->node, indexer);
}
}
char * combineWithNoSpaces(int argc, char *argv[]) {
int i, j;
int count = 0;
int memory = 0;
char *str;
for (i = 1; i < argc; i++) {
for (j = 0; j < strlen(argv[i]); j++) {
++memory;
}
}
str = (char *) malloc(memory * sizeof(char) + 1);
for (i = 1; i < argc; i++) {
for (j = 0; j < strlen(argv[i]); j++) {
*(str + count) = argv[i][j];
++count;
}
}
*(str + memory + 1) = '\0';
return str;
}
void freeLinkedList(struct linkedList *s) {
while (s != NULL) {

struct linkedList *temporary = s;

s = s->node;

free(temporary);
}
}
void printMenu(void) {
printf("\n\n"
"1. print input arguments (no spaces)\n"
"2. remove first character\n"
"3. remove vowels\n"
"4. is the linked list empty?\n"
"5. exit program\n"
"Enter your choice>");
}


The program displays menu. The integer choice 3 is for deleting vowels that executes removeVowels() which further executes locateVowels().
The screen shot for output is :

argument whose ending character is not a vowel
argument with no ending vowel
argument whose ending character is a vowel
argument ending with vowel

Answer

at removeVowels, struct linkedList *temporary = s->node;
temporary will be NULL when s is last element.
So temporary->ch as NULL->ch occurs segmentation fault.

One of way of fix, in the following code.(Policy to overwrite rather than to remove the node.)

void removeVowels(struct linkedList *s) {
    s = locateVowel(s);

    while (s != NULL) {
        struct linkedList *temporary = s->node;
        if(temporary == NULL){
            s->ch = '\0';
            s->node = NULL;
            break;
        } else {
            s->ch = temporary->ch;
            s->node = temporary->node;
        }

        free(temporary);

        s = locateVowel(s);
    }
}

void printLinkedList(struct linkedList **s) {
    if ((*s) != NULL &&  (*s)->ch != '\0') {
        printf("%c", (*s)->ch);
        printLinkedList(&(*s)->node);
    }
    return;
}
Comments