将数组的大小扩展到越来越多的变量

时间:2018-01-28 01:55:48

标签: c arrays multidimensional-array realloc

我已经阅读了有关在C中动态扩展数组的内容以及许多答案,但我无法找到问题的根源。我尝试使用空格作为分隔符进行标记,并将每个字符串存储在一个数组中,因此"this is string"变为{ "this", "is", "string" }

我能够使用预定义的数组大小来执行此操作,但是当传入的语句超过声明时,无法扩展它。以下是代码:

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

#define DEFAULT_SIZE 3 /* default size of an array of words */

// array object
typedef struct {
    char pointer[DEFAULT_SIZE][256];
    int used;
    int size;
} Array;

void createArray(Array *array, int start_size) {
    array->used = 0;
    array->size = start_size;
}

void append(Array *array, char* elem) {
    if (array->used >= array->size) { // if every slot is used, then we expand
        array->size += 2; // expand by 2 slots

        Array *array = malloc(sizeof(Array));
        array = realloc(array, sizeof(array) + 2 * 256);
    }

    strcpy(array->pointer[array->used] , elem); // insert new element
    array->used++; // <-- wrong value here. increment info about used slots
}

char * args_str; // passed string
Array args_list; // expandable array holding words

void parse(char* command) {
    createArray(&args_list, DEFAULT_SIZE);
    args_str = strtok(command, " ");

    while (args_str != NULL) {
        append(&args_list, args_str);
        args_str = strtok(NULL, " ");
    }

return ;
}

我注意到array->used的值正确递增,直到数组扩展为止。如果有超过3个项目,则类似于1,2,3,66123(或其他随机值)。我怀疑这是错误的realloc,但我

2 个答案:

答案 0 :(得分:2)

您遇到的一个问题是您对动态分配的内存可以扩展(或使用)的基本理解。您的typedeffed结构Array固定大小。如果您为Array *array分配,则之后realloc array不能sizeof *array。它始终是Array。为它分配更多的内存,没有任何好处,因为它不包含指向任何额外内存的指针,并且会破坏该类型的指针算术。

你唯一能做的就是分配DEFAULT_SIZE的任何数组。但这会相当麻烦,因为每个元素只能存储最多pointer个令牌。

如果我理解你要完成什么,而不是让你的结构包含一个固定大小的2D数组pointer,你需要char[256]实际上是一个指向一个指针-array #define DEFAULT_SIZE 3 /* default size of an array of words */ #define TOKEN_SIZE 256 typedef struct { char (*pointer)[TOKEN_SIZE]; int used; int size; } arr; 。例如,您想要:

camelCase

注意: C避免使用PascalCaseArray变量名称支持所有小写,同时保留用于宏和常量的大写名称。)

现在,您确实可以在arr(标准情况下为arr)中调整大小。您可以分配arr->pointer的实例,然后在realloc

