如何在C中声明和填充未知大小的全局整数数组

时间:2016-02-14 23:30:27

标签: c arrays integer global

我需要从文本文件中读取未知数量的整数(每行一个)并将它们存储在全局数组中,以便我可以在不同的线程上对它们进行排序。

我的想法是声明(全局)int numberOfValuesToSort;,然后通过快速传递文件并计算行数来设置它(我让这部分工作得很好)。

我还将全局声明int * unsortedValues;int * sortedValues;(我不确定这是否是正确的格式,或许我需要两颗星?)

然后,我希望在两个数组的每一个中分配适当数量的整数槽(numberOfValuesToSort),这样我就可以填充unsortedValues数组,然后将其排序为{{1 }}

我尝试了下面的方法,但在打印时得到了乱码,所以我知道我做错了什么:

sortedValues

修改

在一些打印之后,我注意到/* Allocate the appropriate amount of space in our arrays */ unsortedValues = malloc(numberOfValuesToSort * sizeof(int)); sortedValues = malloc(numberOfValuesToSort * sizeof(int)); for(int i = 0; i < numberOfValuesToSort; i++){ fscanf(myfile, "%d", &unsortedValues[i]); } for (int i = 0; i < numberOfValuesToSort; i++) { printf("Number is: %d\n\n", unsortedValues[i]); } 的大小是8,而(对于我正在使用的测试用例),unsortedValues只有6.包括以下代码似乎成功在将数组中的每个点设置为零时,我的输出现在总是= 0(而不是之前看到的乱码)。但是,大小的差异是一个红旗,以及我仍然看到所有零而不是输入文件中的数字的事实。

numberOfValuesToSort

这是输出:

printf("Size of unsortedValues = %lu\nnumberOfValuesToSort = %d\n",
    sizeof(unsortedValues), numberOfValuesToSort);

for(int i = 0; i < sizeof(unsortedValues); i++){
    unsortedValues[i] = 0;
    printf("unsortedValues[%d] = %d\n", i, unsortedValues[i]);
}

2 个答案:

答案 0 :(得分:1)

对于这种事情,使用实际的数据结构通常会更好,因为您需要将长度与数据一起存储在某处。此外,如果您在不同的线程上进行排序,则需要同步访问权限,如果您使用实际的数据结构,则可以在此处放置互斥锁。

以下是一个可动态调整大小的数组的示例:

main.c

#include <stdio.h>
#include <stdlib.h>
#include "darray.h"

#define BUFSIZE 1024

int main(void)
{
    darray arr = darray_create();

    FILE * fp = fopen("numbers.dat", "r");
    if ( !fp ) {
        perror("couldn't open data file");
        return EXIT_FAILURE;
    }

    while ( 1 ) {
        char buffer[BUFSIZE];
        int value;

        if ( !fgets(buffer, BUFSIZE, fp) ) {
            break;
        }

        if ( sscanf(buffer, "%d", &value) != 1 ) {
            break;
        }

        darray_append(arr, value);
    }

    fclose(fp);

    const size_t len = darray_length(arr);
    printf("Length of array: %zu\n", len); 

    for ( size_t i = 0; i < len; ++i ) {
        printf("%3zu: %d\n", i, darray_get(arr, i));
    }

    darray_destroy(arr);

    return 0;
}

darray.h

#ifndef DARRAY_H
#define DARRAY_H

#include <stddef.h>

typedef struct darray * darray;

darray darray_create(void);
void darray_destroy(darray arr);
size_t darray_length(darray arr);
void darray_append(darray arr, const int data);
void darray_set(darray arr, const size_t index, const int data);
int darray_get(darray arr, const size_t index);
void darray_shrink(darray arr);

#endif      /*  DARRAY_H  */

darray.c

#include <stdio.h>
#include <stdlib.h>
#include "darray.h"

#define INIT_ELEMS 16

struct darray {
    int * data;
    size_t length;
    size_t capacity;
};

