2014-11-02 35 views
0

我一直在寻找类似性质的其他答案,但仍然遇到问题。如何调整整数数组?

我是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++]访问数组后,程序段出错。

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

+0

你好,我在几年前停止了C,但此行:阵列=的malloc(0 *的sizeof(*阵列));将始终分配PointerSize字节。你的数组实际上是指向指针,所以*数组只是一个指针。编辑,btw:0 * XX = 0,所以你没有分配任何内存 – Jurion 2014-11-02 03:11:47

+0

阅读这个问题http://stackoverflow.com/questions/2937409/resizing-an-array-with-c! – Blackhat002 2014-11-02 03:22:34

+0

@ Blackhat002嗨,我已经非常广泛地看到了这个问题。尽管我可能错过了一个重要的细节。我尝试了各种方法,但它们要么有无效的指针,要么有分段错误。 – Ansdai 2014-11-02 03:25:12

回答

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"); 
     } 

    } 
} 
+0

你好,谢谢你和Jonathan,我现在对此理解得更清楚了。然而,这是上面实现的一个问题,当输入到达文件结尾时,会出现分段错误一些原因 – Ansdai 2014-11-02 04:42:48

+0

我不知道为什么,当它到达文件末尾时,'fgets()'应该返回NULL并且'while'循环结束,我想你需要在调试器中运行它以查看在那里它是如何到达导致段错误的线路。 – Barmar 2014-11-02 04:52:42

+0

我明白了。这是因为我没有在malloc中使用curSize,而是意外地把0赋值了。但是我不明白为什么会导致fgets对错误进行分段。 – Ansdai 2014-11-02 05:14:05

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(),这是一个典型的内存泄漏之前分配的内存。

还要注意的是这个代码对待array(一个int **)和data(一个int *)正确。问题中的原始代码将array视为int *,而不是int **

+0

此代码:data [n_used ++]将不会正确地跳到数据指向的内存中的下一个条目,除非它发生int和long int的长度是相同的,这可能是真的,但是这是一个糟糕的假设,将int *数据更改为long int *数据要好得多 – user3629249 2014-11-02 11:34:24

+0

@ user3629249:你能解释为什么'long'与代码相关在这个问题中没有使用'long'吗? – 2014-11-02 16:02:11