2015-12-02 35 views
0

我正在開發一些從xml文檔檢索某些值並使用嵌套結構指針來幫助我管理數據的過程。char *在嵌套結構中產生意外的結果

我遇到我的結構之一內的字符串值意外行爲:

這是程序:

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」,其中期望值爲「廣告系統」

如果我存儲的測試值「作品」 - 這裏沒有任何問題

如果我連打印節點值,這也適用:「廣告系統」

在此先感謝

- 頭文件

/* 
* 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日 *作者:hearme */

#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

+0

而內存指出'節點 - >孩子 - > content'將保持有效,你需要它的整個時間?在使用'xmlFile-> Ads-> data-> Inline-> AdSystem'之前,您不會「釋放」它?你如何檢查內存的內容?你在哪裏檢查它?'node-> children-> content' *已經*初始化爲指向有效的分配內存?你爲什麼要投射指針?你能告訴我們結構的定義,或者至少是相關的部分嗎?如果您刪除了演員陣容,是否會收到編譯器警告或錯誤?如果您啓用更多警告(如果使用GCC或Clang,請添加'-Wall -Wextra -pedantic')? –

+0

您不應該直接'printf'字符串,如果字符串中有格式化字符,則可能會導致問題。 – horns

+0

我對C相當陌生,但我懷疑你在說什麼,因爲 - > AdSystem有效地指向由節點創建的值,當節點被釋放時,值也是如此?那是對的嗎? 我正在檢查我的主要過程中的值,我首先解析xml文檔,釋放文檔,然後返回xmlFile。 在這種情況下,分配此值的最佳方法是什麼?我懷疑創建直接複製是正確的方法? –

回答

1

OK,

我固定的錯誤,但它不」看看最乾淨的代碼,也許有人可以建議,如果這是好的?

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

不,它不是。 1)你輸入'malloc()'的結果,不要這樣做。 2)你分配一個字節的內存,這已經被字符串末尾的'nul'使用。所以你必須爲此清空字符串,而不是分配內存。您必須分配適量的內存。 –

+1

你需要分配足夠的內存。應該是'malloc(strlen(nodeValue)+1);'。話雖如此,你需要在做這樣的事情之前研究一下字符串的基礎知識。 – Lundin

+1

回到最初的問題,有沒有人有一個簡單而有效的方式來分配節點值的值?這似乎比它應該更復雜 –

0

我固定的錯誤,但它看起來不乾淨的代碼,也許如果這是好的 有人能指教?

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

薩米Kuhmonen和倫丁已經指出的是,分配的大小是沒有的。

回到最初的問題,有沒有人有一個簡單有效的 方式從節點值中分配一個值?這似乎更多 比它應該更復雜

你是對的;如果你有一個POSIX系統,上面可以通過使用strdup()被簡化:

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