0

我是这个网站的新手,所以如果我在第一篇文章中做错了什么,我深表歉意。我编写代码的方式(包括为可重用性而编写的代码),我必须使用 char* 数组。我正在将传入的 char* 转换为所有小写字母。我面临的问题涉及我释放 newString2。因为我将它分配给我的newString,所以释放它肯定会丢失我分配给newString 的信息,从而丢失分配给convertedKey 的数据。我在寻找如何成功释放分配的内存方面陷入困境,但也通过我的函数参数返回转换后的字符串的数据。那可能吗?以下是我当前转换为小写的函数。我对 strdup 也很陌生,所以我确定我没有给它任何正义。

void convertKeyCasing (ListElementPtr key, ListElement *convertedKey)
{
    ListElementPtr newString = (ListElementPtr) malloc (sizeof (ListElement));
    int i = 0;
    char ch;
    char *string = key->data.key.key;

    char *newString1 = strdup (string);

    while (isalpha (key->data.key.key[i]) != false)
    {
        ch = tolower(key->data.key.key[i]);

        newString1[i] = ch;

        ++i;
    }

    char* newString2 = strdup (newString1);

    newString->data.key.key = newString2;

    *convertedKey = *newString;

    key = convertedKey;

    free(newString2);
    free (newString1);
    free (newString);
}

我在列表中的结构包括:

typedef struct KEY_DATATYPE
{
    char* key;
    int length;
}KEY_DATATYPE;

typedef struct DATATYPE
{
    Q_DATATYPE data;

    KEY_DATATYPE key;

    // maintained so that it still works with list
  union
  {
    char charValue;
    unsigned int intValue;
    float floatValue;
  };
  unsigned short whichOne;
} DATATYPE;

typedef struct ListElement* ListElementPtr;
typedef struct ListElement
{
    DATATYPE data;
    ListElementPtr psNext;
    ListElementPtr psPrev;
} ListElement;

在我的驱动程序中,我正在创建一个 ListElementPtr 并为其分配一个键值,例如,

ListElementPtr listPtr;
listPtr->data.key.key = "Hello";

再次感谢您的帮助!

4

1 回答 1

1

您的代码中有很多很多错误。您泄漏内存,并设置指向然后释放的内存的指针。我将尝试向您展示如何最简单地编写代码,而不是试图解释所有错误。

从本质上讲,据我所知,您只是想将所有内容都转换key->data.key.key为小写。因此不需要任何动态分配。您可以像这样就地执行修改:

void convertKeyToLower(ListElementPtr key)
{
    char *ch = key->data.key.key;
    while (*ch != 0)
    {
        *ch = tolower(*ch);
        ch++;
    }
}

事实上,这个功能仍然设计得很糟糕。它将两个不同的方面混合在一起:列表元素和字符串处理。我会将字符串处理拆分为一个单独的函数:

void convertStringToLower(char *str)
{
    while (*str != 0)
    {
        *str = tolower(*str);
        str++;
    }
}

或者可能是这样的:

void convertStringToLower(char *str)
{
    for(int i = 0; str[i]; i++)
        str[i] = tolower(str[i]);
}

一旦你有了它,你可以简单地写:

convertStringToLower(element->->data.key.key);

并且任何时候您需要将字符串就地转换为小写,您都可以使用该功能。


从您对问题的更新,现在很清楚为什么您会收到您在评论中报告的分段错误。你写了:

listPtr->data.key.key = "Hello";

listPtr->data.key.key指向一个字符串文字。并且字符串文字是不可修改的。尝试这样做会调用未定义行为 (UB),并且该 UB 的典型表现是分段错误。发生这种情况是因为编译器通常将字符串文字存储在只读内存中。

您需要决定您的元素是否要存储文字或可修改的字符串。你不能真的希望将两者混合在一起。如果您尝试将两者混合,那么您将无法确定如何释放您的元素。那是因为你需要释放一个可修改的字符串,但你不能试图释放一个文字。

因此,您唯一合理的选择是始终使用可修改的字符串,并在释放元素时始终释放它们。因此,将上面的代码行替换为:

listPtr->data.key.key = strdup("Hello");
于 2013-11-27T09:18:49.553 回答