配置文件解析时出错



我在一些示例编码方面遇到了一些问题。理想情况下,我想要一个包含关键字的文件,其中包含可以更改的相关数据(int和字符串)。我将拥有可以随时编辑的持续时间(int)、目标(string)和源(source)。这最终将是为了在几天内的一段时间内方便地备份文件,备份文件的位置和去向。

这是我的示例代码,我已经修复了一些错误,但在最后几条上卡住了。或者有更简单的方法吗?对不起,这一切都很混乱,我是一个相当新的C++。。。

谢谢你的帮助,我知道要经历很多。也许有人有一个关于简单配置文件解析的好教程,我也可以读一下?

我的gcc版本是4.4.7

我收到的错误是:

g++配置文件.cppconfigFile.cpp:36:错误:非命名空间作用域"class Convert"中的显式专用化configFile.cpp:在静态成员函数"static T Convert::string_to_T(const std::string&)"中:configFile.cpp:31:error:"exitWithError"没有依赖于模板参数的参数,因此必须提供"exitWithError"的声明configFile.cpp:31:注意:(如果使用'-fpermission',G++将接受您的代码,但不赞成使用未声明的名称)

#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class Convert
{
public:
template <typename T>
static std::string T_to_string(T const &val) 
{
    std::ostringstream ostr;
    ostr << val;
    return ostr.str();
}
template <typename T>
static T string_to_T(std::string const &val) 
{
    std::istringstream istr(val);
    T returnVal;
    if (!(istr >> returnVal))
        exitWithError("CFG: Not a valid " + (std::string)typeid(T).name() + " received!n");
    return returnVal;
}
template <>
static std::string string_to_T(std::string const &val)
{
    return val;
}
};
void exitWithError(const std::string &error) 
{
std::cout << error;
std::cin.ignore();
std::cin.get();
exit(EXIT_FAILURE);
}
class ConfigFile
{
private:
std::map<std::string, std::string> contents;
std::string fName;
void removeComment(std::string &line) const
{
    if (line.find(';') != line.npos)
        line.erase(line.find(';'));
}
bool onlyWhitespace(const std::string &line) const
{
    return (line.find_first_not_of(' ') == line.npos);
}
bool validLine(const std::string &line) const
{
    std::string temp = line;
    temp.erase(0, temp.find_first_not_of("t "));
    if (temp[0] == '=')
        return false;
    for (size_t i = temp.find('=') + 1; i < temp.length(); i++)
                    if (temp[i] != ' ')
            return true;
    return false;
}
void extractKey(std::string &key, size_t const &sepPos, const std::string &line) const
{
    key = line.substr(0, sepPos);
    if (key.find('t') != line.npos || key.find(' ') != line.npos)
        key.erase(key.find_first_of("t "));
}
void extractValue(std::string &value, size_t const &sepPos, const std::string &line) const
{
    value = line.substr(sepPos + 1);
    value.erase(0, value.find_first_not_of("t "));
    value.erase(value.find_last_not_of("t ") + 1);
}
void extractContents(const std::string &line) 
{
    std::string temp = line;
    temp.erase(0, temp.find_first_not_of("t "));
    size_t sepPos = temp.find('=');
    std::string key, value;
    extractKey(key, sepPos, temp);
    extractValue(value, sepPos, temp);
    if (!keyExists(key))
        contents.insert(std::pair<std::string, std::string>(key, value));
    else
        exitWithError("CFG: Can only have unique key names!n");
}
void parseLine(const std::string &line, size_t const lineNo)
{
    if (line.find('=') == line.npos)
        exitWithError("CFG: Couldn't find separator on line: " + Convert::T_to_string(lineNo) + "n");
    if (!validLine(line))
        exitWithError("CFG: Bad format for line: " + Convert::T_to_string(lineNo) + "n");
    extractContents(line);
}
void ExtractKeys()
{
    std::ifstream file;
    file.open(fName.c_str());
    if (!file)
        exitWithError("CFG: File " + fName + " couldn't be found!n");
    std::string line;
    size_t lineNo = 0;
    while (std::getline(file, line))
    {
        lineNo++;
        std::string temp = line;
        if (temp.empty())
            continue;
        removeComment(temp);
        if (onlyWhitespace(temp))
            continue;
        parseLine(temp, lineNo);
    }
    file.close();
}
public:
ConfigFile(const std::string &fName)
{
    this->fName = fName;
    ExtractKeys();
}
bool keyExists(const std::string &key) const
{
    return contents.find(key) != contents.end();
}
template <typename ValueType>
ValueType getValueOfKey(const std::string &key, ValueType const &defaultValue = ValueType()) const
{
    if (!keyExists(key))
        return defaultValue;
    return Convert::string_to_T<ValueType>(contents.find(key)->second);
}
};
int main()
{
ConfigFile cfg("config.cfg");

bool exists = cfg.keyExists("car");
std::cout << "car key: " << std::boolalpha << exists << "n";
exists = cfg.keyExists("fruits");
std::cout << "fruits key: " << exists << "n";

std::string someValue = cfg.getValueOfKey<std::string>("mykey", "Unknown");
std::cout << "value of key mykey: " << someValue << "n";
std::string carValue = cfg.getValueOfKey<std::string>("car");
std::cout << "value of key car: " << carValue << "n";
double doubleVal = cfg.getValueOfKey<double>("double");
std::cout << "value of key double: " << doubleVal << "nn";

std::cin.get();
return 0;
}

使用以下代码,您是否试图将其专门化?

template <>
static std::string string_to_T(std::string const &val)
{
    return val;
}

如果是这种情况,则需要在类之外定义显式专门化,如错误所示(explicit specialization in non-namespace scope):

template <>
std::string Convert::string_to_T<std::string>(std::string const &val)
{
    return val;
}

此外,在Convert中使用它之前需要exitWithError,或者前向声明它,因为在Convert中使用它时编译器还没有看到它。将其移动到Convert:的定义之前

void exitWithError(const std::string &error) 
{
std::cout << error;
std::cin.ignore();
std::cin.get();
exit(EXIT_FAILURE);
}
// Or just forward declare void exitWithError(const std::string &);
class Convert
{ ....

相关内容

  • 没有找到相关文章

最新更新