2017-03-09 46 views
1

我需要編寫一個程序,從xml文件中填充結構並讀取xml文件,但這不是問題。C:錯誤,當我嘗試單獨的程序模塊

首先,我不寫模塊的程序(它的編譯):

的main.c

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <strings.h> 
#include <libxml/tree.h> 
#include <string.h> 

#include "startupDirector.h" 

static void startup_from_xml(Startup_T *startup, xmlNode * curNode) 
{ 
    char * data; 
    for(curNode = curNode->children; curNode != NULL; curNode = curNode->next) 
    { 
     // Get "name" string field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"name")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      strcpy(startup->name, data); 
      continue; 
     } 
     // Get "budget" integer field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"budget")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      startup->budget = atoi(data); 
      continue; 
     } 
    } 
} 

static Director_T *director_from_xml(Director_T *curDirector, xmlNode * curNode) 
{ 
    char *data; 
    char *properties; 

    // Get "name" string attribute. 
    properties = (char *) xmlGetProp(curNode, (const xmlChar *)"name"); 
    strcpy(curDirector->name, properties); 
    // Get "surname" string attribute. 
    properties = (char *)xmlGetProp(curNode, (const xmlChar *)"surname"); 
    strcpy(curDirector->surname, properties); 
    for(curNode = curNode->children; curNode != NULL; curNode = curNode->next) 
    { 
     // Get "nationality" string field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"nationality")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      strcpy(curDirector->nationality, data); 
      continue; 
     } 
     // Get "birthdate" UTC ISO 8601 field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"birthdate")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      sscanf(data, "%d-%d-%d", 
        &curDirector->birthDate.tm_year, 
        &curDirector->birthDate.tm_mday, 
        &curDirector->birthDate.tm_mon); 
      continue; 
     } 
     // Get "enthusiasm" integer field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"enthusiasm")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      curDirector->enthusiasm = atoi(data); 
      continue; 
     } 
     // Get "experience" double field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"experience")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      curDirector->experience = atof(data); 
      continue; 
     } 
     // Get "money" integer field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"money")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      curDirector->money = atoi(data); 
      continue; 
     } 
     // Get "startup" (string,integer) complex field. 
     if(!xmlStrcmp(curNode->name, (xmlChar *)"startup")) 
     { 
      startup_from_xml(&(curDirector->startup), curNode); 
      continue; 
     } 
    } 
    return (curDirector); 
} 

Director_T *director_new(void) 
{ 
    Director_T *director = (Director_T *)malloc(sizeof(struct Director_S)); 
    strcpy(director->name, ""); 
    strcpy(director->surname, ""); 
    strcpy(director->nationality, ""); 
    memset(&director->birthDate, 0, sizeof(director->birthDate)); 
    director->enthusiasm = 0; 
    director->experience = 0; 
    director->money = 0; 
    strcpy(director->startup.name, ""); 
    director->startup.budget = 0; 
    return (director); 
} 

void xmlParse(Director_T **directorSet, const char * XMLFileName) 
{ 
    xmlDoc * doc = xmlReadFile(XMLFileName, "UTF-8", 0); 
    if(doc == NULL) 
    { 
     xmlFreeDoc(doc); 
     return; 
    } 
    xmlNode *xml_root = xmlDocGetRootElement(doc); 
    xmlNode *curNode; 
    int i; 
    for(i = 0, curNode = xml_root->children; curNode != NULL; curNode = curNode->next) 
    { 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"director")) 
     { 
      director_from_xml(directorSet[i++], curNode); 
     } 
    } 
    xmlFreeDoc(doc); 
} 

void printDirectorInfo(Director_T *director) 
{ 
    printf("\t[%s]\n" 
      "\t[%s]\n" 
      "\t[%s]\n" 
      "\t%d-%d-%d\n" 
      "\t%i\n" 
      "\t%f\n" 
      "\t%i\n" 
      "\t[%s]\n" 
      "\t%i\n\n", 
      director->name, 
      director->surname, 
      director->nationality, 
      director->birthDate.tm_year, director->birthDate.tm_mon, director->birthDate.tm_mday, 
      director->enthusiasm, 
      director->experience, 
      director->money, 
      director->startup.name, 
      director->startup.budget 
     ); 
} 

