【问题标题】:String Compare and Deep Copy with Custom Struct and Pointers使用自定义结构和指针进行字符串比较和深度复制
【发布时间】:2021-10-14 11:39:37
【问题描述】:

我目前正在尝试在不使用string.h 库的情况下为自定义字符串结构编写一堆函数,但是在我的几个函数中实现我的结构时遇到了一些困难——特别是copy_string(...)compare_string(...)。本质上,这两个函数应该与 C 中的 strcpy(...)strcmp(...) 做同样的事情,但我希望它们与下面定义的基本 String 对象一起工作。

这是结构本身:

struct _String {

   char     *letters; // dynamically-allocated array to hold the characters
   uint32_t  count;   // number of characters in the string
};
typedef struct _String String;

/* IMPORTANT NOTE:
 *    String object S:
 *
 *    S.letters points to an array of dimension S.count + 1 and S.letters[S.count] == '\0'.
 *    If S.count > 0, then S.letters[0:S.count-1] hold the character letters for the string.
 */

这是我当前对 copy_string 的实现,其中 cmets 描述了我希望我的函数做什么:

/** Makes an exact, full copy of a String.
*
* Pre:
*    *target is a String object
*    *source is a String object
*    target != source
* Post:
*    no memory leaks have occurred and
*    *target is a deep copy of *source
*    target->count = source->count
*    target->letters[i] == source->letters[i], i = 0 to target->count
*    target->letters != source->letters
*    *target is a String object
*
* Returns:
*    the count of target->letters
*    a negative value, if some error occurs
*/
int32_t copy_string(String* const target, const String* const source) {

    // int8_t count = 0;
    // while (source->letters[count] != '\0') { }

    if (source->letters == NULL)
        return -1;

    int i = 0;

    while (source->letters[i] != '\0') {

        target->letters[i] = source->letters[i];
        i++;

    }

    target->letters[target->count] = '\0';
    target->count = source->count;

    if (target->letters == NULL)
        return -2;

    return target->count;

}

这是我当前对 compare_string 的实现,其中 cmets 描述了我希望我的函数执行的操作:

/** Compares two Strings.
 * 
 *  Pre:
 *    *first is a String object
 *    *second is a String object
 *
 *  Returns:
 *    < 0 if first precedes second based on ASCII values
 *      0 if first equals second
 *    > 0 if first follows second based on ASCII values
 */
int32_t compare_string(const String* const first, const String* const second) {

    while (first->letters && (first->letters == second->letters))
        first++, second++; // impossible due to const qualifiers

    return first->letters - second->letters    
}

我遇到了编译错误,例如“成员 count 是只读对象”、内存泄漏以及其他与指针相关的问题。我实际上是在四个星期前开始学习 C 的,所以请多多包涵。任何批评和/或帮助都会很棒。

(更新)这是string_compare 应该如何工作的示例:第一个字符串是“cat”,第二个字符串是“elephant”。该函数应通过使用 > 或

【问题讨论】:

  • 为什么要在不使用字符串库的情况下重新发明轮子?如果您的目标是学习该语言,我建议您先阅读 string.c 的源代码。
  • 我完全同意,但这是为课堂项目做准备。我试图理解为什么这段代码不能帮助我更好地理解项目规范。我们本质上是在以简化的形式重新编写字符串库,并且使用上述结构编写这些函数应该为我们的项目做好准备。实现上述功能有什么技巧吗?
  • 感谢您的回复。明白了。顺便说一句,如果您的程序导致内存泄漏,您能否提供调用函数的代码?调用者负责管理(分配和释放)内存。
  • 是否必须使用struct成员count来保存字符串的长度?当count的值与实际长度(NUL字符之前的字符数)冲突时,我们认为它是多余的,我们需要定义行为。
  • 很遗憾,我无法提供托管在代码提交站点上的测试代码。我相信使用了 Valgrind 调用,这就是检测内存泄漏的原因。假设,测试代码仅根据提供的结构使用 String 对象调用我的函数。此外,函数需要使用给定的结构,并且给定的函数参数是用于测试目的。

标签: c pointers struct memory-leaks free


【解决方案1】:

copy_string() 函数中,您指的是变量target-&gt;count 在分配之前。将两句顺序切换为:

target->count = source->count;
target->letters[target->count] = '\0';

compare_string() 函数中,您的代码:

for (int i = 0; i < first->count; i++) {
    if (*(first->letters + i) == *(second->letters + i))
        return 0;
}

仅在比较第一个字符后返回0立即
请尝试以下方法:

int32_t compare_string(const String* const first, const String* const second) {

    int32_t i;
    while (1) {
        int32_t c1 = first->letters[i];
        int32_t c2 = second->letters[i];
        if (!c1) {              // end of string "first"
            if (!c2) {          // end of string "second", too
                break;          // both "first" and "second" ends
            } else {
                return -c2;     // "first" ends before "second"
            }
        } else if (!c2) {       // "second" ends before "first"
            return c1;
        } else if (c1 != c2) {  // the characters differ
            return c1 - c2;     // return the difference
        }
        i++;
    }

    return 0;                   // exact match
}

从您的评论来看,内存泄漏似乎不是您的责任。

【讨论】:

  • 感谢您的回复。在compare_string 函数中,两个字符串的顺序取决于哪个字符串按字母顺序排列(或者在C 的情况下,按ASCII 值排序)。我相信您的代码一次只比较每个字符串中的单个给定字母。有什么想法吗?
  • 感谢您的反馈。我希望您澄清您对我的代码的担忧。您能否提供一些要比较的两组字符串和预期结果来证明您的要求?请通过编辑您的问题将它们包括在内,而不是作为评论。我会在 7 小时后回来,因为现在是我所在时区的时间。干杯。
  • 感谢您更新您的问题。尽管附加信息有限,但我确信我的compare_string 可以正常工作。实际上我已经测试过它的行为与库 strcmp 函数完全相同。我仍然没有得到你对我的功能的关注。我强烈建议您编写自己的测试代码(主函数)来调用函数、编译并运行,然后再将函数提交给主机。否则你无法判断问题所在。
  • 对于信息有限,我深表歉意,您说我应该做一些手动测试是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-14
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-03
相关资源
最近更新 更多