#c #c #boost #libxml2 #boost-preprocessor
#c #c #повышение #libxml2 #boost-препроцессор
Вопрос:
typedef struct _xmlNode xmlNode;
typedef xmlNode *xmlNodePtr;
struct _xmlNode {
void *_private; /* application data */
xmlElementType type; /* type number, must be second ! */
const xmlChar *name; /* the name of the node, or the entity */
struct _xmlNode *children; /* parent->childs link */
struct _xmlNode *last; /* last child link */
struct _xmlNode *parent; /* child->parent link */
struct _xmlNode *next; /* next sibling link */
struct _xmlNode *prev; /* previous sibling link */
struct _xmlDoc *doc; /* the containing document */
/* End of common part */
xmlNs *ns; /* pointer to the associated namespace */
xmlChar *content; /* the content */
...
}
Есть узел, подобный указанному выше, и предположим, что у него есть xmlNode node
(нет NULL
).
Один хочет получить доступ
node->next->children->next->next->content
но поскольку каждый указатель может быть NULL
, нужно проверять их все.
if(node == NULL || node->next == NULL || node->next->children == NULL ...)
fprintf(stderr, "err");
Есть ли способ проверить, является ли указатель нулевым автоматически? Например
#define CHECK(ptr) BOOST_PP_????(...) ??
if (CHECK(node->next->children->next->next->content))
...
_xmlNode
это из libxml2, и поскольку я обращаюсь к участникам в проанализированных данных HTML, чтобы получить определенный элемент для обхода веб-сайта, доступ не может быть регулярным, как показано ниже.
bool go_next(xmlNode n, int num) {
for(; num; --num) {
if(n==NULL) return false;
n = n->next;
}
return true;
}
Комментарии:
1. Почему тег «с»?
2. @UlrichEckhardt метание просто для объяснения.
Ответ №1:
Тривиально использовать enum
и составной литерал, что-то вроде:
enum {END, PREV, NEXT, CHILDREN, CONTENTS};
int check_node(xmlNode node, int test[])
{
while ((node != NULL) amp;amp; (*test != END))
{
switch (*test)
{
case PREV:
node = node->prev;
break;
case NEXT:
node = node->next;
break;
case CHILDREN:
node = node->children;
break;
case CONTENTS:
node = node->contents;
break;
default:
return 0;
}
test ;
}
return (node != NULL);
}
if (!check_node(node, (int []){NEXT, CHILDREN, NEXT, NEXT, CONTENTS, END}))
{
fprintf(stderr, "err");
}