C ++编译时错误不喜欢DocTree :: setTree(std :: __ 1 :: basic_string <char,std :: __ 1 :: char_traits <char =“”>,std :: __ 1 :: allocator <char>&gt; const&amp; )</焦炭> </炭,>

时间:2014-11-15 21:44:27

标签: c++ xcode macos

我正在尝试调试我的C ++程序,因为我逐个构建它。现在,我试图做的就是测试我将html文件读入string的过程(顺便说一句,它是否会像读取文本文件一样直接工作?它是什么?基本上是一样的,对吧?),并且我得到的错误引用了我的类实现的不同部分,即使在我的代码运行中根本没有使用该实现。我的编译器是Mac OSX Yosemite上的XCode 6,配备Intel Core i5的Macbook Pro。在我真正尝试编译之前,它没有标记任何错误。

错误:

Undefined symbols for architecture x86_64:
  "HtmlProcessor::HtmlProcessor()", referenced from:
      _main in main.o
  "HtmlProcessor::~HtmlProcessor()", referenced from:
      _main in main.o
  "DocTree::_hp", referenced from:
      DocTree::setTree(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in CSS_Generator.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

由于我不允许在此发布内嵌图片,请查看此链接,完整错误:http://i.stack.imgur.com/1BEqn.png

如果没有完成&#34;代码转储&#34;,我会发布我的文件的缩写版本,包括似乎相关的部分。

main.cpp中:

#include <iostream>
#include "CSS_Generator.h"

int main(int argc, const char * argv[]) {
    node dummyNode;
    HtmlProcessor HP;
    HP.processFile("sample.html", dummyNode);

    return 0;
}

CSS_Generator.h

#ifndef __CSS_Template_Generator__CSS_Generator__
#define __CSS_Template_Generator__CSS_Generator__

#include <stdio.h>
#include <string>
#include <vector>
#include <utility>
#include <set>

struct node
{
    std::string element_type;
    std::set<std::string> class_list;
    std::string iden;
    std::vector<node*> children;
};

class HtmlProcessor
{
public:
    HtmlProcessor();
    ~HtmlProcessor();
    void processFile(const std::string &, node &);

private:
    bool _getNextBracket(std::pair<std::string::const_iterator &, const std::string::const_iterator &> &, bool &);
    bool _processTag(std::string::const_iterator, const std::string::const_iterator, node &);
    bool _hasNextAttribute(std::string::const_iterator &, const std::string::const_iterator &, std::pair<std::string, std::string> &);
    bool _processAttributes(const std::vector<std::pair<std::string, std::string>> &, std::set<std::string> &, std::string &);
    std::vector<std::string> _splitWithoutQuotes(std::string::const_iterator, std::string::const_iterator);
    bool _splitAttribute(const std::string &, std::pair<std::string, std::string> &);
    static const std::string _elementTypeChars;
    static const std::string _attributeTypeChars;
    static const std::string _attributeValChars;
};

class DocTree
{
public:
    DocTree();
    ~DocTree();
    void setTree(const std::string &);
    void getCSS(const std::string &);

private:
    node * _root;
    void _destroyTree(node *);
    std::string _tree2Str(node *);
    std::string _innerTree2Str(node *, unsigned);
    static HtmlProcessor _hp;
};


#endif /* defined(__CSS_Template_Generator__CSS_Generator__) */

CSS_Generator.cpp:

#include "CSS_Generator.h"

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <fstream>

/* -------------------------- DocTree class implementation begin ---------------------------*/


void DocTree::setTree(const std::string & F)
{
    _destroyTree(_root);
    try
    {
        _hp.processFile(F, *_root);
    }
    catch (const std::string & error_message)
    {
        std::cout << error_message << std::endl;
    }
}

void DocTree::_destroyTree(node * rt)
{
    for (std::vector<node*>::iterator it(rt->children.begin()), offend(rt->children.end()); it != offend; ++it)
        _destroyTree(*it);

    delete rt;
}

std::string DocTree::_innerTree2Str(node * rt, unsigned depth)
{
    std::string css("");

    if (depth > 0)
        css.append(" > ");


    if (rt)
    {
        css.append(rt->element_type);

        if (!rt->class_list.empty())
        {
            for (std::set<std::string>::iterator it(rt->class_list.begin()), offend(rt->class_list.end()); it != offend; ++it)
                css.append("." + *it);
        }
        if (!rt->iden.empty())
        {
            css.append("#" + rt->iden);
        }
        if (!rt->children.empty())
        {
            std::string tabs(depth, '\t');
            for (std::vector<node*>::iterator it(rt->children.begin()), offend(rt->children.end()); it != offend; ++it)
                css.append("\n" + tabs + _innerTree2Str(*it, depth + 1));
        }
    }
    return css;
}

std::string DocTree::_tree2Str(node * rt)
{
    return _innerTree2Str(rt, 0);
}


/* -------------------------- DocTree class implementation end -------------------------------*/

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */


/* ---------------------- HtmlProcessor class implementation begin -------------------------- */


const std::string HtmlProcessor::_elementTypeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const std::string HtmlProcessor::_attributeTypeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
const std::string HtmlProcessor::_attributeValChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_ ";

void HtmlProcessor::processFile(const std::string & F, node & nd)
{
/*  F: Path of HTML file
   nd: node element that will be the root of the document tree tree if processing is successful

      Throws an error if any problems occur during the processing
*/
    std::ifstream html_file(F);
    std::string html_str, line;
    while(std::getline(html_file, line)) html_str.append(line);
    /* ----- TEST ----- */
    std::cout << html_str;
    /* ---------------- */


}


bool HtmlProcessor::_processTag(std::string::const_iterator it1, const std::string::const_iterator it2, node & nd)
{
    /*
       [it1, it2): iterators for the range of the string
               nd: node in which classes and ids of the tage are stored

        Returns true or false depending on whether a problem was encountered during the processing.
    */



    /* Get the element type, at the beginning of the tag: */
    std::string elementType("");
    while (_elementTypeChars.find(*it1) != std::string::npos && it1 != it2) elementType.push_back(*it1++);
    if (elementType.empty()) return false;
    nd.element_type = elementType;

    /* Get any attributes: */
    std::vector<std::pair<std::string, std::string>> attributes;
    std::pair<std::string, std::string> thisAttribute;
    while (_hasNextAttribute(it1, it2, thisAttribute)) attributes.push_back(thisAttribute);
    if (!_processAttributes(attributes, nd.class_list, nd.iden)) return false;


    return true;
}

bool HtmlProcessor::_hasNextAttribute(std::string::const_iterator & it1, const std::string::const_iterator & it2, std::pair<std::string, std::string> & attrHolder)
{
      /* Parses the first HTML attributes in the iterator range [it1, it2), adding them to attrHolder; eg.

         class="myClass1 myClass2" id="myId" onsubmit = "myFunction()"

         ----------  _hasNextAttribute  -------->

         attrHolder = (class, myClass1 myClass2)

         When the function terminates, it1 will be the iterator to the last character parsed, will be equal to 
         it2 if no characters were parsed.

      */

    while (*it1 == ' ' && it1 != it2) ++it1; /* Skip through left whitespace padding */
    if (it1 == it2) return true; /* No attributes in tag; only whitespace after the element name. Such is valid HTML. */

    std::string attr(""); /* String to hold the attribute type, expected after any whitespace. Should be non-empty. */
    while (_attributeTypeChars.find(*it1) == std::string::npos && it1 != it2) attr.push_back(*it1++);
    if (attr.empty()) return false;

    while (*it1 == ' ' && it1 != it2) ++it1; /* Skip through whitespace padding between the attribute name and equals sign */
    if (*it1 != '=' || it1++ == it2) return false; /* Current character should be an equals sign */

    while (*it1 == ' ' && it1 != it2) ++it1; /* Skip through whitespace between the equals sign and quotation mark */
    if (*it1 != '"' || it1++ == it2) return false; /* Current character should be a quotation mark */

    std::string val(""); /* String to hold the attribute's value, exepcted after the first quotation mark. */
    while (_attributeValChars.find(*it1) != std::string::npos) val.push_back(*it1++);
    if (attr.empty()) return false;

    if (*it1 != '"' || it1++ != it2) return false; /* Current character should be a quotation mark */

    /* If we're here, it1 should point to the character after the quotation mark that closes off the attribute's value */
    attrHolder = std::make_pair(attr, val);

    return true;

}

bool HtmlProcessor::_processAttributes(const std::vector<std::pair<std::string, std::string>> & attrs, std::set<std::string> &classesTarget, std::string & identifierTarget)
{
    for (std::vector<std::pair<std::string, std::string>>::const_iterator it(attrs.cbegin()), offend(attrs.end()); it != offend; ++it)
    {
        std::string thisAttr(it->first), thisVal(it->second);
        std::transform(thisAttr.begin(), thisAttr.end(), thisAttr.begin(), ::tolower);
        if (thisAttr == "id")
            identifierTarget = thisVal;
        else if (thisAttr == "class")
        {
            /* Since the value for a class attribute can be several classes separated by whitespace, 
               add all of them to set of classes for the node.
            */
            std::stringstream ss(thisAttr);
            std::string thisClass;
            while (std::getline(ss, thisClass, ' ')) classesTarget.insert(thisClass);
        }

    }


    return true;
}

bool HtmlProcessor::_getNextBracket(std::pair<std::string::const_iterator &, const std::string::const_iterator &> & bounds, bool & IQ)
{
    bool foundOne = false;
    while (bounds.first != bounds.second)
    {
        switch (*bounds.first)
        {
            case '<':
                if (!IQ) foundOne = true;
                break;

            case '>':
                if (!IQ) foundOne = true;
                break;
            case '"':
                IQ = !IQ;
                break;
        }
        if (foundOne) break;
        ++bounds.first;
    }
    return foundOne;
}

/* ----------------------------- HtmlProcessor class implementation end --------------------------- */

0 个答案:

没有答案