如何在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);
}

然后把 "a "中除了 "dog "以外的所有元素复制到 "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.