这个字符串的代码问题出在哪里


#include<stdio.h>
#define STRINGMAX 100
typedef struct 
{
    char vec[STRINGMAX];   
    int len;
}str;
int LenStr(str *r)
{
    int i=0;
    while(r->vec[i]!='\0')
        i++;
    return i;
}
str *CreateStr(str *r)
{
    gets(r->vec);
    r->len=LenStr(r);
    return r;
}
void ConcatStr(str *r1,str *r2) 
{
    int i;
    printf("r1=%s,r2=%s\n",r1->vec,r2->vec);
    if(r1->len+r2->len>STRINGMAX)
        printf("两个串太长,溢出!\n");
    else
    {
        for(i=0;i<r2->len;i++)
            r1->vec[r1->len+i]=r2->vec[i];
        r1->vec[r1->len+i]='\0';
        r1->len=r1->len+r2->len;
    }
}
void InsStr(str *r,str *r1,int i)
{
    int k;
    if(i>r->len+2||r->len+r1->len>STRINGMAX)
        printf("不能插入\n!");
    else
    {
    for(k=r->len-1;k>=i-1;k--)
            r->vec[r1->len+k]=r->vec[k];
        for(k=0;k<=r1->len;k++)
            r->vec[i-1+k]=r1->vec[k];
        r->len=r->len+r1->len;
    }
}
void DelStr(str *r,int i,int j)
{
    int k;
    if(i+j-1>r->len)
        printf("!\n");
    else
    {
        for(k=i+j-1;k<=r->len;k++,i++)
            r->vec[i-1]=r->vec[k];
        r->len=r->len-j;
    }
}
void main()
{    
    str a,b,c,d;
    str *r=&a,*r1;    
    char choice,p;
    int i,j,ch=1,k;
    r->vec[0]='\0';
    while(ch!=0)
    {
        printf("\n                     串子系统                  ");
        printf("\n***********************************************");
        printf("\n*          1-------创  建  字  串             *");
        printf("\n*          2-------连  接  字  串             *");
        printf("\n*          3-------插  入  子  串             *");
        printf("\n*          4-------删  除  子  串             *");
        printf("\n*          5-------显  示  字  串             *");
        printf("\n*          0-------返          回             *");
        printf("\n***********************************************");
        printf("\n请选择菜单号(0—8):");
        scanf("%c",&choice);
        getchar();
        if(choice=='1')
        {
            printf("\n请输入一个字符串:");
            CreateStr(r);
        }
        else 
            if(choice=='2')
            {
                printf("\n请输入所要连接的串:");
                r1=CreateStr(&b);
                ConcatStr(r,r1);
                printf("\n连接以后的新串值为:");
                puts(r->vec);
            }
            else 
                if(choice=='3')
                {
                    printf("\n请输入在第几个字符前插入:");
                            scanf("%d",&i);
                            getchar();
                            printf("\n请输入所要插入的字符串:");
                            r1=CreateStr(&b);
                            InsStr(r,r1,i);
                }
                else
                    if(choice=='4')
                    {
                        printf("\n请输入从第几个字符开始:");
                        scanf("%d",&i);
                        getchar();
                        printf("\n请输入删除的连续字符数:");
                        scanf("%d",&j);
                        getchar();
                        DelStr(r,i,j);
                    }
                                else
                                    if(choice=='5')
                                    {
                                        printf("\n该串值为:");
                                        if(r->vec[0]=='\0')
                                            printf("空!\n");
                                        else
                                            puts(r->vec);
                                    }
                                    else
                                    if(choice=='0')
                                    ch=0;
    }
}

img

基于new bing加以修改过后的回答:

  1. 问题出在 InsStr 函数中,因为在循环中 r1->len+k 可能会超过字符串 r 的最大长度,导致字符串溢出。修正的方法是在循环中加入一个判断条件 k < STRINGMAX - 1
  1. 在 DelStr 函数中,有一个问题是在从字符串 r 中删除子串时没有考虑到删除后的字符串应该以 '\0' 结束,这可能导致结果不正确。修改的方法是在删除完子串后,在字符串末尾添加 '\0'。此外,在循环中变量 k 和 i 的计算也存在问题,正确的计算应该是 k=i+j-1,即要删除的连续字符的最后一个字符的下标。
  1. 在菜单选择中,当用户输入菜单号后需要加上一个getchar()读取掉换行符,否则下次读取菜单号时会直接读取到上次剩余的换行符,造成错误的输入。
    修改过后:

img

img

 
 