时分配arr->pointer(以及arr->used >= arr->size realloc

重新修改您的示例,为每个内存分配添加正确的验证,并使用realloc方案,每个方案arr->pointer 2 * arr->sizearr->used >= arr->size时间#include <stdio.h> #include <stdlib.h> #include <string.h> #define DEFAULT_SIZE 3 /* default size of an array of words */ #define TOKEN_SIZE 256 typedef struct { char (*pointer)[TOKEN_SIZE]; int used; int size; } arr; arr *createArray (int start_size) { arr *array = malloc (sizeof *array); if (!array) { perror ("malloc - array"); exit (EXIT_FAILURE); } array->used = 0; array->size = start_size; array->pointer = malloc (start_size * sizeof *array->pointer); if (!array->pointer) { perror ("malloc - array->pointer"); exit (EXIT_FAILURE); } return array; } void append (arr *array, char *elem) { if (array->used >= array->size) { void *tmp = realloc (array->pointer, array->size * 2 * sizeof *array->pointer); if (!tmp) { perror ("realloc - array->pointer"); return; /* you should change function type provide success/failure */ } array->pointer = tmp; array->size *= 2; /* update size */ } if (strlen (elem) + 1 < sizeof *array->pointer) { strcpy (array->pointer[array->used], elem); // insert new element array->used++; // <-- wrong value here. increment info about used slots } else fprintf (stderr, "error: token too long.\n"); } arr *parse (char* command) { char *args_str; arr *args_list = createArray (DEFAULT_SIZE); args_str = strtok (command, " "); while (args_str != NULL) { append (args_list, args_str); args_str = strtok (NULL, " "); } return args_list; } /* simple print function */ void prnarr (arr *array) { int i; for (i = 0; i < array->used; i++) printf ("array[%2d] : %s\n", i, array->pointer[i]); } /* simple function to free allocated memory */ void freearr (arr *array) { free (array->pointer); free (array); } int main (void) { char str[] = "my dog has fleas my cat has none lucky cat"; arr *args = parse (str); prnarr (args); freearr (args); return 0; } ,您可以执行以下操作:

$ ./bin/arr_struct_arr_of_ptrs
array[ 0] : my
array[ 1] : dog
array[ 2] : has
array[ 3] : fleas
array[ 4] : my
array[ 5] : cat
array[ 6] : has
array[ 7] : none
array[ 8] : lucky
array[ 9] : cat

示例使用/输出

valgrind

内存使用/错误检查

在你编写的动态分配内存的任何代码中,你有2个职责关于任何分配的内存块:(1)总是保留一个指向起始地址的指针内存块,(2)当不再需要时,它可以释放

必须使用内存错误检查程序,以确保您不会尝试访问内存或写入超出/超出已分配块的范围,尝试读取或基于未初始化值的条件跳转,最后,确认您释放了所有已分配的内存。

对于Linux $ valgrind ./bin/arr_struct_arr_of_ptrs ==9128== Memcheck, a memory error detector ==9128== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==9128== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==9128== Command: ./bin/arr_struct_arr_of_ptrs ==9128== array[ 0] : my array[ 1] : dog array[ 2] : has array[ 3] : fleas array[ 4] : my array[ 5] : cat array[ 6] : has array[ 7] : none array[ 8] : lucky array[ 9] : cat ==9128== ==9128== HEAP SUMMARY: ==9128== in use at exit: 0 bytes in 0 blocks ==9128== total heap usage: 4 allocs, 4 frees, 5,392 bytes allocated ==9128== ==9128== All heap blocks were freed -- no leaks are possible ==9128== ==9128== For counts of detected and suppressed errors, rerun with: -v ==9128== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 是正常的选择。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。

double max = decMax[0];
    for (int counter = 1; counter < decMax.length; counter++){
        if(max<decMax[i]){
            max=decMax[i]; //swapping
            decMax[i]=decMax[0];
        }
    }
    System.out.println("The max value is "+ max);

始终确认已释放已分配的所有内存并且没有内存错误。

仔细看看,如果您有其他问题,请告诉我。

答案 1 :(得分:1)

您使用realloc错误。

Array *array = malloc(sizeof(Array));
array = realloc(array, sizeof(array) + 2 * 256);

realloc用于调整(增大或缩小)动态分配的内存量。它使 在下一步中首先分配然后重新分配的意义不大。为什么不这样做 你首先分配了足够的内存吗?

这是你应该重新分配更多内存的方法:

Array *append(Array *array, char* elem) {
    size_t size;
    if(array == NULL)
        size = 2;
    else if (array->used >= array->size)
        size = array->size + 2;

    Array *tmp = realloc(array, size * sizeof *tmp);
    if(tmp == NULL)
        return NULL;  // telling the caller that something went wrong

    array = tmp;
    array->size = size;


    // I don't understand what you are trying to do here
    // strcpy(array->pointer[array->used] , elem); // insert new element
    // array->used++; // <-- wrong value here. increment info about used slots

    return array;
}

我不知道你在realloc获得256的位置。现在致电append

Array *tmp = append(array, element);
if(tmp == NULL)
{
    // something went wrong
    // do error handling,
    // do NOT continue
}

array = tmp;
...

说实话,我真的不明白你在做什么 Array结构。 pointer是一个无法动态调整大小的数组, 因为它的大小是固定的。相反,您正在创建越来越多Array 已经有二维数组的对象。我不明白这个原因 为此。

无论如何,这就是我要用的:

typedef struct {
    char **words;
    size_t size;
    size_t used;
} Array;

Array *createArray(size_t size) {
    Array *array = malloc(sizeof *array);
    if(array == NULL)
        return NULL;

    array->used = 0;
    array->size = size;
    array->words = calloc(size, sizeof *array->words);

    if(array->words == NULL)
    {
        free(array);
        return NULL;
    }

    return array;
}

// it can make grow and shrink the array
int resize_array(Array *array, size_t newsize)
{
    if(array == NULL)
        return 0;

    if(array->size == newsize)
        return 1;

    char **tmp = realloc(array->words, newsize * sizeof *tmp);
    if(tmp == NULL)
        return 0;

    array->words = tmp;

    if(array->size < newsize)
    {
        // setting new fields to 0
        memset(array->words + array->size, 0, newsize - array->size); 
    } else {
        if(array->used > newsize)
            array->used = newsize;
    }

    array->size = newsize;
    return 1;
}

int append(Array *array, char* elem) {
    if(array == NULL || elem == NULL)
        return 0;

    if(array->used >= array->size)
    {
        // adding 2 more spaces
        if(!resize_array(array, array->size + 2))
            return 0;
    }

    array->words[array->used++] = strdup(elem);

    return 1;
}

void free_array(Array *array)
{
    if(array == NULL)
        return;

    for(int i = 0; i < array->size; ++i)
        free(array->words[i]);
    free(array->words);
    free(array);
}

别忘了释放记忆,请不要使用全局变量,这是一种不好的做法。你必须使用 全局变量只有在它们真正必要时才会出现。