C:尝试单独的程序到模块时出错



我需要编写一个填充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-%dn"
           "t%in"
           "t%fn"
           "t%in"
           "t[%s]n"
           "t%inn",
           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 #%in", (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时,一切都很好,但是随后我尝试将程序分开以模块并遇到问题:

新的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 #%in", (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-%dn"
           "t%in"
           "t%fn"
           "t%in"
           "t[%s]n"
           "t%inn",
           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

我希望有人会帮助我。感谢您阅读此内容。

问题是makefile。

这是我使用的制造文件(修复了评论中提到的#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

感谢所有人。问题确实在于makefile:我应该写"*c&quot"当我写下-c&quot。

最新更新