Обработка ошибок для разбора XML - PullRequest
1 голос
/ 03 июля 2010

Я использую 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;

Я не буду пыхтеть и пыхтеть над этим, но если кто-нибудь сможет придумать более чистый способ достижения этого, это будет оценено.

P.S. Исключения не вариант.

Edit:

Было бы что-то подобное предпочтительнее?

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

Это исключает код стрелки, но вид кода стрелки помещает всю регистрацию ошибок в одном месте.

Ответы [ 4 ]

2 голосов
/ 04 июля 2010

Использование возвращаемых значений в качестве кодов ошибок просто приводит к такому коду, его нельзя значительно улучшить.Немного более чистый способ будет использовать goto для группировки всей обработки ошибок в один блок и для уменьшения вложенности блоков.

Это, однако, не решает реальную проблему, которая использует возвращаемые значения в качестве кодов ошибок.В C альтернативы нет, но в C ++ имеются исключения, которые следует использовать.Если это не вариант, вы застряли на том, что у вас есть.

0 голосов
/ 23 февраля 2012

Я знаю, что уже немного поздно, но я знаю, что QueryIntAttribute возвращает значение, которое можно использовать для обработки ошибок, если вы хотите это также для своих атрибутов.

if (instance->QueryIntAttribute("x",&x)!=TIXML_SUCCESS)
    cout << "No x value found";
0 голосов
/ 05 июля 2010

Я не надуюсь и не надуюсь, но если кто-нибудь может придумать чище способ сделать это было бы оценили.

Я заменил вложенные if в операторах возврата при ошибке (это заставляет код «течь вниз», а не в форме «стрелки». Я также заменил ваши циклы do на циклы for (чтобы я мог лучше это понять).

Это то, что вы хотели?

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;
0 голосов
/ 03 июля 2010

Вы можете создать для этого макрос, который включает в себя if (!var) { .. return false; } и отчеты об ошибках.

Тем не менее, я не вижу, как все это можно улучшить; это просто так оно и есть. C'est la vie. C'est le code ...

...