【问题标题】:Error handling for xml parsingxml解析的错误处理
【发布时间】:2011-03-11 11:45:08
【问题描述】:

我正在使用 tinyxml 来解析 xml 文件,我发现这里的错误处理适用于箭头代码。我们的错误处理只是向文件报告一条消息。

这是一个例子:

  const TiXmlElement *objectType = dataRoot->FirstChildElement( "game_object" );
  if ( objectType ) {
    do {
      const char *path = objectType->Attribute( "path" );
      if ( path ) {
        const TiXmlElement *instance = objectType->FirstChildElement( "instance" ); 
        if ( instance ) {
          do {
            int x, y = 0; 
            instance->QueryIntAttribute( "x", &x );
            instance->QueryIntAttribute( "y", &y );
            if ( x >= 0 && y >= 0 ) {
              AddGameObject( new GameObject( path, x, y ));
            } else {
              LogErr( "Tile location negative for GameObject in state file." );
              return false;
            }
          } while ( instance = instance->NextSiblingElement( "instance" ));
        } else {
          LogErr( "No instances specified for GameObject in state file." );
          return false;
        }
      } else {
        LogErr( "No path specified for GameObject in state file." );
        return false;
      }
    } while ( objectType = objectType->NextSiblingElement( "game_object" ));
  } else {
    LogErr( "No game_object specified in <game_objects>. Thus, not necessary." );
    return false;
  }
  return true;

我不是对此大发雷霆,但如果有人能想出一种更清洁的方法来实现这一点,我将不胜感激。

附:例外不是一种选择。

编辑:

这样的东西会更好吗?

if ( !path ) {
  // Handle error, return false
}
// Continue

这消除了箭头代码,但箭头代码类型将所有错误日志记录在一个地方。

【问题讨论】:

    标签: c++ refactoring error-handling xml-parsing


    【解决方案1】:

    我知道这有点晚了,但我知道 QueryIntAttribute 返回一个值,如果你也想为你的属性使用这个值,该值可用于错误处理。

    if (instance->QueryIntAttribute("x",&x)!=TIXML_SUCCESS)
        cout << "No x value found";
    

    【讨论】:

      【解决方案2】:

      我不是为此而大发雷霆, 但如果有人能想到清洁工 实现这一目标的方法是 赞赏。

      我已经用错误的返回语句替换了嵌套的 ifs(这使得代码“向下流动”而不是“箭头形”。我还用 for 循环替换了你的 do 循环(这样我可以更好地理解它)。

      这是你想要的吗?

      const TiXmlElement *objectType = dataRoot->FirstChildElement( "game_object" );
      if ( !objectType ) {
          LogErr( "No game_object specified in <game_objects>. Thus, not necessary." );
          return false;
      }
      
      for(; objectType != 0; objectType = objectType->NextSiblingElement( "game_object" )) {
          const char *path = objectType->Attribute( "path" );
          if ( !path ) {
              LogErr( "No path specified for GameObject in state file." );
              return false;
          }
      
          const TiXmlElement *instance = objectType->FirstChildElement( "instance" ); 
          if ( !instance ) {
              LogErr( "No instances specified for GameObject in state file." );
              return false;
          }
      
          for(; instance != 0; instance = instance->NextSiblingElement( "instance" )) {
              int x, y = 0; 
              instance->QueryIntAttribute( "x", &x );
              instance->QueryIntAttribute( "y", &y );
              if ( x >= 0 && y >= 0 ) {
                  AddGameObject( new GameObject( path, x, y ));
              } else {
                  LogErr( "Tile location negative for GameObject in state file." );
                  return false;
              }
          }
      }
      return true;
      

      【讨论】:

        【解决方案3】:

        使用返回值作为错误代码只会导致这样的代码,它无法改进。更简洁的方法是使用goto 将所有错误处理分组到一个块中并减少块的嵌套。

        但这并不能解决实际问题,即使用返回值作为错误代码。在 C 中,没有其他选择,但在 C++ 中,异常是可用的并且应该被使用。如果它们不是一个选项,那么你就会被你所拥有的东西所困。

        【讨论】:

          【解决方案4】:

          您可以为此创建一个宏,它封装了if (!var) { .. return false; } 和错误报告。

          但是,我看不出有什么可以改进的地方。它就是这样。 C'est la vie。 C'est le code...

          【讨论】:

            猜你喜欢
            • 2016-02-07
            • 1970-01-01
            • 2013-11-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-11
            • 1970-01-01
            相关资源
            最近更新 更多