-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.

construct.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

構造体内に動的配列が1つだけ必要な場合は、「構造体ハック」(元の形式または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事前に作成することはできません。ObjectHolder2番目の方法では、ObjectHolderそれ自体がどのように割り当てられるかはまったく関係ありません。

また、2番目の方法では、アレイのライフタイムに関する要件に適合していると仮定すると、動的な割り当てはまったく必要ない場合があります。

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


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

要件に適した方法を選択してください。

于 2013-01-13T20:53:29.653 に答える
0

コンパイラが不平を言っている問題が少なくとも 1 つあります。

// 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++ では、それぞれ and を使用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

構造体でポインターを宣言し、malloc() を使用してその初期サイズを設定し、必要に応じて realloc() を実行する、入力ファイルから読み取るコードの部分に if ステートメントを含めることができます。

初期メモリ割り当て

//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

チャップス、どうもありがとう。私はそれが働いています。ただし、AndreyT の 2 番目の例を使用することにしました。その理由は、柔軟性と独立性です。コード内の別の場所で構造体宣言を行う必要があるため、(AndreyT が呼び出すように) 独立した動的に割り当てられた配列が必要です。

AndreyT のコードを 1 つ修正しました。malloc はエラーを生成するため、その前に (float*) が必要です。AndreyT と他のユーザーのコメントに感謝します。

この便利な関数が必要な場合のコンパイル可能なコードは次のとおりです。

Sourceforge の WorldEngin プロジェクトでの Lee

#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 に答える