【问题标题】:C - Recursion with stringsC - 字符串递归
【发布时间】:2017-10-28 09:57:39
【问题描述】:

我正在尝试在C 中编写一个函数,它获取 2 个指针,一个指向字符串中的第一个字符,另一个指向字符串中的中间字符。该函数需要检查字符串的前半部分是否与后半部分相同(忽略大小写)并返回"TRUE""FALSE"

我不知道是什么停止了递归条件以及为什么它不起作用。

这是我的代码。错误是什么?

#define SIZE 80
enum { FALSE = 0, TRUE = 1 };

int CheckString(char* start, char* middle);

int main()
{
    char str[SIZE], *pstart, *pmiddle;

    printf("Enter a String-->:");
    fgets(str, SIZE, stdin);

    pstart = &str[0];
    pmiddle = &str[(strlen(str) - 1) / 2];

    printf("  %d \n", CheckString(pstart, pmiddle));

    return 0;
}

int CheckString(char* start, char* middle)
{
    if (middle == '\0');
    return TRUE;

    if ((*start == *middle) || (*start == *middle + 32) || (*start == *middle - 32))
        CheckString(start + 1, middle + 1);
    else
        return FALSE;
}

我把它改成了这个代码

int CheckString(char* start, char* middle)
{   
    if ((*start == *middle) || (*start == *middle + 32) || (*start == *middle - 32))
    {
        CheckString(start + 1, middle + 1);
        return TRUE;
    }
    else
        return FALSE;
}

现在它的工作但只针对第一个字符和中间它不会检查下一个字符 帮别人穿什么???

【问题讨论】:

  • main 函数中的pstartpmiddle 变量是单个字符,而不是指针。您的函数将超出这些变量的范围,您将有未定义的行为
  • 所以把它改成*pstart?
  • 这应该会发出编译器警告,因为递归路径不会返回值。您只调用CheckString(),而不是将其返回值返回到递归链。是的,pstartpmiddle 需要指向原始字符串的开头和中间,而不是当前实现的那些位置的字符副本。
  • 那么我如何将其返回值返回到递归链中?,我将 pstart 更改为 *pstart ..
  • 版主注意:请不要破坏您的帖子。发布问题后,您已将内容授权给整个 Stack Overflow 社区(根据 CC-by-SA 许可)。如果您想取消此帖子与您的帐户的关联,请参阅What is the proper route for a disassociation request?

标签: c string pointers recursion


【解决方案1】:

其他答案指出了主要问题,即您必须返回递归调用函数返回的值,但您的代码中还有其他问题。

fgets 用于收集用户输入时,它也会复制换行符,这会使你的函数失败。

这是一个可能的修复方法,还有一些其他提示:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

#define SIZE 160

bool CheckString(char* start, char* middle);

int main()
{
    char str[SIZE];

    for (;;)
    {
        printf("Enter a String-->:");
        if ( fgets(str, SIZE, stdin) == NULL ) break;

        // remove the newline copied in the string by fgets
        size_t length = strcspn(str, "\n");
        str[length] = '\0';

        if ( length == 0 ) continue;

        printf("%s\n", CheckString(str, str + length / 2) ? "True" : "False");
    }

    return 0;
}

bool CheckString(char* start, char* middle)
{
    if ( *middle == '\0') return true; 
    //   ^ note this     ^ here there was a ;

    if ( tolower(*start) == tolower(*middle) )
        return CheckString(start + 1, middle + 1);
    else
        return false;
}

【讨论】:

    【解决方案2】:

    我认为您仍然可以使用循环进行存档。这是您修改后的工作代码。解决其他人提到的问题。

    #define SIZE 80
    enum { FALSE = 0, TRUE = 1 };
    
    int CheckString(char* start, char* middle);
    
    int main()
    {
        char str[SIZE];
        char *pstart = NULL;
        char *pmiddle = NULL;
    
        printf("Enter a String-->:");
        fgets(str, SIZE, stdin);
    
        pstart = &str[0];
        pmiddle = &str[(strlen(str) - 1) / 2];
    
        printf("  %d \n", CheckString(pstart, pmiddle));
    
        return 0;
    }
    
    int CheckString(char* start, char* middle)
    {
        int flag = 0;
        char * end = middle;
        while (start != end) {
            if ((*start == *middle) || (*start == *middle + 32) || (*start == *middle - 32))
                flag = 1;
            else
                flag = 0;
    
          start++; middle++;
        }
    
            return flag;
    }
    

    递归版本

    #define SIZE 80
    enum { FALSE = 0, TRUE = 1 };
    
    int CheckString(char* start, char* middle, char* end, int []);
    
    int main()
    {
        char str[SIZE];
        char *pstart = NULL;
        char *pmiddle = NULL;
        char *end = NULL;
        int  flag[1];
        *flag = 0;
    
        printf("Enter a String-->:");
        fgets(str, SIZE, stdin);
    
        pstart = &str[0];
        pmiddle = &str[(strlen(str) - 1) / 2];
        end = pmiddle;
        printf("  %d \n", CheckString(pstart, pmiddle , end, flag));
    
        return 0;
    }
    
    int CheckString(char* start, char* middle, char* end, int *flag)
    {
    
        if (start == end)
            return *flag;
    
        else 
        {
            if ((*start == *middle) || (*start == *middle + 32) || (*start == *middle - 32))
                *flag = 1;
            else
                *flag = 0;
    
            start++; middle++;
            return CheckString(start, middle,  end, flag);
        }
    
    
    }
    

    【讨论】:

    • 但是为什么为什么??????我知道如何用循环来做我问如何用递归来做......RECURSION!!
    • @monkey.D.Ganga 添加了递归版本
    【解决方案3】:

    正如@some-programmer-dude 所说,pstartpmiddle 只是分配了 str[0]str[(strlen(str) - 1) / 2] 值的字符变量,而不是它们各自的地址。在函数中,您传递pmidpstart 的地址。您应该按如下方式更改代码-

    替换 pmid 和 pstart。而是将它们更改为指针 -

    char* pstart,pmid;
    pstart = &str[0];
    pmiddle = &str[(strlen(str) - 1) / 2];
    

    【讨论】:

    • 你能检查我的代码并告诉我穿了什么吗? @Amarnath Karthi
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 2017-04-24
    • 2014-02-22
    • 2015-09-27
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    相关资源
    最近更新 更多