如何调整整数数组?

时间:2014-11-02 03:06:58

标签: c malloc realloc

我一直在寻找类似性质的其他答案,但仍然遇到问题。

我是C的初学者,需要一些建议。

代码的相关部分:

int readNumbers(int **array, char* fname, int hexFlag) {

    int numberRead = 0;
    FILE* fp;
    int counter = 0;
    char arr[100];
    char* ptr;

    array = malloc(0 * sizeof(*array)); //Problematic area. Should I initially give it space?



    fp = fopen(fname, "r");  

    if (fp == NULL) {
            printf("Error opening file\n");
            return -1;
    }

    while (fgets(arr, sizeof(arr), fp)) {
            ptr = strtok(arr, " \n");
            while(ptr) {
               if (hexFlag == 0) { 
                        array = realloc(array, (counter + 1) * sizeof(int*)); 
                        array[counter++] = strtol(ptr , NULL , 10); //Seg Faulting
               } else {
                        array = realloc(array, (counter + 1) * sizeof(int*));
                        array[counter++] = strtol(ptr, NULL, 16);
               }
               ++numberRead;
               ptr = strtok(NULL , " \n");
    }

}

我调试了这个,似乎数组永远不会分配给它的内存。此外,程序在我尝试通过array[counter++];

访问数组后立即出现故障

我还发现每次增量后重新分配是不好的做法,但我不知道还能做什么。

2 个答案:

答案 0 :(得分:1)

经验法则是分配一个小的初始分配,并在需要更多空间时将分配的大小加倍。您必须跟踪两种尺寸 - 分配的尺寸和使用的尺寸。您可以使用realloc()完成所有操作,但首先使用malloc()然后realloc()可能更为常规。

size_t n_alloc = 1;
size_t n_used = 0;
int *data = malloc(n_alloc * sizeof(*arr));

if (arr == 0)
    …report out of memory and return…
int base = (hexFlag == 0) ? 10 : 16;

while (fgets(arr, sizeof(arr), fp))
{
    ptr = strtok(arr, " \n");
    while (ptr)
    {
        if (n_used == n_alloc)
        {
            size_t new_size = n_alloc * 2;
            int *new_data = realloc(data, new_size);
            if (new_data == 0)
            {
                free(data);
                …report error and return…
            }
            data = new_data
            n_alloc = new_size;
        }
        data[n_used++] = strtol(ptr, NULL, base);
        ptr = strtok(NULL, " \n");
    }
}

/* Optionally resize array */
*array = realloc(data, n_used * sizeof(*data));
/* Or, instead of realloc(), just write: *array = data; */
return n_used;

或者,初始化可以是:

size_t n_alloc = 0;
size_t n_used = 0;
int *data = 0;

这也可行;它甚至减少了需要错误报告的地方数量。

请注意,在realloc()失败的情况下,代码会小心避免内存泄漏。写这是错误的:

ptr = realloc(ptr, size);

如果realloc()失败,ptr被指定为NULL,这意味着您无法释放在调用realloc()之前分配的内存,这是一个典型的内存泄漏。

另请注意,此代码正确处理arrayint **}和dataint *)。问题中的原始代码是将array视为int *,而不是int **

答案 1 :(得分:1)

每次循环都是realloc的不良做法。根据需要在更大的区块内成长会更好。

此外,您正在错误地分配数组。 array是一个指向整数数组的指针,你需要间接通过它来设置调用者的指针。

*array = malloc(size * sizeof(**array));

所以你的功能应该是这样的:

int readNumbers(int **array, char* fname, int hexFlag) {

    int numberRead = 0;
    FILE* fp;
    int counter = 0;
    char arr[100];
    char* ptr;
    size_t curSize = 16;
    int radix = hexFlag ? 16 : 10;

    *array = malloc(curSize * sizeof(**array));

    fp = fopen(fname, "r");  

    if (fp == NULL) {
        printf("Error opening file\n");
        return -1;
    }

    while (fgets(arr, sizeof(arr), fp)) {
        ptr = strtok(arr, " \n");
        while(ptr) {
            if (counter >= curSize) {
                curSize += 16;
                *array = realloc(*array, curSize * sizeof(**array));
            }
            (*array)[counter++] = strtol(ptr , NULL , radix);
            ++numberRead;
            ptr = strtok(NULL , " \n");
        }

    }
}