簡體   English   中英

如何用{}塊C ++解析文件

[英]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數組),然后將令牌與預期的下一個令牌(如果它是固定的令牌之一,如EntityNameAnimation{ )進行比較,然后將令牌的值分配給相應的部分結構。 如果需要一個整數作為下一個值,則可以使用結構的適當成員替換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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM