字符串数组排序与数据存储

求解答:
1.存储在什么区域的字符串能交换其内容?
2.GetStringsA,GetStringB和FreeStrings函数的第一个参数为什么要使用三级指针?如果不用三级指针,会有什么结果?


 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define NUM 20
 
void BubbleA(char(*str)[NUM], int size)            
{
    // 以数组指针为基础进行排序
}
 
void BubbleB(char* str[], int size)                    
{
    // 以指针数组为基础进行排序
 
}
 
void ShowStringsA(const char* prompt, const char(*str)[NUM], int n)
{
    int i;
    if (n > 0)
        printf("%s%s", prompt, str[0]);
    for (i = 1; i < n; i++)
        printf(", %s", str[i]);
    printf("\n");
}
 
void ShowStringsB(const char* prompt, const char* str[], int n)
{
    int i;
    if (n > 0)
        printf("%s%s", prompt, str[0]);
    for (i = 1; i < n; i++)
        printf(", %s", str[i]);
    printf("\n");
}
 
void GetStringsA(char*** dest, const char(*str)[NUM], int n)
{
    int i, len;
    *dest = (char**)calloc(n, sizeof(char**));
    if (dest == NULL) return;
    for (i = 0; i < n; i++)
    {
        len = strlen(str[i]);
        (*dest)[i] = (char*)calloc(len + 1, sizeof(char));    // 请注意strlen(str[i])+1
        strcpy_s((*dest)[i], len + 1, str[i]);
    }
}
 
void GetStringsB(char*** dest, const char* str[], int n)
{
    int i, len;
    *dest = (char**)calloc(n, sizeof(char**));
    if (dest == NULL) return;
    for (i = 0; i < n; i++)
    {
        len = strlen(str[i]);
        (*dest)[i] = (char*)calloc(len + 1, sizeof(char));
        strcpy_s((*dest)[i], len + 1, str[i]);
    }
}
 
void FreeStrings(char*** strs, int n)
{
    if (*strs != NULL)
    {
        for (int i = 0; i < n; i++)
            if ((*strs)[i] != NULL)
                free((*strs)[i]);
        free(*strs);
        *strs = NULL;
    }
}
 
void TestString()
{
    char strA[][NUM] = { "enter", "number", "size", "begin", "of", "cat", "case", "program", "certain", "a", "cake", "side" };
    char* strB[] = { "enter", "number", "size", "begin", "of", "cat", "case", "program", "certain", "an", "cake", "side" };
    char** strC, ** strD;
    int n1 = sizeof(strA) / sizeof(*strA), n2 = sizeof(strB) / sizeof(*strB);
    GetStringsA(&strC, strA, n1);
    GetStringsB(&strD, strB, n2);
 
    printf("\n\t*** 多种不同存储方式的C-字符串数组的排序 ***\n");
    ShowStringsA("\n原始数据: ", strA, n1);
    BubbleA(strA, n1);
    ShowStringsA("排序结果: ", strA, n1);
 
    ShowStringsB("\n原始数据: ", strB, n2);
    BubbleB(strB, n2);
    ShowStringsB("排序结果: ", strB, n2);
 
    ShowStringsB("\n原始数据: ", strC, n1);
    BubbleB(strC, n1);                        // 调用一个排序函数执行排序操作
    ShowStringsB("排序结果: ", strC, n1);
 
    ShowStringsB("\n原始数据: ", strD, n2);
    BubbleB(strD, n2);                        // 调用一个排序函数执行排序操作
    ShowStringsB("排序结果: ", strD, n2);
 
    FreeStrings(&strC, n1);
    FreeStrings(&strD, n2);
}
 

以下来自GPT的回答:

  1. 存储在堆区的字符串可以交换其内容。在这段代码中,通过使用动态内存分配函数callocmalloc,字符串被分配到了堆区。

  2. 第一个参数使用三级指针的原因是为了在函数内部修改指针的值并将其指向新的内存地址。如果不使用三级指针,而是使用二级指针,则函数内部只能修改指针指向的内存内容,无法修改指针本身。结果是,在函数返回后,调用函数的地方仍然会指向原来的内存地址,无法获取到新分配的内存空间的地址。

使用三级指针可以允许在函数内部分配内存并将指针指向新的内存地址,然后通过指针的指针传递修改后的指针值到函数外部。这样,调用函数的地方将指向新分配的内存地址,可以正确获取到函数内部分配的内存空间。

简而言之,使用三级指针可以修改指针本身的值,而二级指针只能修改指针指向的内容。

在这段代码中,如果不使用三级指针,而是使用二级指针,GetStringsAGetStringsB函数将无法正确分配内存并将修改后的指针值传递到函数外部,导致内存泄漏或访问无效的内存。