char *从嵌套结构中的过程产生意外结果

时间:2015-12-02 12:00:04

标签: c pointers struct char

我正在开发一些从xml doc中检索某些值的过程,并使用嵌套的struct指针来帮助我管理数据。

我遇到了来自我的一个结构中的字符串值的意外行为:

这是程序:

void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){

do {
    if (xmlStrcmp (node->name, XMLSTR("AdSystem")) == 0){

        xmlFile->Ads->data->Inline->AdSystem = (char *)node->children->content; // does not work - displays �9;
        xmlFile->Ads->data->Inline->AdSystem = "Works"; // works
        printf ((char *)node->children->content); // works
    }
    else if (xmlStrcmp (node->name, XMLSTR("Creatives")) == 0){
        parseCreatives (doc, node->children, xmlFile);
    }

    } while((node = node->next));

}

这是我遇到的问题:

xmlFile->Ads->data->Inline->AdSystem = (char *)node->children->content;

当我在我的程序中测试结果时,该值看起来并没有指向内存中的正确位置,因为它产生垃圾,即:"�9"其中预期值是"广告系统"

如果我存储测试值" Works" - 这里没问题

如果我打印节点值,这也有效:"广告系统"

提前致谢

- HEADER FILE

/*
* daastXML.h
 *
 *  Created on: Nov 27, 2015
 *      Author: hearme
 */

#ifndef DAASTXML_H_
#define DAASTXML_H_

#define VECTOR_INITIAL_CAPACITY 100

// Define a vector type
typedef struct {
    int size;               // slots used so far
    int capacity;           // total available slots
    struct daastAd *data;     // array of ads we're storing

    char * testData;
} VectorAds;

typedef struct {
    int size;               // slots used so far
    int capacity;           // total available slots
    struct daastCreative *data;     // array of ads we're storing
} VectorCreatives;

typedef struct {
    int size;
    int capacity;
    struct daastMediaFile *data;
} VectorMediaFiles;


struct daastInline {

    // Required elements
    char *AdTitle;
    char *Impression;
    VectorCreatives *Creatives;
    char *Category;

    // Optional elements
    char *AdSystem;
    char *Description;
    char *Advertiser;
    char *Expires;

    // Multiple survey urls
    // Multiple error urls

    char *Pricing;

    // Extensions - for custom xml extensions

};

struct daastXML {
    char *version;
    VectorAds *Ads;
};

struct daastAd {
    char *id;
    char *sequence;
    struct daastInline *Inline;
};

struct daastMediaFile {
    char *id;
    char *delivery;
    char *type;
    char *url;
    char *bitRate;
};

struct daastLinear {
    char *duration;
    VectorMediaFiles MediaFiles;

};

struct daastCreative {
    struct daastLinear linear;
};



// Main handler
void processDaast (char * filePath, struct daastXML *xmlFile);



// Methods used to manage Ads collection
void vectorAds_init(VectorAds *vector);
void vectorAds_append(VectorAds *vector, struct daastAd value);
struct daastAd vectorAds_get(VectorAds *vector, int index);
void vectorAds_set(VectorAds *vector, int index, struct daastAd value);
void vectorAds_double_capacity_if_full(VectorAds *vector);
void vectorAds_free(VectorAds *vector);

// Methods used to manage Creatives collection
void vectorCreatives_init(VectorCreatives *vector);
void vectorCreatives_append(VectorCreatives *vector, struct daastCreative value);
struct daastCreative VectorCreatives_get(VectorCreatives *vector, int index);
void vectorCreatives_set(VectorCreatives *vector, int index, struct daastCreative value);
void vectorCreatives_double_capacity_if_full(VectorCreatives *vector);
void vectorCreatives_free(VectorCreatives *vector);

// Methods used to manage Creatives collection
void vectorMediaFiles_init(VectorMediaFiles *vector);
void vectorMediaFiles_append(VectorMediaFiles *vector, struct daastMediaFile value);
struct daastMediaFile vectorMediaFiles_get(VectorMediaFiles *vector, int index);
void vectorMediaFiles_set(VectorMediaFiles *vector, int index, struct daastMediaFile value);
void vectorMediaFiles_double_capacity_if_full(VectorMediaFiles *vector);
void vectorMediaFiles_free(VectorMediaFiles *vector);


#endif /* DAASTXML_H_ */

C档案     / *      * daastXML.c      *      *创建日期:2015年11月27日      *作者:听到      * /

#ifndef DAASTXML_C_
#define DAASTXML_C_