darray darray_create(void)
{
    struct darray * new_arr = malloc(sizeof *new_arr);
    if ( !new_arr ) {
        perror("couldn't allocate memory for darray");
        exit(EXIT_FAILURE);
    }

    new_arr->data = malloc(INIT_ELEMS * sizeof *new_arr->data);
    if ( !new_arr->data ) {
        perror("couldn't allocate memory for darray elements");
        exit(EXIT_FAILURE);
    }

    new_arr->length = 0;
    new_arr->capacity = INIT_ELEMS;
    return new_arr;
}

void darray_destroy(darray arr)
{
    free(arr->data);
    free(arr);
}

size_t darray_length(darray arr)
{
    return arr->length;
}

static void darray_reallocate(darray arr, const size_t new_size)
{
    arr->capacity = new_size;
    if ( arr->length > arr->capacity ) {
        arr->length = arr->capacity;
    }
    int * new_data = realloc(arr->data, arr->capacity);
    if ( !new_data ) {
        perror("couldn't reallocate memory for darray data");
        exit(EXIT_FAILURE);
    }
    arr->data = new_data;
}

void darray_append(darray arr, const int data)
{
    if ( arr->length == arr->capacity ) {
        darray_reallocate(arr, arr->capacity * 2);
    }

    arr->data[arr->length++] = data;
}

void darray_set(darray arr, const size_t index, const int data)
{
    if ( index >= arr->length ) {
        fprintf(stderr, "Couldn't set - index of %zu exceeds length of %zu\n",
                index, arr->length);
        exit(EXIT_FAILURE);
    }
    arr->data[index] = data;
}

int darray_get(darray arr, const size_t index)
{
    if ( index >= arr->length ) {
        fprintf(stderr, "Couldn't get - index of %zu exceeds length of %zu\n",
                index, arr->length);
        exit(EXIT_FAILURE);
    }

    return arr->data[index];
}

void darray_shrink(darray arr)
{
    if ( arr->length != arr->capacity ) {
        darray_reallocate(arr, arr->length);
    }
}

带输出:

paul@horus:~/Documents/src/sandbox/nsort$ cat numbers.dat
1432
9382
4211
482
55819
11
777
2881
33
6224
paul@horus:~/Documents/src/sandbox/nsort$ ./nsort
Length of array: 10
  0: 1432
  1: 9382
  2: 4211
  3: 482
  4: 55819
  5: 11
  6: 777
  7: 2881
  8: 33
  9: 6224
paul@horus:~/Documents/src/sandbox/nsort$ 

请注意,您只需以这种方式通过输入文件进行一次传递。

答案 1 :(得分:0)

我想出了我的问题。通过初始传递文件来计算行数,我导致连续调用fscanf从文件末尾开始并返回-1

我需要做的是:

  • 打开文件
  • 扫描它,计算行数
  • 在我的数组中分配适当数量的空间
  • 回到文件的开头
  • 再次扫描文件,这次将整数读入我的数组
  • 关闭文件

这是我的工作代码:

    /* Determine how many integers (one per line) the file holds */
/* From http://stackoverflow.com/questions/1910724/retrieving-total-line-numbers-in-a-file */
FILE * myfile = fopen(filename, "r");
int ch = 0;
do{
    ch = fgetc(myfile);
    if(ch == '\n'){ numberOfValuesToSort++; }
} while(ch != EOF);
/* Seek to the beginning of the file */
rewind(myfile);

/* Allocate the appropriate amount of space in our arrays */
unsortedValues = malloc(numberOfValuesToSort * sizeof(int));
sortedValues   = malloc(numberOfValuesToSort * sizeof(int));

/* Read through the file again, this time grabbing integers from it as we scan */
int i = 0;
while (!feof (myfile)) {
    /* Read an integer and insert it in the array unsortedValues */
    fscanf (myfile, "%d", &unsortedValues[i]);
    i++;
}
/* Close the file */
fclose(myfile);

/* Ensure we have filled the array with the correct values */
for(int i = 0; i < numberOfValuesToSort; i++){
    printf("unsortedValues[%d] = %d\n", i, unsortedValues[i]);
}