Naman Sharma
Naman Sharma

Reputation: 95

Remove vowels from a character string, Stack smashing error

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

int main() {
    char str[] = "my name is khan. and i am not a terrorist\n";
    char arr[80];
    char wolf[] = { 'a', 'e', 'i', 'o', 'u', '\0' };
    int i, j, k, len;

    len = strlen(str);
    for (i = 0, j = 0; i < len; i++) {
        for (k = 0; k <= 4; k++) {
            if (wolf[k] != str[i]) {
                arr[j] = str[i];
                j++;
            }
        }
    }
    return 0;
}

Here, I have to remove vowels from string str. I am storing the resulting string in arr. But stack smashing error comes whenever I execute it. why?

Upvotes: 0

Views: 163

Answers (7)

Br34th7aking
Br34th7aking

Reputation: 89

You are getting a buffer overflow(probably) due to large number of comparisons being done. This part of your code:

if(wolf[k]!=str[i]){
    arr[j]=str[i];
    j++;
}

seems to change the value of j, every time there is a mismatch. For example lets say the first character 'm', will end up being copied more than once in your 'arr' array.

Upvotes: 1

chqrlie
chqrlie

Reputation: 144951

You are actually duplicating the characters from str for each failed comparison to a vowel. The resulting string is between 4 and 5 times longer than the original, much longer than the destination array arr. Writing beyond the end of the array invokes undefined behavior: an early program termination in your case.

Here is how to fix your problem:

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

int main() {
    char str[] = "my name is khan. and i am not a terrorist\n";
    char arr[80];
    char wolf[] = { 'a', 'e', 'i', 'o', 'u', '\0' };
    int i, j, k, len;

    len = strlen(str);
    for (i = 0, j = 0; i < len; i++) {
        for (k = 0; k < 5; k++) {
            if (str[i] == wolf[k])
                break;
        }
        if (k == 5) { // not a vowel
            arr[j] = str[i];
            j++;
        }
    }
    arr[j] = '\0';  // remember to put the final null byte to close the C string

    printf("result: %s\n", arr);
    return 0;
}

Upvotes: 0

joop
joop

Reputation: 4523

There are some string functions in the standard library that may help you, strchr() is one of them (you can get rid of the inner loop!) :

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

int main()
{
    char str[] = "my name is khan. and i am not a terrorist\n";
    char arr[80];
    char *wolf = "aeiouy";
    int i,j;
    for(i=j=0; arr[j] = str[i]; i++)
    {
            if ( !strchr (wolf, str[i]) ) j++;
    }
   printf("%s\n", arr);
    return 0;
}

Upvotes: 0

sps
sps

Reputation: 2720

Stack smashing means you are using stack (a part of computer memory) illegally. This illegal use of stack memory can be done in many ways. One way do this is to add more elements to an array than its capacity. For example if you try to add 15 elements to an array with capacity of 10 elements then you will have stack smashing.

Here in your case, the array char arr[80]; has the capacity for 80 chars, but you are adding more than 80 chars in this array. This is why you are getting stack smashing error.

There are two issues in your code. First, you are adding elements from str[] more than one times to arr[].

    /* Issue 1 */
    for(k=0;k<=4;k++)
    {
        if(wolf[k]!=str[i])
        {
            /* You are adding str[i] to 
               arr[] multiple times 
             */
            arr[j]=str[i];
            j++;
        }
    }

Here you are comparing str[i] with each vowel character and adding that character to arr[] everytime. This way each character is added 5 times (non-vowel characer), or 4 times (a vowel character).

To solve this issue, you need to compare str[i] with all vowels, and add it to arr[] only if it does NOT match to any vowel. There are many ways to do it. For example you can use an additional variable as a flag.

Second, you are not checking if there is any space left in arr[] to add any new character. In this part of your code:

/* Issue 2: You are not checking if space left in arr[] */
for(i=0,j=0;i<len;i++)
{

Here in your for loop condition you need to make sure that there is space left in arr[]. So, you need to add one more condition in your for loop.

This is one (among many) solutions:

/* Check if space left in arr, i.e. j < 80 */
for(i=0,j=0;i<len && j < 80;i++)
{
    /* Add a flag:
       1 means vowel
       0 means not a vowel
     */
    int v_flag = 0; 

    for(k=0;k<=4;k++)
    {
        if(wolf[k] == str[i])
        {
           v_flag = 1; /* Indicate that this is vowel */
           break;
        }
    }
    /* Add to arr[] only if not a vowel */
    if (v_flag == 0)
    {
        arr[j] = str[i];
        j++;
    }
}
/* Null terminate the string */
arr[j] = '\0'; 

Upvotes: 0

MOHAMED
MOHAMED

Reputation: 43548

You have error in the check, you are copying the same characheter 5 times if the characheters is not vowel. you should make your check in this way

for(i=0,j=0;i<len;i++)
{
    unsigned char isvowel = 0;
    for(k=0;k<=4;k++)
    {
        if(wolf[k]==str[i])
        {
            isvowel = 1;
            break;
        }
    }
    if (!isvowel) {
        arr[j]=str[i];
        j++;
    }   
}

or you can develop a separate function to check if charachter is vowel:

unsigned char isvowel(char c)
{
    char wolf[]={'a','e','i','o','u','\0'};
    int k;
    for(k=0;k<=4;k++)
    {
        if(wolf[k]==c)
        {
            return 1;
        }
    }
    return 0;
}

And you can use it in your for loop in this way:

for(i=0,j=0;i<len;i++)
{
    if (!isvowel(str[i]) {
        arr[j]=str[i];
        j++;
    }   
}

By the way, you have to add null charachter at the end of your arr string. After the for loop add the follwing line:

arr[j] = '\0';

Upvotes: 1

GShaik
GShaik

Reputation: 311

I modified your code a little change with a flag and at the end you missed arr[j]='\0';

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[]="my name is khan. and i am not a terrorist";
char arr[80]={0};
char wolf[]={'a','e','i','o','u','\0'};
int i,j,k,len,flag=0;
len=strlen(str);
for(i=0,j=0;i<len;i++)
{
    for(k=0;k<=4;k++)
    {
        if(wolf[k]==str[i])
        {
            flag = 1;
            break;
        }
    }
    if(0==flag)
    {
        arr[j]=str[i];
        j++;
    }   
 flag=0;    
}
arr[j]='\0';
printf("str:%s\n",str);
printf("arr:%s\n",arr);
return 0;
}

This may be the same idea of previous answers.

Upvotes: 0

4386427
4386427

Reputation: 44329

What will happen when the char m is processed?

you will write it 5 times to arr. In general all chars will be written 4 or 5 times.

Don't write to arr in the inner-loop. Instead use a flag to remember whether you had a match. Test the flag after the loop to see if the char is to be written or not.

Upvotes: 2

Related Questions