#define XMLSTR(str) ((xmlChar *)(str))

#include "daastXML.h"
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void parseAds(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseInline(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseCreatives(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseCreativesElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseCreativeElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseLinear (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);
void parseMediaFiles (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile);


void processDaast (char * filePath, struct daastXML *xmlFile){

    xmlDocPtr doc;
    xmlNodePtr node;

    doc = xmlParseFile(filePath);
    node = xmlDocGetRootElement(doc);


    if (xmlStrcmp (node->name, XMLSTR("DAAST")) == 0){

        xmlFile->version = (char *)xmlGetProp(node, XMLSTR("version"));
        parseAds(doc, node->children, xmlFile);

    }

    xmlFreeDoc(doc);

}

void parseAds(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){

    // Allocate new instance of the VectorAds and assign it to the xmlFile, set default data
    VectorAds *Ads;
    Ads = (VectorAds *) malloc (sizeof(VectorAds));

    Ads->testData = "testData";
    xmlFile->Ads = Ads;

    // Initialise the vector
    vectorAds_init(xmlFile->Ads);



    do {
        if (node == NULL) break;
        if (xmlIsBlankNode(node)) continue;

    if (xmlStrcmp (node->name, XMLSTR("Ad")) == 0) {

        // Set up new advert
        struct daastAd *newAd;
        newAd = (struct daastAd *) malloc (sizeof(struct daastAd));

        // Set add properties
        newAd->id = (char *)xmlGetProp(node, XMLSTR("id"));
        newAd->sequence = (char *)xmlGetProp(node, XMLSTR("sequence"));

        vectorAds_append(xmlFile->Ads, *newAd);

        // At this point we need to get the inline (or wrapper) info *** WRAPPER NOT INTEGRATED ***
        parseInline (doc, node->children, xmlFile);

    }
} while ((node = node->next));


}

void parseInline (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){


// Set up Inline Property Here
struct daastInline *Inline;
Inline = (struct daastInline *) malloc (sizeof(struct daastInline));

// Assing Inline Property
xmlFile->Ads->data->Inline = Inline;

do {
    if (node->type == XML_ELEMENT_NODE){
        if (xmlStrcmp (node->name, XMLSTR("InLine")) == 0){

            // Various parses at this level
            parseInlineElements(doc, node->children, xmlFile);
            //xmlFile->Ads->data->Inline->AdSystem = "AdSystem";

            // Should this be here?
            //parseCreatives (doc, node->children, xmlFile);

            break;
        }
    }
} while((node = node->next));
}

void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){

// loop through Inline child elements, and pick out the values
//*
do {
    if (xmlStrcmp (node->name, XMLSTR("AdSystem")) == 0){
        char *nodeValue = (char *) node->children->content;
        xmlFile->Ads->data->Inline->AdSystem = malloc (sizeof(char));
        strcpy (xmlFile->Ads->data->Inline->AdSystem, nodeValue);
    }
    else if (xmlStrcmp (node->name, XMLSTR("AdTitle")) == 0){
        char *nodeValue = (char *) node->children->content;
        xmlFile->Ads->data->Inline->AdTitle = malloc (sizeof(char));
        strcpy (xmlFile->Ads->data->Inline->AdTitle, nodeValue);
    }
    else if (xmlStrcmp (node->name, XMLSTR("Category")) == 0){
        char *nodeValue = "";
        nodeValue = (char *) node->children->content;
        xmlFile->Ads->data->Inline->Category = malloc (sizeof(char));
        strcpy (xmlFile->Ads->data->Inline->Category, nodeValue);
    }
    else if (xmlStrcmp (node->name, XMLSTR("Advertiser")) == 0){
        char *nodeValue = (char *) node->children->content;
        xmlFile->Ads->data->Inline->Advertiser = malloc (sizeof(char));
        strcpy (xmlFile->Ads->data->Inline->Advertiser, nodeValue);
    }
    else if (xmlStrcmp (node->name, XMLSTR("Pricing")) == 0){
        char *nodeValue = (char *) node->children->content;
        xmlFile->Ads->data->Inline->Pricing = malloc (sizeof(char));
        strcpy (xmlFile->Ads->data->Inline->Pricing, nodeValue);
    }
    else if (xmlStrcmp (node->name, XMLSTR("Expires")) == 0){
        char *nodeValue = (char *) node->children->content;
        xmlFile->Ads->data->Inline->Expires = malloc (sizeof(char));
        strcpy (xmlFile->Ads->data->Inline->Expires, nodeValue);
    }
//      else if (xmlStrcmp (node->name, XMLSTR("Impression")) == 0){
//          char *nodeValue = (char *) node->children->next->content;
//          xmlFile->Ads->data->Inline->Impression = malloc (sizeof(char));
//          strcpy (xmlFile->Ads->data->Inline->Impression, nodeValue);
//
//      }
    else if (xmlStrcmp (node->name, XMLSTR("Creatives")) == 0){
        parseCreatives (doc, node->children, xmlFile);
    }

} while((node = node->next));

}


void parseCreatives(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){

// Need to set up a new Creatives and assign it to the nested struct pointer
VectorCreatives *Creatives;
Creatives = (VectorCreatives *) malloc (sizeof(VectorCreatives));

VectorAds *Ads;
Ads = (VectorAds *) malloc (sizeof(VectorAds));

xmlFile->Ads->data->Inline->Creatives = Creatives;

vectorCreatives_init(xmlFile->Ads->data->Inline->Creatives);

//*parseCreativesElements(doc, node->next, xmlFile);

}


void parseCreativesElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){

do {

    // Loop through the creatives - find the individual Creatives
    if (xmlStrcmp (node->name, XMLSTR("Creative")) == 0){

        // Various parses at this level
        parseCreativeElements(doc, node->children, xmlFile);
    }

} while ((node = node->next));
}

void parseCreativeElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){

do {
    if (xmlStrcmp (node->name, XMLSTR("Linear")) == 0){
        // Linear branch
        parseLinear(doc, node->children, xmlFile);

    } else if (xmlStrcmp (node->name, XMLSTR("CompanionAds")) == 0){
        // Companion Ad branch

    }
} while ((node = node->next));

}

