我目前在win7 64bit上使用VS2008 Express,使用C(非C ++)和OpenGL。有这个软件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
};
好的,然后我在初始化引擎时调用了一个函数。
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.
construct.dat看起来像
vc 16
v -20 0 20
v -10 0 20
...
这个问题有很多版本,很令人困惑。我喜欢保持我的代码简单。任何人都可以弄清楚为什么我会遇到编译错误?
only static const integral data members can be initialized within a class
答案 0 :(得分: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 ++中,您分别使用new
和delete
。
另一个问题是:
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 ) {}
答案 1 :(得分: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;
}
}
答案 2 :(得分: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;
选择更符合您要求的方法。
答案 3 :(得分:0)
Chaps,非常感谢。我有它的工作。但是我决定使用AndreyT的第二个例子。原因是灵活性和独立性。我需要在代码中的另一个位置进行结构声明,因此需要(如AndreyT所称)一个独立的动态分配数组。
我对AndreyT的代码做了一个修复。 malloc生成错误,因此需要一个(float *)在它之前。非常感谢AndreyT和其他用户评论。
如果你需要这个有用的功能,这是可编辑的代码:享受!
李在Sourceforge的WorldEngin项目
#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;
}