void director_delete(Director_T *director) 
{ 
    free(director); 
} 

int main() 
{ 
    const char *filePath = "StartupDirector.xml"; 
    Director_T *directors[DIRECTORS_COUNT]; 

    // Init directors array. 
    for(int i = 0; i < DIRECTORS_COUNT; i++) 
    { 
     directors[i] = director_new(); 
    } 

    // Parse elements from .xml file. 
    xmlParse(directors, filePath); 

    // Print parsed info. 
    for(int i = 0; i < DIRECTORS_COUNT; i++) 
    { 
     printf("STARTUP_DIRECTOR #%i\n", (i+1)); 
     printDirectorInfo(directors[i]); 
    } 

    // Free allocated memory. 
    for(int i = 0; i < DIRECTORS_COUNT; i++) 
    { 
     director_delete(directors[i]); 
    } 
    return 0; 
} 

的Makefile:

all: 
    gcc main.c -g -Werror -c -I /usr/include/libxml2 
    gcc *.o -lxml2 
    rm *.o 

當我編譯這一切的main.c要美觀大方,但後來我試圖分開我的程序模塊,並得到了一個問題:

new main.c

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <strings.h> 
#include <libxml/tree.h> 
#include <string.h> 

#include "startupDirector.h" 

int main() 
{ 
    const char *filePath = "StartupDirector.xml"; 
    Director_T *directors[DIRECTORS_COUNT]; 

    // Init directors array. 
    for(int i = 0; i < DIRECTORS_COUNT; i++) 
    { 
     directors[i] = director_new(); 
    } 

    // Parse elements from .xml file. 
    xmlParse(directors, filePath); 

    // Print parsed info. 
    for(int i = 0; i < DIRECTORS_COUNT; i++) 
    { 
     printf("STARTUP_DIRECTOR #%i\n", (i+1)); 
     printDirectorInfo(directors[i]); 
    } 

    // Free allocated memory 
    for(int i = 0; i < DIRECTORS_COUNT; i++) 
    { 
     director_delete(directors[i]); 
    } 
    return 0; 
} 

startupDirector.c(用於模塊)

#include <stdlib.h> 
#include <stdio.h> 
#include <strings.h> 
#include <time.h> 

#include <libxml/tree.h> 
#include "startupDirector.h" 

// private: 
static void startup_from_xml(Startup_T *startup, xmlNode * curNode) 
{ 
    char * data; 
    for(curNode = curNode->children; curNode != NULL; curNode = curNode->next) 
    { 
     // Get "name" string field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"name")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      strcpy(startup->name, data); 
      continue; 
     } 
     // Get "budget" integer field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"budget")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      startup->budget = atoi(data); 
      continue; 
     } 
    } 
} 

static Director_T *director_from_xml(Director_T *curDirector, xmlNode * curNode) 
{ 
    char *data; 
    char *properties; 

    // Get "name" string attribute. 
    properties = (char *) xmlGetProp(curNode, (const xmlChar *)"name"); 
    strcpy(curDirector->name, properties); 
    // Get "surname" string attribute. 
    properties = (char *)xmlGetProp(curNode, (const xmlChar *)"surname"); 
    strcpy(curDirector->surname, properties); 
    for(curNode = curNode->children; curNode != NULL; curNode = curNode->next) 
    { 
     // Get "nationality" string field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"nationality")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      strcpy(curDirector->nationality, data); 
      continue; 
     } 
     // Get "birthdate" UTC ISO 8601 field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"birthdate")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      sscanf(data, "%d-%d-%d", 
        &curDirector->birthDate.tm_year, 
        &curDirector->birthDate.tm_mday, 
        &curDirector->birthDate.tm_mon); 
      continue; 
     } 
     // Get "enthusiasm" integer field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"enthusiasm")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      curDirector->enthusiasm = atoi(data); 
      continue; 
     } 
     // Get "experience" double field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"experience")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      curDirector->experience = atof(data); 
      continue; 
     } 
     // Get "money" integer field. 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"money")) 
     { 
      data = (char *)xmlNodeGetContent(curNode); 
      curDirector->money = atoi(data); 
      continue; 
     } 
     // Get "startup" (string,integer) complex field. 
     if(!xmlStrcmp(curNode->name, (xmlChar *)"startup")) 
     { 
      startup_from_xml(&(curDirector->startup), curNode); 
      continue; 
     } 
    } 
    return (curDirector); 
} 
// public: 
Director_T *director_new(void) 
{ 
    Director_T *director = (Director_T *)malloc(sizeof(struct Director_S)); 
    strcpy(director->name, ""); 
    strcpy(director->surname, ""); 
    strcpy(director->nationality, ""); 
    memset(&director->birthDate, 0, sizeof(director->birthDate)); 
    director->enthusiasm = 0; 
    director->experience = 0; 
    director->money = 0; 
    strcpy(director->startup.name, ""); 
    director->startup.budget = 0; 
    return (director); 
} 

void director_delete(Director_T *director) 
{ 
    free(director); 
} 

void xmlParse(Director_T **directorSet, const char * XMLFileName) 
{ 
    xmlDoc * doc = xmlReadFile(XMLFileName, "UTF-8", 0); 
    if(doc == NULL) 
    { 
     xmlFreeDoc(doc); 
     return; 
    } 
    xmlNode *xml_root = xmlDocGetRootElement(doc); 
    xmlNode *curNode; 
    int i; 
    for(i = 0, curNode = xml_root->children; curNode != NULL; curNode = curNode->next) 
    { 
     if(!xmlStrcmp(curNode->name, (const xmlChar *)"director")) 
     { 
      director_from_xml(directorSet[i++], curNode); 
     } 
    } 
    xmlFreeDoc(doc); 
} 

void printDirectorInfo(Director_T *director) 
{ 
    printf("\t[%s]\n" 
      "\t[%s]\n" 
      "\t[%s]\n" 
      "\t%d-%d-%d\n" 
      "\t%i\n" 
      "\t%f\n" 
      "\t%i\n" 
      "\t[%s]\n" 
      "\t%i\n\n", 
      director->name, 
      director->surname, 
      director->nationality, 
      director->birthDate.tm_year, director->birthDate.tm_mon, director->birthDate.tm_mday, 
      director->enthusiasm, 
      director->experience, 
      director->money, 
      director->startup.name, 
      director->startup.budget 
     ); 
} 

startupDirector.h

#ifndef STARTUPDIRECTOR_H 
#define STARTUPDIRECTOR_H 

#include <time.h> // time_t 

#define DIRECTOR_NAME_LEN 50 
#define DIRECTOR_SURNAME_LEN 50 
#define DIRECTOR_NATIONALITY_LEN 50 
#define STARTUP_NAME_LEN 100 

#define DIRECTORS_COUNT 4 

typedef struct Startup_S 
{ 
    char name[STARTUP_NAME_LEN]; 
    int budget; 
} Startup_T; 

typedef struct Director_S 
{ 
    char name[DIRECTOR_NAME_LEN]; 
    char surname[DIRECTOR_SURNAME_LEN]; 
    char nationality[DIRECTOR_NATIONALITY_LEN]; 
    struct tm birthDate; 
    int enthusiasm; 
    float experience; 
    int money; 
    struct Startup_S startup; 
} Director_T; 

Director_T *director_new(void); 
void director_delete(Director_T *director); 
Startup_T *startup_new(void); 
void startup_delete(Startup_T *startup); 