void parseLinear(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){

do {

    if (xmlStrcmp (node->name, XMLSTR("Duration")) == 0){

        struct daastCreative newCreative;

        //*newCreative.linear.duration = node->children->content;

        //*vectorCreatives_append(&xmlFile->Ads.data->Inline.Creatives, newCreative);

    } else if (xmlStrcmp (node->name, XMLSTR("MediaFiles")) == 0){
        //parseMediaFiles(doc,node->children,xmlFile);
    }
} while ((node = node->next));

}


void parseMediaFiles(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){

//* vectorMediaFiles_init(&xmlFile->Ads.data->Inline.Creatives.data->linear.MediaFiles);

do {

    // Store all occurrences of Media Files
    if (xmlStrcmp (node->name, XMLSTR("MediaFile")) == 0){

        // Create a new Media File, and append
        struct daastMediaFile newMediaFile;

        newMediaFile.url = (char *) node->children->next->content;

        newMediaFile.id = (char *)xmlGetProp(node, XMLSTR("id"));
        newMediaFile.type = (char *)xmlGetProp(node, XMLSTR("type"));
        newMediaFile.bitRate = (char *)xmlGetProp(node, XMLSTR("bitrate"));
        newMediaFile.delivery = (char *)xmlGetProp(node, XMLSTR("delivery"));

        //*vectorMediaFiles_append(&xmlFile->Ads.data->Inline.Creatives.data->linear.MediaFiles, newMediaFile);

    }
} while ((node = node->next));

}


// ***************************************************************
// ***************************************************************
// ***************************************************************
// ***************************************************************


// Methods to manage collection (Ads)

void vectorAds_init(VectorAds *vector) {
  // initialize size and capacity
  vector->size = 0;
  vector->capacity = VECTOR_INITIAL_CAPACITY;

  // allocate memory for vector->data
  vector->data = malloc(sizeof(struct daastAd) * vector->capacity);
}

void vectorAds_append(VectorAds *vector, struct daastAd value) {
  // make sure there's room to expand into
  vectorAds_double_capacity_if_full(vector);

  // append the value and increment vector->size
  vector->data[vector->size++] = value;
}

struct daastAd vectorAds_get(VectorAds *vector, int index) {
  if (index >= vector->size || index < 0) {
    printf("Index %d out of bounds for vector of size %d\n", index, vector->size);
    exit(1);
  }
  return vector->data[index];
}

void vectorAds_set(VectorAds *vector, int index, struct daastAd value) {
  // zero fill the vector up to the desired index
  struct daastAd zero;
  while (index >= vector->size) {
    vectorAds_append(vector, zero);
  }

  // set the value at the desired index
  vector->data[index] = value;
}

