【问题标题】:How to recursively return string value in C?如何在C中递归返回字符串值?
【发布时间】:2019-02-01 13:32:40
【问题描述】:

尝试在这里学习一些东西,而不是解决特定问题。请帮助我找到一些适用于这种情况的最佳实践,并在可能的情况下澄清原因。提前感谢您的帮助。

基本上,我在已知范围内暴力破解了一个非常简单的哈希算法。函数根据散列测试字符串(在长度限制内)的可能性,直到它与传递的散列匹配。然后递归应该停止所有迭代并返回匹配的字符串。迭代是有效的,但是当找到答案时,似乎函数的每次运行都没有得到相同函数调用返回的值

这是函数的代码,为了清楚起见,额外添加了 cmets:

//'hash' is the hash to be replicated
//'leading' is for recursive iteration (1st call should have leading=="")
//'limit' is the maximum string length to be tested

string crack(string hash, string leading, int limit)
{
    string cracked=NULL, force=NULL, test=NULL;

    //as per definition of C's crypt function - validated
    char salt[3] = {hash[0], hash[1], '\0'};

    // iterate letters of the alphabet - validated
    for(char c='A'; c<='z'; c++)
    {
        // append c at the end of string 'leading' - validated
        test = append(leading,c);

        // apply hash function to tested string - validated
        force = crypt(test,salt);

        // if hash replicated, store answer in 'cracked' - validated
        if(strcmp(hash,force)==0)
        {
            cracked = test;
        }
        else
        {
            // if within length limit, iterate next character - validated
            if(strlen(test)<=limit+1)
            {
                // THIS IS WHERE THE PROBLEM OCCURS
                // value received when solution found
                // is always empty string ("", not NULL)
                // tried replacing this with strcpy, same result
                cracked = crack_des(hash,test,limit);
            }
        }

        // if answer found, break out of loop - validated
        if(cracked){break;}

        // test only alphabetic characters - validated
        if(c=='Z'){c='a' - 1;}
    }

    free(test);

    // return NULL if not cracked to continue iteration on level below
    // this has something to do with the problem
    return cracked;
} // end of function

从我对指针的记忆中,我猜这是传递引用而不是值的东西,但我没有足够的知识来解决它。我已阅读 this thread,但此建议似乎无法解决问题 - 我尝试使用 strcpy 并得到相同的结果。

免责声明:这是 EDX 哈佛大学 2018 年 CS50 中的一项练习。它不会影响我的评分(本周已经提交了两个完美的练习,这是必需的)但如上所述,我正在学习。

编辑:将标签编辑回 C(如 cmets 中所述,字符串来自 string.h,并且 append 由我编码并多次验证 - 我将在一会儿)。谢谢大家的cmets;问题解决了,吸取了教训!

【问题讨论】:

  • 有人在我不看的时候给 C 添加了字符串类型吗?还是 char* 的 typedef?
  • 你是说C++? C中没有string
  • ...据我所知,在 C++ 中的 bool 上下文中没有用于转换的运算符,因此如果意图是 C++,if(cracked){break;} 是可疑的。代码中的所有内容似乎都与它是一个 typdef 一致。
  • c 标签更改为c++append() 方法不是 C 方法。这是一个 C++ 方法。
  • 修复提交,使其中有递归函数。了解如何定义 stringappend 也会有所帮助。

标签: c string recursion cs50


【解决方案1】:

我在代码中发现了一个错误,但我不确定它是否是您问题的根本原因。

当代码命中时:

strcmp(hash,force)==0

然后你将'test'指向的字符串分配给'cracked':

cracked = test;

然后这条线被击中:

if(cracked){break;}

然后循环中断,下一行:

free(test);

此行将释放 test 指向的字符串,并记住它与 'cracked' 指向的字符串相同,因此您返回了一个已经释放的字符串

字符串会发生什么取决于您的编译器和 libc。您可以尝试通过为 'cracked' 分配内存来解决此问题:

cracked = strdup(test);

另外,'test' 和 'force' 字符串会导致内存泄漏,但它们应该与您的问题无关。

【讨论】:

  • 你假设字符串在这里是 std::string 吗? .如果然后cracked = test; 进行复制,而不是保留指针。但我不明白为什么free(test) 是字符串。
  • @PraAnj 他是用strcmp()操作字符串,用free()释放字符串,标签是“C”而不是“C++”,所以我把string当成char的typedef *
  • @PraAnj 我在回答问题的时候,标签还是“C”,现在被其他人编辑了。我认为很明显,在问题中,作者使用 strcmp/strlen/free 来操作“字符串”类型。 typedef char * 是唯一合理的猜测。且未经与作者进一步确认而将标签编辑为C++概不负责。
  • @YiZhenfei OP 没有试图否认或确认他们的源代码是否为 C。鉴于我们掌握的信息,可以肯定地假设这是一篇 C++ 帖子。我同意你的说法;如果需要,当 OP 说明更多信息时,将再次编辑标签。
  • 感谢@YiZhenfei,确实释放test 是问题所在。正如你所提到的,我之前有过完整的执行失败,并认为这可能是由于testforce 引起的内存泄漏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-30
  • 2017-10-28
相关资源
最近更新 更多