#include<stdio.h>
#define STRINGMAX 100
typedef struct 
{
    char vec[STRINGMAX];   
    int len;
}str;
int LenStr(str *r)
{
    int i=0;
    while(r->vec[i]!='\0')
        i++;
    return i;
}
str *CreateStr(str *r)
{
    gets(r->vec);
    r->len=LenStr(r);
    return r;
}
void ConcatStr(str *r1,str *r2) 
{
    int i;
    printf("r1=%s,r2=%s\n",r1->vec,r2->vec);
    if(r1->len+r2->len>STRINGMAX)
        printf("两个串太长,溢出!\n");
    else
    {
        for(i=0;i<r2->len;i++)
            r1->vec[r1->len+i]=r2->vec[i];
        r1->vec[r1->len+i]='\0';
        r1->len=r1->len+r2->len;
    }
}
void InsStr(str *r, str *r1, int i)
{
    int k;
    if (i > r->len + 2 || r->len + r1->len > STRINGMAX)
        printf("不能插入!\n");
    else
    {
        for (k = r->len - 1; k >= i - 1; k--)
        {
            if (k + r1->len < STRINGMAX - 1)
                r->vec[k + r1->len] = r->vec[k];
        }
        for (k = 0; k < r1->len; k++)
        {
            if (i - 1 + k < STRINGMAX - 1)
                r->vec[i - 1 + k] = r1->vec[k];
        }
        r->len = r->len + r1->len;
    }
}

void DelStr(str *r, int i, int j)
{
    int k;
    if (i + j - 1 > r->len)
        printf("不能删除!\n");
    else
    {
        for (k = i + j - 1; k <= r->len; ++k)
            r->vec[k - j] = r->vec[k];
        r->len = r->len - j;
        r->vec[r->len] = '\0'; // 添加结束符
    }
}

void main()
{    
    str a,b,c,d;
    str *r=&a,*r1;    
    char choice,p;
    int i,j,ch=1,k;
    r->vec[0]='\0';
    while(ch!=0)
    {
        printf("\n                     串子系统                  ");
        printf("\n***********************************************");
        printf("\n*          1-------创  建  字  串             *");
        printf("\n*          2-------连  接  字  串             *");
        printf("\n*          3-------插  入  子  串             *");
        printf("\n*          4-------删  除  子  串             *");
        printf("\n*          5-------显  示  字  串             *");
        printf("\n*          0-------返          回             *");
        printf("\n***********************************************");
        printf("\n请选择菜单号(0—8):");
        scanf("%c",&choice);
        getchar();
        if(choice=='1')
        {
            printf("\n请输入一个字符串:");
            CreateStr(r);
        }
        else 
            if(choice=='2')
            {
                printf("\n请输入所要连接的串:");
                r1=CreateStr(&b);
                ConcatStr(r,r1);
                printf("\n连接以后的新串值为:");
                puts(r->vec);
            }
            else 
                if(choice=='3')
                {
                    printf("\n请输入在第几个字符前插入:");
                            scanf("%d",&i);
                            getchar();
                            printf("\n请输入所要插入的字符串:");
                            r1=CreateStr(&b);
                            InsStr(r,r1,i);
                }
                else
                    if(choice=='4')
                    {
                        printf("\n请输入从第几个字符开始:");
                        scanf("%d",&i);
                        getchar();
                        printf("\n请输入删除的连续字符数:");
                        scanf("%d",&j);
                        getchar();
                        DelStr(r,i,j);
                    }
                                else
                                    if(choice=='5')
                                    {
                                        printf("\n该串值为:");
                                        if(r->vec[0]=='\0')
                                            printf("空!\n");
                                        else
                                            puts(r->vec);
                                    }
                                    else
                                    if(choice=='0')
                                    ch=0;
    }
}

引用chatGPT作答,这段C语言代码的问题可能有以下几个:

1.gets()函数存在缺陷和安全隐患,容易导致缓冲区溢出攻击,应该避免使用。可以使用fgets()函数代替,限制输入长度并防止缓冲区溢出。

2.DelStr()函数中的循环条件可能存在问题,如果i+j-1等于r->len,则循环条件成立,但是r->vec[i+j-1]越界了。

3.InsStr()函数中的第一个循环条件应该是i>r->len,而不是i>r->len+2,因为字符数组的下标是从0开始的。

4.在main()函数中,第一次输入菜单号时,会多读入一个换行符,导致后面的输入函数无法读入正确的输入值。可以使用getchar()函数来读取多余的换行符。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^