xml解析错误处理

发布于 2024-09-08 02:36:36 字数 1596 浏览 4 评论 0原文

我使用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;

我并没有对此气喘吁吁,但如果有人能想出一种更干净的方法来实现这一点,我将不胜感激。

PS 例外不是一个选项。

编辑:

这样的事情会更好吗?

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

这消除了箭头代码,但箭头代码有点将所有错误记录放在一处。

I'm using tinyxml to parse xml files, and I've found that error handling here lends itself to arrow code. Our error handling is simply reporting a message to a file.

Here is an example:

  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;

I'm not huffing and puffing over it, but if anyone can think of a cleaner way to accomplish this it would be appreciated.

P.S. Exceptions not an option.

Edit:

Would something like this be preferable?

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

This eliminates the arrow code, but the arrow code kind of puts all of the error logging on one place.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ヤ经典坏疍 2024-09-15 02:36:36

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

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

Using return values as error codes just leads to such code, it can't be improved much. A slightly cleaner way would use goto to group all error handling into a single block and to decrease the nesting of blocks.

This does however not solve the actual problem, which is using return values as error codes. In C, there is no alternative, but in C++ exceptions are available and should be used. If they are not an option, you're are stuck with what you have.

怪我入戏太深 2024-09-15 02:36:36

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

然而,我不认为这可以得到多大改善;事情就是这样。 这就是生活。这是代码...

You could create a macro for that, which encapsulates the if (!var) { .. return false; } and error reporting.

However, I do not see how this can be improved all that much; its just the way it is. C'est la vie. C'est le code...

つ低調成傷 2024-09-15 02:36:36

我并没有为此气喘吁吁,
但如果有人能想到一个清洁工
实现这一目标的方法是
赞赏。

我已经将嵌套的 if 替换为错误时的 return 语句(这使得代码“向下流动”而不是“箭头形状”。我还用 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;

I'm not huffing and puffing over it,
but if anyone can think of a cleaner
way to accomplish this it would be
appreciated.

I have replaced the nested ifs with return statements on error (this makes the code "flow down" instead of going "arrow shaped". I have also replaced your do loopps with for loops (so I could understand it better).

Is this what you wanted?

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;
稍尽春風 2024-09-15 02:36:36

我知道有点晚了,但我知道 QueryIntAttribute 返回一个值,可用于错误处理,以防您也希望将其用于属性。

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

I know it is a little late, but I know that QueryIntAttribute returns a value which can be used for error handling in case you want this for your attributes too.

if (instance->QueryIntAttribute("x",&x)!=TIXML_SUCCESS)
    cout << "No x value found";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文