简体   繁体   English

从字符串中删除元音,堆栈粉碎错误

[英]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 . 在这里,我必须从字符串str删除元音。 I am storing the resulting string in arr . 我将结果字符串存储在arr But stack smashing error comes whenever I execute it. 但是无论何时执行堆栈粉碎错误都会出现。 why? 为什么?

What will happen when the char m is processed? 处理字符时会发生什么?

you will write it 5 times to arr. 您将其写5次到arr。 In general all chars will be written 4 or 5 times. 通常,所有字符将被写入4或5次。

Don't write to arr in the inner-loop. 不要在内部循环中写arr。 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. 在循环之后测试标志,以查看是否要写入char。

You have error in the check, you are copying the same characheter 5 times if the characheters is not vowel. 您的支票有误,如果字符不是元音,您将复制同一字符5次。 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循环中使用它:

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. 顺便说一句 ,您必须在arr字符串的末尾添加null charachter。 After the for loop add the follwing line: 在for循环之后,添加以下行:

arr[j] = '\0';

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. 似乎改变j的值,每次都存在不匹配。 For example lets say the first character 'm', will end up being copied more than once in your 'arr' array. 例如,假设第一个字符“ m”将最终在“ arr”数组中被复制多次。

Stack smashing means you are using stack (a part of computer memory) illegally. Stack smashing意味着您非法使用堆栈(计算机内存的一部分)。 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 . 例如,如果您尝试将15个元素添加到容量为10个元素的数组中,则将发生stack smashing

Here in your case, the array char arr[80]; 在您的情况下,数组char arr[80]; has the capacity for 80 chars, but you are adding more than 80 chars in this array. 可以容纳80字符,但是您要在此数组中添加80个以上的字符。 This is why you are getting stack smashing error. 这就是为什么您会得到stack smashing错误的原因。

There are two issues in your code. 您的代码中有两个问题。 First, you are adding elements from str[] more than one times to arr[] . 首先,您要将str[]元素添加到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. 在这里,您将str[i]与每个元音字符进行比较,并每次将该字符添加到arr[] This way each character is added 5 times (non-vowel characer), or 4 times (a vowel character). 这样,每个字符将被添加5次(非元音字符)或4次(一个元音字符)。

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. 要解决此问题,您需要将str[i]与所有元音进行比较,并且仅在与任何元音不匹配时才将其添加到arr[] 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. 其次,您不检查arr[]是否有剩余空间来添加任何新字符。 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 [] . 在这里,在for循环条件下,您需要确保arr []留有空间。 So, you need to add one more condition in your for loop. 因此,您需要在for循环中添加另一个条件。

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'; 

I modified your code a little change with a flag and at the end you missed arr[j]='\\0'; 我用一个flag修改了您的代码,最后您错过了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. 这可能与先前答案的想法相同。

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!) : 标准库中有一些字符串函数可能会对您有所帮助,strchr()是其中之一(您可以摆脱内循环!):

#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;
}

You are actually duplicating the characters from str for each failed comparison to a vowel. 您实际上是将每个失败比较的str的字符复制到元音。 The resulting string is between 4 and 5 times longer than the original, much longer than the destination array arr . 结果字符串比原始字符串长4到5倍 ,比目标数组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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM