-2

我目前在带有 C(非 C++)和 OpenGL 的 win7 64 位上使用 VS2008 Express。拥有这个我已经编码了一段时间的软件 3d 引擎,是时候从文件中加载对象了。最大的变化是从结构内的静态数组(完成并除尘)转移到结构内的动态数组(痛苦)。

结构如下:

// the structure for handling an object
struct ObjectHolder
{
    int iVertexCount;     //number of vertices of object being loaded 

    //float fVerticeStore[48];  //actual vertex data read from file
                                     //changing to dynamic
                                    //this works but is not scalable

    //my dynamic array test
    float *fpVerticeStore = NULL;   //should be dynamic

};

好的,那么我有一个在初始化引擎时调用的函数。

  1. 它实例化结构
  2. 打开保存对象数据的文件
  3. 然后将数据读入动态数组
  4. 沿途测试任意错误
void weLoad_file_objects_to_memory()
{

    int i = 0; 

    ifstream indata; // nuf said

    int num1, num2, num3; // variables to hold vertex data
    char tag[2];          // tag holds the abbreviation of the data type being loaded
                        //such as vc = vertexcount, v = vertex, l = line
                        //mildly similar to .obj format 

    indata.open("construct.dat"); // opens the file

    if(!indata) 
    { // file couldn't be opened
            cerr << "Error: file could not be opened" << endl;
    exit(1);

    }

    struct ObjectHolder weConstructObject;  //struct instantiated here

    indata >> tag;   //tag simply tests for type of data in file

    if ( tag == "vc") 
    {
        indata >> weConstructObject.iVertexCount;

        //set size of dynamic array ie: the Vertex Store 

        //first try using "new" does not work
        //weConstructObject.fpVerticeStore = new int[weConstructObject.iVertexCount]; 

        //second try using malloc does not work
        weConstructObject.fpVerticeStore = (float*) malloc(32 * sizeof(float));
    }
    else
    {
        MessageBox(NULL,"Vertex Count Error!","VERTEX COUNT ERROR",MB_OK|MB_ICONEXCLAMATION);
        //break;
    }


    //read in vertex data from file
    while ( !indata.eof() ) 
    { // keep reading until end-of-file
    indata >> tag >> num1 >> num2 >> num3;

    if (tag == "v") 
    {
        weConstructObject.fpVerticeStore[i++] = float(num1);
        weConstructObject.fpVerticeStore[i++] = float(num2);
        weConstructObject.fpVerticeStore[i++] = float(num3);
    }
    else
    {
        MessageBox(NULL,"Vertex Store Error!","STORE ERROR",MB_OK|MB_ICONEXCLAMATION);
        //break;
    }

}
   indata.close();
   //cout << "End-of-file reached.." << endl;
   //return 0;

} 

在关闭发动机时,以下内容适用

// Delete all dynamic arrays
delete [] weConstructObject.fpVerticeStore; // When done, free memory pointed to.
weConstructObject.fpVerticeStore = NULL; // Clear to prevent using invalid memory reference.

构造.dat 看起来像

vc 16
v -20 0 20
v -10 0 20
...

这个问题有很多版本,非常混乱。我喜欢保持我的代码简单。谁能弄清楚我为什么会出现编译错误?

only static const integral data members can be initialized within a class
4

4 回答 4

0

您可以在结构中声明一个指针并使用 malloc() 设置其初始大小,然后在从输入文件读取的代码部分中包含一个 if 语句,如果需要,它将 realloc() 。

初始内存分配

//When comparing a string to a pointer you MUST use strcmp()
if (strcmp(tag, "vc")==0) 
{
    //You should not need to typecast your pointer as float pointer unless it is
    //declared as something else i.e. char int
    weConstructObject.fpVerticeStore = (float*) malloc(32 * sizeof(float));

    //You should instead allocate your memory this way note that I allocate
    //size+1 the +1 being for the NULL terminating character. So the usable space of
    //in your array is size not size-1.
    int size = 32;
    weConstructObject.fpVerticeStore = malloc(sizeof(float)*size+1)
    if(weConstructObject.fpVerticeStore == NULL)
    {
      //Error
    }
}
else
{
    MessageBox(NULL,"Vertex Count Error!","VERTEXCOUNTERROR",MB_OK|MB_ICONEXCLAMATION);
    //break;
}
int size = 32;
weConstructObject.fpVerticeStore = malloc(sizeof(float)*size+1)

必要时重新分配内存

while(!indata.eof())
{
   indata >> tag >> num1 >> num2 >> num3; 
   if(i >= size) //i should represent your current index in the array
   {
     size *= 2;
     float *tmp = realloc(weConstructObject.fpVerticeStore, sizeof(float)*size+1)
     if (tmp == NULL)
     {
        //Error
     }
     else
     {
       weConstructObject.fpVerticeStore = tmp;
       //You should now have size*2 usable space in your array.
     }
   }
   //You don't have to use strcmp() here if you know where the character constant v
   //will be located in your array i.e if (tag[0] == 'v')
   if (strcmp(tag, "v")==0)
   {
     weConstructObject.fpVerticeStore[i++] = float(num1);
     weConstructObject.fpVerticeStore[i++] = float(num2);
     weConstructObject.fpVerticeStore[i++] = float(num3);
   }
   else
   {
     MessageBox(NULL,"Vertex Store Error!","STORE ERROR",MB_OK|MB_ICONEXCLAMATION);
     //break;
   }
}
于 2013-01-13T20:05:14.487 回答
0

当您在结构中只需要一个动态数组时,您可以选择使用“struct hack”(原始形式或 C99 形式)

struct ObjectHolder
{
    int iVertexCount;
    float fpVerticeStore[]; /* use `[1]` for C89/90 */
};


int iVertexCount;
...
struct ObjectHolder *p = malloc(offsetof(ObjectHolder, fpVerticeStore) + 
  iVertexCount * sizeof *p->fpVerticeStore);
p->iVertexCount = iVertexCount;
...

或独立的动态分配数组

struct ObjectHolder
{
    int iVertexCount;
    float *fpVerticeStore;
};


ObjectHolder holder;
...
holder.fpVerticeStore = 
  malloc(holder.iVertexCount * sizeof *holder.fpVerticeStore);

请注意,在第一种情况下ObjectHolder,必须动态分配整个嵌入数组,这意味着您不能ObjectHolder在知道确切的数组大小之前预先创建。ObjectHolder在第二种方法中,如何分配自身完全无关紧要。

此外,在第二种方法中,可能根本不需要动态分配,假设它符合您对数组生命周期的要求

struct ObjectHolder
{
    int iVertexCount;
    float *fpVerticeStore;
};


ObjectHolder holder;
...
float vertices[holder.iVertexCount];
holder.fpVerticeStore = vertices;

选择更适合您要求的方法。

于 2013-01-13T20:53:29.653 回答
0

您至少有一个问题,您的编译器正在抱怨:

// the structure for handling an object
struct ObjectHolder
{
    int iVertexCount;     //number of vertices of object being loaded 

    //float fVerticeStore[48];  //actual vertex data read from file
                                     //changing to dynamic
                                    //this works but is not scalable

    //my dynamic array test
    float *fpVerticeStore; // = NULL;   //should be dynamic
    //You cannot initialize inside the definition of the struct.  

};

struct ObjectHolder objHolder;
objHolder.fpVerticeStore = (float*) malloc(32 * sizeof(float)); //allocate memory

// do stuff

free(objHolder.fpVerticeStore); //Free memory

此外,在 C 中,您必须使用malloc动态分配内存并free再次释放内存。在 C++ 中,您将分别使用newdelete

另一个问题是:

if (tag == "v") 

你有一个char数组,所以如果你想检查一个元素的值是什么,你需要索引到数组并进行比较,如下所示:

if (tag[0] == 'v') { }

在 C++ 中你永远不会这样做:

 while ( !indata.eof() ) 
 { // keep reading until end-of-file
  indata >> tag >> num1 >> num2 >> num3;

相反,你最好这样做:

 while ( indata >> tag >> num1 >> num2 >> num3 ) {}
于 2013-01-13T19:48:55.197 回答
0

伙计们,非常感谢。我有它的工作。但是我决定使用 AndreyT 的第二个例子。原因是灵活性和独立性。我需要在代码中的另一个位置声明结构,因此需要(正如 AndreyT 所说)一个独立的动态分配数组。

我对 AndreyT 的代码做了一个修复。malloc 会生成错误,因此需要在其前面添加 (float*)。非常感谢 AndreyT 和其他用户的评论。

如果您需要这个有用的功能,这里是可编译的代码:享受吧!

Lee 在 Sourceforge 上的 WorldEngine 项目

#include <windows.h>    
//file handler
#include <iostream>
    using std::cerr;
    using std::cout;
    using std::endl;

#include <fstream>
    using std::ifstream;

#include <cstdlib> // for exit function
//end file handler


struct ObjectHolder
{
    int iVertexCount;
    float *fpVerticeStore;
};

ObjectHolder holder;

//float vertices[holder.iVertexCount];


int main(void)
{
    ifstream indata; // nuf said

float num1, num2, num3; // variables to hold vertex data
char tag[2];          // tag holds the abbreviation of the data type being loaded
                    //such as vc = vertexcount, v = vertex, l = line
                    //mildly similar to .obj format 

indata.open("construct.dat"); // opens the file
 if(!indata) 
{ // file couldn't be opened
        cerr << "Error: file could not be opened" << endl;
exit(1);

}
indata >> tag;   //tag simply tests for type of data in file

if (strcmp(tag, "c")==0) 
{
    indata >> holder.iVertexCount;

    //holder.fpVerticeStore = vertices;
    holder.fpVerticeStore = (float*)malloc(holder.iVertexCount * sizeof *holder.fpVerticeStore);
}
else
{
    MessageBox(NULL,LPCSTR("Vertex Count Error!"),LPCSTR("VERTEX COUNT ERROR"),MB_OK|MB_ICONEXCLAMATION);
    //break;
}

 printf("vertex count %d\n", holder.iVertexCount);
int j = 1;
//read in vertex data from file
while ( !indata.eof() ) 
{ // keep reading until end-of-file
    indata >> tag >> num1 >> num2 >> num3;
    int i = 0;
    if (strcmp(tag, "v")==0) 
    {
        printf("vertex %d", j++);

        holder.fpVerticeStore[i++] = num1;
        printf(" %f", holder.fpVerticeStore[i - 1]);

        holder.fpVerticeStore[i++] = num2;
        printf(" %f", holder.fpVerticeStore[i - 1]);

        holder.fpVerticeStore[i++] = num3;
        printf(" %f\n", holder.fpVerticeStore[i - 1]);
    }
    else
    {
        MessageBox(NULL,LPCSTR("Vertex Store Error!"),LPCSTR("STORE ERROR"),MB_OK|MB_ICONEXCLAMATION);
        //break;
    }

}
indata.close();

//return 0;
}
于 2013-01-14T09:31:36.797 回答