我需要编写一个程序来填充xml文件中的结构并读取xml文件,但这不是问题。
首先,我编写了一个没有模块的程序(它正在编译):
的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;
}
生成文件:
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编译这些文件后出错了 终端:
brusentcov@brusentcov:~/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 :(得分: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 $@ $^ -L /usr/lib/x86_64-linux-gnu/ -lxml2
%.o:%.c
$(CC) $(CFLAGS) -o $@ $< -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
强烈建议您修正有关从double
转换为float
由于我没有预期的输入文件,因此输出为:
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上运行
答案 1 :(得分:0)
谢谢大家。问题确实存在于makefile中:当我写“-c”时我应该写“* c”。