微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如果出现 k 次,则删除字符串中的相邻重复项---堆缓冲区溢出错误

如何解决如果出现 k 次,则删除字符串中的相邻重复项---堆缓冲区溢出错误

给定一个字符串 s一个整数 kk 重复删除包括k 中选择 s 个相邻且相等的字母并删除它们,导致被删除子串的左侧和右侧连接在一起。 我们反复在 k 上进行 s 次重复删除,直到无法再删除为止。 我尝试了以下代码,它在一台机器(机器 1)上工作,并在另一台机器(机器 2)中引发错误

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

int sizeOfString(char * s)
{
    int count=0;
    while(s[count]!='\0')
        count ++;
    
    return count;
}

int getSubString(char *source,char *target,int from,int to)
{
    int i=0,j=0;
    for(i=from,j=0;i<=to;i++,j++){
        target[j]=source[i];
    }
    target[j]='\0'; 
    return 0;   
}

char * removeDuplicates(char * s,int k){
        int sizeString=sizeOfString(s);
        char *stringS= (char*)calloc(sizeString,sizeof(char));
        strcpy( stringS,s);
        int occuranceCount=1;
        int i=1;
        for (i=1;i<sizeString;i++)
        {
          if (s[i]==s[i-1])
          {
              occuranceCount++;
          }
          else{
              occuranceCount=1;
          }
          if (occuranceCount==k)
          {
              char *firstPart=(char*)calloc(i-k,sizeof(char));
              getSubString(s,firstPart,i-k);
              char *secondPart=(char*)calloc(sizeString,secondPart,i+1,sizeString-1);
              strcat(firstPart,secondPart);
              strcpy(s,firstPart);
              free (firstPart);
              free(secondPart);
              removeDuplicates(s,k);
          }
            
        }
    free(stringS);
    return s;
            
}

int main()
{
    char word[]="adbbbcccb";
    printf("after truncating the string is %s\n",removeDuplicates(word,3));
    return 0;
}

机器 1 输出

after truncating the string is adb


...Program finished with exit code 0
Press ENTER to exit console.

机器 2 在 PC、BP 和 SPthe error is shown in the attached picture 的特定值处引发堆缓冲区溢出错误。我做错了什么?

解决方法

对于初学者来说,不清楚为什么您编写自己的函数 sizeOfString 而不是使用标准字符串函数 strlen 而另一方面您正在使用其他标准字符串函数,例如 {{1} } 或 strcpy

要么你应该在任何需要标准字符串函数的地方使用它,要么你不应该完全使用标准字符串函数。

使用动态分配内存的方法效率低下且不安全。

例如这个代码片段

strcat

导致内存溢出,因为没有为源字符串的终止零分配空间。

该功能存在错误。例如,假设 int sizeString=sizeOfString(s); char *stringS= (char*)calloc(sizeString,sizeof(char)); strcpy( stringS,s); 等于 k 并且字符串以两个相等的字符开头。在这种情况下,您有(请参阅此代码片段)

2

int occuranceCount=1; int i=1; for (i=1;i<sizeString;i++) { if (s[i]==s[i-1]) { occuranceCount++; } else{ occuranceCount=1; } if (occuranceCount==k) { char *firstPart=(char*)calloc(i-k,sizeof(char)); //... 等于 i1 递增并变为等于 2,因为字符串的第二个字符等于字符串的第一个字符。因此,occuranceCount 调用中的表达式 i - k 等于 calloc,这会导致分配的内存大小无效,从而导致未定义的行为。

或者例如在这个声明之后

-1

以及函数本身的递归调用

strcpy(s,firstPart);

字符串removeDuplicates(s,k); 的长度和使用的索引s变得无效。所以for循环依次无效。

我可以建议以下演示程序中显示的以下非递归函数。该函数不是基于使用标准 C 字符串函数,也不动态分配内存。

i

程序输出为

#include <stdio.h>

char * removeDuplicates( char *s,size_t n )
{
    if ( n == 1 )
    {
        *s = '\0';
    }
    else if ( n != 0 )
    {
        char *p = s;
        for ( char *q = s; *q; )
        {
            char c = *q;
            size_t i = 1;
            while ( i < n && *++q == c ) ++i;
            
            if ( i != n )
            {
                if ( p != q - i )
                {
                    while ( i ) *p++ = *( q - i-- );
                }
                else
                {
                    p += i;
                }
            }
            else
            {
                ++q;
            }
        }
        
        *p = '\0';
    }
    
    return s;
}

int main(void) 
{
    char s0[] = "112223333";
    
    puts( removeDuplicates( s0,0 ) );
    
    char s1[] = "112223333";
    
    puts( removeDuplicates( s1,1 ) );
    
    char s2[] = "112223333";
    
    puts( removeDuplicates( s2,2 ) );
    
    char s3[] = "adbbbcccb";
    
    puts( removeDuplicates( s3,3 ) );
    
    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。