【问题标题】:Allocation of string, recursive function of two strings in one字符串的分配,两个字符串合二为一的递归函数
【发布时间】:2015-01-25 16:25:01
【问题描述】:

我编写了一个递归函数,它获取 3 个字符串,其中两个按字母顺序排序,第三个分配用于将前两个字符串放入第三个字符串中。字母顺序应保持不变;例如:

s1="abbcde";
s2="bckj";

所以,

s3="abbbccdekj";

这是main()中第三个字符串的分配:

char *s3 = (char*)malloc(len*sizeof(char));
SS1together(s1,s2,s3);//send to recursive function 3 strings

这就是函数:

   void SS1together(char *s1, char*s2, char*s3)
{
if (s1 == NULL || s2 == NULL)
{
    if (s1 == NULL)
    {
        s3[0] = s2[0];
        SS1together(s1, s2 + 1, s3 + 1);

    }
    else
    {
        s3[0] = s1[0];
        SS1together(s1 + 1, s2, s3 + 1);
    }
}
if (s1 != NULL && s2 != NULL)
{
    if (s1[0] <= s2[0])
    {
        s3[0] = s1[0];
        SS1together(s1 + 1, s2, s3 + 1);
    }
    else
    {
        s3[0] = s2[0];
        SS1together(s1 , s2 + 1, s3 + 1);
    }
}
}

显示是内存的问题,但是找不到。

我分配的字符串 3,在 main 函数中,还有一个可以完美运行的函数,所以我把 main 放在了全图:

  void main()
{
char *s1[N], *s2[N], *s3[N];//N=30 ,it is define in the top
int ans, len;

printf("Please enter your string  s1 and then string s2\n");
gets(s1);
gets(s2);
len = strlen(s1) + strlen(s2);

if ((CheckS(s1) == 0) || (CheckS(s2) == 0))
    printf("Not sorted\n");
else
{
    char *s3 = (char*)malloc(len*sizeof(char));
    SS1together(s1,s2,s3);
    puts(s3);
    free(s3);
}
_getch();
}

【问题讨论】:

  • 你没有展示len是如何计算的(它必须是strlen(s1) + strlen(s2) + 1),你也没有展示输出字符串是如何以空值结尾的(尽管它可能会自动发生——我'在声称它没有之前有一些事情要做;但我担心如果s2[0] == '\0'同时s1[0] == '\0',第一个if子句中的递归。
  • 看起来您只是在尝试做something like this,这可能比您最初想象的要简短)。而且您发布的代码在分配s3 时缺少+1,以说明随后的终止符。
  • 这种行:'s3[0] = s2[0];'不复制字符串,它复制的只是字符串的第一个字节。实际需要的是:'strcpy(s3, s2);'并且 s3 需要是 s3 = malloc( strlen(s1)+strlen(s2)+1);注意:sizeof(char) 总是 1

标签: c string recursion


【解决方案1】:

您的距离适中,但尚未充分考虑终止条件。迭代合并排序数据也比递归合并更容易。

您没有显示 len 是如何计算的(它必须是 strlen(s1) + strlen(s2) + 1),但即使这是正确的,您的代码也会遇到问题。例如,考虑最简单的情况,两个空字符串。第一个if 执行,但递归使用超出字符串末尾的s2 + 1,并导致灾难。我认为修复这个问题需要类似于以下代码:

void SS1together(char *s1, char *s2, char *s3)
{
    if (s1 == NULL || s1[0] == '\0')
    {
        s3[0] = s2[0];
        if (s2[0] != '\0')
            SS1together(s1, s2 + 1, s3 + 1);
    }
    else if (s2 == NULL|| s2[0]=='\0')
    {
        s3[0] = s1[0];
        if (s1[0] != '\0')
            SS1together(s1 + 1, s2, s3 + 1);
    }
    else if (s1[0] <= s2[0])
    {
        s3[0] = s1[0];
        SS1together(s1 + 1, s2, s3 + 1);
    }
    else
    {
        s3[0] = s2[0];
        SS1together(s1, s2 + 1, s3 + 1);
    }
}

警告:未经测试的代码。

迭代替代

void SS1together(char *s1, char *s2, char *s3)
{
    if (s1 == NULL)
        s1 = "";
    if (s2 == NULL)
        s2 = "";
    while (*s1 != '\0' && *s2 != '\0')
    {
        if (s1[0] <= s2[0])
            *s3++ = *s1++;
        else
            *s3++ = *s2++;
    }
    while (s1[0] != '\0')
        *s3++ = *s1++;
    while (s2[0] != '\0')
        *s3++ = *s2++;
    *s3 = '\0';
}

警告:还有未经测试的代码。

【讨论】:

  • 我忘记了 len=strlen(s1)+strlen(s2)+1
【解决方案2】:

您的代码假定当s1NULL(第一个if)时,s2 不是NULL 并递增s2 并进行递归调用。

但是当s2 字符串小于s1 时,s2 将首先到达末尾,因此在递归调用中传递s2+1 将导致访问超出范围的内存。从技术上讲,这会导致未定义的行为,并且实际上很可能会导致内存访问冲突。

您应该在增加指针之前进行更严格的 NULL 检查 - s1s2s3

【讨论】:

  • 我将其修复为: if (s1 == NULL || s1[0] == '\0' || s2 == NULL || s2[0] == '\0')这是第一个if,然后是另外两个if,一个用于s1==NULL,另一个用于s2==NULL,但仍有问题/
  • @t_box24:更新您的问题而不使此答案无效(因此添加修改后的代码而不是替换原始代码)。您可以控制问题中的格式;你不能在 cmets 中有意义地格式化。
  • @t_box24,测试也应该针对*s1==NULL*s2== NULL
猜你喜欢
  • 2012-05-15
  • 2017-07-16
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 1970-01-01
  • 2023-03-23
  • 2015-05-27
  • 1970-01-01
相关资源
最近更新 更多