如何在C中最小化动态分配的字符串大小

问题描述 投票:0回答:1

如何减少动态分配的字符串数组的大小?

int main(){
    char **a = malloc(sizeof(char *)*5);
    for (int i = 0; i < 5; i++){
        a[i] = malloc(sizeof(char) * 10);
    }
    strcpy(a[0], "apple");
    strcpy(a[1], "cat");
    strcpy(a[2], "dog");
    strcpy(a[3], "sun");
    strcpy(a[4], "moon");
    //Now I want to get rid of dog and resize the array to 5
}

我尝试创建新的动态字符串数组,如下所示:

char **temp_storage = malloc(sizeof(char *) * 4);
for (int i = 0; i < 4; i++){
    temp_storage[i] = malloc(sizeof(char) * 10);
}

然后将除“ dog”以外的所有元素从“ a”复制到“ temp_storage”。一切完成后,我释放'a'

中的所有元素
for (int i = 0; i < 5; i++){
    free(a[i]);
    a[i] = NULL;
}

然后我将a的大小重新分配为4。然后将'temp_storage'中的所有元素复制到'a'。

但是我仍然收到AddressSanitizer错误。

c dynamic-memory-allocation address-sanitizer
1个回答
0
投票

如果您只想删除一个条目,则实际上并不需要另一个临时数组。您要做的就是:

  1. 找到要删除的条目(您可能已经有了索引,或者您想要搜索内容)。
  2. 释放该条目。
  3. 将所有其他条目移回一个位置(或仅将最后一个移到已删除的位置,如果您不关心顺序,这会更快)。
  4. realloc()重新分配以调整数组的大小。

这里是一个例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ENTRY_SIZE 10

int main(void) {
    size_t size = 5;
    char **arr, **tmp;
    size_t i;

    arr = malloc(sizeof(char *) * size);
    if (arr == NULL) {
        perror("malloc failed");
        return 1;
    }

    for (i = 0; i < size; i++) {
        arr[i] = malloc(sizeof(char) * ENTRY_SIZE);
        if (arr[i] == NULL) {
            perror("malloc failed");
            return 1;
        }
    }

    strcpy(arr[0], "apple");
    strcpy(arr[1], "cat");
    strcpy(arr[2], "dog");
    strcpy(arr[3], "sun");
    strcpy(arr[4], "moon");

    // Search for "dog" and remove it if found
    for (i = 0; i < size; i++) {
        if (!strcmp(arr[i], "dog")) {
            free(arr[i]);
            break;
        }
    }

    // If "dog" was found and removed
    if (i < size) {
        // Move all elements after "dog" back one position
        for (; i < size - 1; i++)
            arr[i] = arr[i + 1];

        // Resize the array
        size--;
        tmp = realloc(arr, sizeof(char *) * size);
        if (tmp == NULL) {
            perror("realloc failed");
            return 1;
        }

        arr = tmp;
    }

    // Print everything to show the results
    for (i = 0; i < size; i++)
        printf("%d: %s\n", i, arr[i]);

    // Free everything
    for (i = 0; i < size; i++)
        free(arr[i]);
    free(arr);

    return 0;
}

结果:

0: apple
1: cat
2: sun
3: moon

如果您不关心元素的顺序,则不需要移动所有元素,只需移动最后一个元素代替已删除的元素:

    if (i < size) {
        arr[i] = arr[size - 1];

        size--;
        tmp = realloc(arr, sizeof(char *) * size);

        // Same as above...
    }

结果:

0: apple
1: cat
2: moon
3: sun
© www.soinside.com 2019 - 2024. All rights reserved.