void vectorAds_double_capacity_if_full(VectorAds *vector) {
  if (vector->size >= vector->capacity) {
    // double vector->capacity and resize the allocated memory accordingly
    vector->capacity *= 2;
    vector->data = realloc(vector->data, sizeof(struct daastAd) * vector->capacity);
  }
}

void vectorAds_free(VectorAds *vector) {
  free(vector->data);
}


// Methods to manage Creatives Vector

void vectorCreatives_init(VectorCreatives *vector) {
  // initialize size and capacity
  vector->size = 0;
  vector->capacity = VECTOR_INITIAL_CAPACITY;

  // allocate memory for vector->data
  vector->data = malloc(sizeof(struct daastCreative) * vector->capacity);
}

void vectorCreatives_append(VectorCreatives *vector, struct daastCreative value) {
  // make sure there's room to expand into
  vectorCreatives_double_capacity_if_full(vector);

  // append the value and increment vector->size
  vector->data[vector->size++] = value;
}

struct daastCreative vectorCreatives_get(VectorCreatives *vector, int index) {
  if (index >= vector->size || index < 0) {
    printf("Index %d out of bounds for vector of size %d\n", index, vector->size);
    exit(1);
  }
  return vector->data[index];
}

void vectorCreatives_set(VectorCreatives *vector, int index, struct daastCreative value) {
  // zero fill the vector up to the desired index
  struct daastCreative zero;
  while (index >= vector->size) {
    vectorCreatives_append(vector, zero);
  }

  // set the value at the desired index
  vector->data[index] = value;
}

void vectorCreatives_double_capacity_if_full(VectorCreatives *vector) {
  if (vector->size >= vector->capacity) {
    // double vector->capacity and resize the allocated memory accordingly
    vector->capacity *= 2;
    vector->data = realloc(vector->data, sizeof(struct daastCreative) * vector->capacity);
  }
}

void vectorCreatives_free(VectorCreatives *vector) {
  free(vector->data);
}


// Methods used to manage MediaFiles Vector

void vectorMediaFiles_init(VectorMediaFiles *vector) {
  // initialize size and capacity
  vector->size = 0;
  vector->capacity = VECTOR_INITIAL_CAPACITY;

  // allocate memory for vector->data
  vector->data = malloc(sizeof(struct daastMediaFile) * vector->capacity);
}

void vectorMediaFiles_append(VectorMediaFiles *vector, struct daastMediaFile value) {
  // make sure there's room to expand into
  vectorMediaFiles_double_capacity_if_full(vector);

  // append the value and increment vector->size
  vector->data[vector->size++] = value;
}

struct daastMediaFile vectorMediaFiles_get(VectorMediaFiles *vector, int index) {
  if (index >= vector->size || index < 0) {
    printf("Index %d out of bounds for vector of size %d\n", index, vector->size);
    exit(1);
  }
  return vector->data[index];
}

void vectorMediaFiles_set(VectorMediaFiles *vector, int index, struct daastMediaFile value) {
  // zero fill the vector up to the desired index
  struct daastMediaFile zero;
  while (index >= vector->size) {
    vectorMediaFiles_append(vector, zero);
  }

  // set the value at the desired index
  vector->data[index] = value;
}

void vectorMediaFiles_double_capacity_if_full(VectorMediaFiles *vector) {
  if (vector->size >= vector->capacity) {
    // double vector->capacity and resize the allocated memory accordingly
    vector->capacity *= 2;
    vector->data = realloc(vector->data, sizeof(struct daastMediaFile) * vector->capacity);
  }
}

void vectorMediaFiles_free(VectorMediaFiles *vector) {
  free(vector->data);
}

#endif /* DAASTXML_C_ */

链接到XML:http://hearme.fm/ars.xml

2 个答案:

答案 0 :(得分:1)

行,

我已经修复了错误,但它看起来并不是最干净的代码,也许有人可以告诉我这是否合适?

@users

答案 1 :(得分:0)

  

我已修复错误,但它看起来并不是最干净的代码,也许   有人可以建议这是否合适?

char *nodeValue = (char*) node->children->content;
xmlFile->Ads->data->Inline->AdSystem = (char *) malloc (sizeof(char));
strcpy (xmlFile->Ads->data->Inline->AdSystem, nodeValue);

Sami Kuhmonen和Lundin已经注意到分配的大小不是。

  

回到原来的问题,有没有人有简单有效的   从节点值中分配值的方式?这似乎更多   比应该是复杂的

你是对的;如果您有POSIX系统,可以使用strdup()

简化上述内容
xmlFile->Ads->data->Inline->AdSystem = strdup((char *)node->children->content);