如何处理在运行时确定类型的数组的声明和分配?

Posted

技术标签:

【中文标题】如何处理在运行时确定类型的数组的声明和分配?【英文标题】:How to handle the declaration and allocation of an array whose type is determined at runtime? 【发布时间】:2012-08-19 19:16:49 【问题描述】:

假设我在磁盘上有五个二进制文件。这五个文件以二进制格式对数字序列进行编码,但它们都有不同的类型。假设它们是 SHORT INT、INT、LONG、FLOAT 和 DOUBLE。我们将让文件也存储不同数量的数字。

现在假设我有一个程序在执行时询问用户

输入您要加载的文件名:

并且用户可以选择这五个文件之一。我希望程序将这些文件加载​​到一个数组中,以便执行进一步的计算。

我们可以假设存在两个函数:一个返回一个整数值,该值对文件的类型(即,SHORT INT、INT、LONG、FLOAT 或 DOUBLE)进行编码(称为“getfiletype”),另一个返回文件中数字的数量(例如,1000、9338、8131、0 等)(称为“getfilesize”)。条目的实际数量可能是数十亿个数字。如果可能的话,在程序中,我想为包含用户选择的任何文件的值的数组(比如“数组”)使用相同的名称。这样我就可以拥有像

这样的块
N=getfilesize("pickedfile.dat");
for(i=0 ; i<N ; i++ ) 
    doublearray[i]==2.0*(double)array[i]+7.12;

可以转换数组。在这里,我引入了一个名为“doublearray”的新数组来保存转换后的值。然后,这个双精度数组要么以 DOUBLE 格式写入文件,要么在写入其他格式之前进行转换。

我该怎么做这种事情?完全糊涂了。

【问题讨论】:

C 是一种静态类型的语言,所以你不能在运行时声明 type。类型必须在编译时指定。你可以拥有的是一个 void 指针(@ 987654322@) 可以指向任何数据类型。当然,在执行所需的类型转换时需要小心。 您不能在 C 中动态更改数组的基本类型,它不是为此而设计的。基本上,您必须为要处理的每种类型编写一个函数。你可以帮助自己编写一个产生这 10 个不同函数的宏,但如果你是 C 初学者,这不是你应该做的。顺便说一句,你的代码 sn-p 已经有一个严重的缺陷。请仔细阅读。 【参考方案1】:

您的程序可以创建一个静态(或全局)void* 数组,该数组将由对 getfiletype() 或 getfilesize() 的最新调用填充。然后,您必须适当地转换它(正如您在示例中专门为 double 所做的那样)。假设您已经解决了文件数据方面的加载问题。

虽然这种方法在使用方面并不是很干净(依赖静态或全局会限制您执行不同对话的选择 - 特别是目前的情况,您必须确保以顺序方式操作)。

更简洁的 API 可能是这样的:

enum TypeEnum  SHORT_INT, INT, LONG, FLOAT, DOUBLE ;
void* getfiledata(char *filename, unsigned int *size, TypeEnum *type);
#define GET_DATA_AND_CAST(filename, array, array_size) \
    do  \
        TypeEnum type; \
        void* arr = getfiledata(filename, array_size, &type); \
        switch(type)  \
            case SHORT_INT: \
                array = (short*)arr; break; \
            case INT: \
                array = (int*)arr; break; \
            case LONG: \
                array = (long*)arr; break; \
            case FLOAT: \
                array = (float*)arr; break; \
            case DOUBLE: \
                array = (double*)arr; break; \
            default: \
                // ASSERT \
         \
     while(0)

然后你可以像这样使用它:

void process_doubles(void *array) 
    double to_conv[];
    unsigned int size;
    GET_DATA_AND_CAST("pickedfile.dat", to_conv, &size);

    for(i=0; i<size; ++i ) 
        doublearray[i] = 2.0 * to_conv[i] + 7.12;
    

恕我直言,C++ 会让这变得更好(因为您可以使用模板),但由于这个问题仅用 C 标记,我只是在 C 中呈现选项。

【讨论】:

【参考方案2】:

您可以使用void * 指针来存储指向任何数据类型的指针。

int num_elements = getfilesize();
size_t element_size;
switch (getfiletype()) 
    case SHORT_INT: element_size = sizeof(short int); break;
    ...

void *array = malloc(num_elements * element_size);

...

void process_doubles(void *array) 
    for(i=0 ; i<getfilesize("pickedfile.dat") ; i++ ) 
    doublearray[i] = 2.0 * ((double *) array)[i] +7.12;

请注意,您需要在间接转换数组指针之前对其进行强制转换。

【讨论】:

以上是关于如何处理在运行时确定类型的数组的声明和分配?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理在 Angular CLI 中安装对等依赖项?

GraphQL:如何处理在自己的类型定义中引用类型?

如何处理在反编译时,原包验证包名问题

HSQLDB UNIQUE 约束和 SQL 数组类型

使用MVVM框架时,如何处理在页面动态渲染完之后需要发生的事件呢?

如何处理 C 中的堆栈数组分配失败?