[英]How do I parse a file with {} block C++
我有這樣的文件
EntityName Jaws
{
Animation WALK
{
NumberOfFrames 9
DirectionOfSprite L
DirectionGenerate LR
FPS 9
}
Animation IDLE
{
NumberOfFrames 6
DirectionOfSprite L
DirectionGenerate LR
FPS 9
}
.......
.......
}
如何在此結構中解析此文件
struct AnimationData
{
string animationName;
int noOfFrames;
eAnimationDataDirection direction;
int FPS;
};
struct EntityAnimationData
{
string entityName;
vector<AnimationData> animationData;
string getSpriteResourceName(AnimationData animationData, int frameNumber);
};
我想將這些數據存儲到結構中。 我該如何獲得一個干凈的解決方案? 我已經閱讀了文件的基本閱讀材料。
這就是我嘗試過的
EntityAnimationData parseAnimationData(const char* filename)
{
EntityAnimationData data;
ifstream file;
file.open(filename);
char output[128];
string op;
if (file.is_open())
{
while (!file.eof())
{
file >> output;
if(strcmp(parameter,AD_ENTITY_NAME.c_str())==0)
{
file >> output;
data.entityName = output;
cout<<data.entityName<<endl;
do
{
file >> output;
cout<<output<<endl;
}while(strcmp(output,"}")!=0);
}
}
}
file.close();
return data;
}
如果這是你正在制作的游戲,我會考慮更改輸入文件格式的詳細信息。 如果使用現有文件格式,則可以使用庫來大大簡化解析。
例如,這些相同的數據可以很容易地存儲為XML,這允許您使用XML解析器(例如TinyXML-2 )來讀取數據,並且可能使文件的創建更簡單。 它還可以更簡單地添加更強大的格式問題處理,例如額外的空格等。
無法創建語法並使用lex / yacc等工具為您創建解析器(BOOST庫也有解析器),您需要讀取每個令牌(就像您現在正在做的那樣: file >> token
- 我建議使用std::string
作為令牌,而不是char
數組),然后將令牌與預期的下一個令牌(如果它是固定的令牌之一,如EntityName , Animation , { )進行比較,然后將令牌的值分配給相應的部分結構。 如果需要一個整數作為下一個值,則可以使用結構的適當成員替換token
。
注意 :如果采用這種方法,請確保在每次提取操作時檢查錯誤,而不是假設文件的格式始終正確
如果你有一個固定的文件格式,你不希望改變,那么你可以做readline,然后是if / else。 否則為這種格式編寫解析器非常簡單,並提供更大的靈活性。 下面是使用AX解析器生成器的示例。
一些假設:您沒有指定名稱是什么,我在此示例中使用標識符規則( axe::r_ident
),您可以將其更改為適合您需要的名稱。 我還假設你不關心空格,制表符,行尾,所以你可以使用axe::r_skip
規則來跳過它們。 我假設你使用的數字是十進制的。
template<class I>
EntityAnimationData parse(I begin, I end)
{
EntityAnimationData data;
AnimationData ad; // temporary
auto direction = axe::r_lit("LR") | "RL" | 'L' | 'R';
auto animation_data = "Animation" & axe::r_ident() >> ad.animationName
& '{'
& "NumberOfFrames" & axe::r_decimal(ad.noOfFrames)
& "DirectionOfSprite" & direction >> axe::e_ref([&](I i1, I i2)
{
std::string dir(i1, i2); // this will be "LR" or "RL" or 'L' or 'R'
// ad.direction = ...
})
& "DirectionGenerate" & direction >> axe::e_ref([&](I i1, I i2)
{
std::string dir(i1, i2); // this will be "LR" or "RL" or 'L' or 'R'
// ad.direction = ...
})
& "FPS" & axe::r_decimal(ad.FPS)
& '}';
auto entity_data = axe::r_lit("EntityName") & axe::r_ident() >> data.entityName
& '{'
& *(animation_data >> axe::e_ref([&](...) { data.animationData.push_back(ad); }))
& '}'
& axe::r_end();
// create a skip rule
auto data_skip_spaces = axe::r_skip(entity_data, " \t\n");
auto match = data_skip_spaces(begin, end);
if(!match.matched)
throw "format error";
return data;
}
void foo()
{
std::string text = "EntityName Jaws\n{\n Animation WALK\n {\n NumberOfFrames 9 ...";
EntityAnimationData data = parse(text.begin(), text.end());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.