void xmlParse(Director_T *directorSet[], const char * XMLFileName); 
void printDirectorInfo(Director_T *director); 

#endif 

,利用makefile編譯這個文件後,我有一個錯誤 終端:

[email protected]:~/projects/xml_startup$ make 
gcc main.c -g -Werror -c -I /usr/include/libxml2 
gcc *.o -lxml2 
main.o: In function `main': 
/home/brusentcov/projects/xml_startup/main.c:168: undefined reference to `director_new' 
/home/brusentcov/projects/xml_startup/main.c:172: undefined reference to `xmlParse' 
/home/brusentcov/projects/xml_startup/main.c:178: undefined reference to `printDirectorInfo' 
/home/brusentcov/projects/xml_startup/main.c:184: undefined reference to `director_delete' 
collect2: error: ld returned 1 exit status 

我希望有人能幫助我。感謝您的關注,如果您閱讀此內容。

+0

您需要**編譯並鏈接**'startupDirector.c',而不僅僅是'main.c' – StoryTeller

+0

'startupDirector.c'文件缺少必需的語句:'#include (不是字符串。 h)對於函數'strcpy()'和'memset()',它有一個聲明:'#include '這是不使用的。 – user3629249

回答

0

感謝所有。問題確實在makefile中:當我寫「-c」時,我應該寫「* c」。

0

問題是makefile。

下面是我用make文件(固定在評論中提到的#include聲明

#all: 
# gcc xml_main.c -g -Werror -c -I /usr/include/libxml2 
# gcc *.o -lxml2 
# rm *.o 

CC := /usr/bin/gcc 
RM := /bin/rm 

CFLAGS := -c -Wall -Wextra -pedantic -Wconversion -std=gnu11 

SRC := main.c startupDirector.c 

OBJ := $(SRC:.c=.o) 

target := xmlProgram 

.PSEUDO: all clean 

all: $(target) 

$(target): $(OBJ) 
    $(CC) -o [email protected] $^ -L /usr/lib/x86_64-linux-gnu/ -lxml2 

%.o:%.c 
     $(CC) $(CFLAGS) -o [email protected] $< -I. -I /usr/include/libxml2 

clean: 
    $(RM) -f $(OBJ) $(target) 

這裏是從調用輸出完全以make

/usr/bin/gcc -c -Wall -Wextra -pedantic -Wconversion -std=gnu11 -o main.o main.c -I. -I /usr/include/libxml2 
/usr/bin/gcc -c -Wall -Wextra -pedantic -Wconversion -std=gnu11 -o startupDirector.o startupDirector.c -I. -I /usr/include/libxml2 
startupDirector.c: In function ‘director_from_xml’: 
startupDirector.c:73:39: warning: conversion to ‘float’ from ‘double’ may alter its value [-Wfloat-conversion] 
      curDirector->experience = atof(data); 
            ^
/usr/bin/gcc -o xmlProgram main.o startupDirector.o -L /usr/lib/x86_64-linux-gnu/ -lxml2 

後,強烈建議您修復關於從doublefloat

的轉換的警告,因爲我做了沒有預期的輸入文件,這裏是輸出:

I/O warning : failed to load external entity "StartupDirector.xml" 
STARTUP_DIRECTOR #1 
    [] 
    [] 
    [] 
    0-0-0 
    0 
    0.000000 
    0 
    [] 
    0 

STARTUP_DIRECTOR #2 
    [] 
    [] 
    [] 
    0-0-0 
    0 
    0.000000 
    0 
    [] 
    0 

STARTUP_DIRECTOR #3 
    [] 
    [] 
    [] 
    0-0-0 
    0 
    0.000000 
    0 
    [] 
    0 

STARTUP_DIRECTOR #4 
    [] 
    [] 
    [] 
    0-0-0 
    0 
    0.000000 
    0 
    [] 
    0 

注:我編譯,連接,運行在Ubuntu Linux 16.04

相關問題