Reputation: 95
#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
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
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
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
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
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
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
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