FarhanShariff Ответов: 1

Парсер файла получаю сообщение об ошибке


Я пытаюсь создать парсер с возможностью чтения конфигурационных файлов
ошибка явной специализации в не пространстве имен "преобразование классов"

Что я уже пробовал:

#include <iostream>
#include <string>
#include <sstream>
#include <map> //holding the pair of parameter-value
#include <fstream>
#include <stdlib.h>
#include <typeinfo>


void FileNotFound(const std::string &error)
{
	std::cout << error;
	std::cin.get();
	exit(EXIT_FAILURE);
}


class Conversion
{
public:
	template <typename T>
	static std::string Ttostring(T const &val)
	{
		std::ostringstream ostr;
		ostr << val;

		return ostr.str();
	}

	template <typename T>
	static T stringtoT(std::string const &val)
	{
		std::istringstream istr(val);
		T returnVal;
		if (!(istr >> returnVal))
			FileNotFound("Not a valid " + (std::string)typeid(T).name() + " present\n");

		return returnVal;
	}

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


class Parser
{
    private:
	std::map<std::string, std::string> contents;
	std::string filename;

//function itself is a const cannot call any non-const member functions, nor can it change any member variables.
    void Deletecomments(std::string &line) const
	{  //npos is a static member constant value with the greatest possible value for an element of type size_t

		if (line.find(';') != line.npos)
		line.erase(line.find(';'));

	}
//Searches the string for the first character that does not match any of the characters specified in its arguments.
    bool Whitespace(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 Key(std::string &key, size_t const &Pos, const std::string &line) const
	{
		key = line.substr(0, Pos);
		if (key.find('\t') != line.npos || key.find(' ') != line.npos)
			key.erase(key.find_first_of("\t "));
	}
	void Value(std::string &value, size_t const &Pos, const std::string &line) const
	{
		value = line.substr(Pos + 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 Pos = temp.find('=');

		std::string key, value;
		Key(key, Pos, temp);
		Value(value, Pos, temp);

		if (!keyExists(key))
			contents.insert(std::pair<std::string, std::string>(key, value));
		else
			FileNotFound("Can only have unique key names!\n");
	}

    void parse(const std::string &line, size_t const lineNumber)
	{
		if (line.find('=') == line.npos)
			FileNotFound("Cannot find separator " + Conversion::Ttostring(lineNumber) + "\n");

		if (!validLine(line))
			FileNotFound("Bad format for line: " + Conversion::Ttostring(lineNumber) + "\n");

		extractContents(line);
	}
    /*
	  Extracting the parameter and values
	*/
	void getfield()
	{
		std::ifstream file;
		file.open(filename.c_str()); //c_str() return the char*
		if (!file)
			FileNotFound("" + filename + " not found!\n");

		std::string line;
		size_t lineNumber = 0; //unsigned integer type
		while (std::getline(file, line))
		{
			lineNumber++;
			std::string temp = line;

			if (temp.empty())
				continue;

			Deletecomments(temp);
			if (Whitespace(temp))
				continue;

			parse(temp, lineNumber);
		}

		file.close();
	}

   public:
	Parser(const std::string &filename)
	{
		this->filename = filename;
		getfield();
	}


	bool keyExists(const std::string &key) const
	{
		return contents.find(key) != contents.end();
	}

	/*function that retrieves the value of a specific key
	 function returns a default value ValueType, if the key couldn't be found or,
	 it will return the Conversion value from string to ValueType
	*/
	template <typename ValueType>
	ValueType getValueOfKey(const std::string &key, ValueType const &defaultValue = ValueType()) const
	{
		if (!keyExists(key))
			return defaultValue;

		return Conversion::stringtoT<ValueType>(contents.find(key)->second);
	}
};

int main()
{
	Parser Par("ParameterFile");

	bool exists = Par.keyExists("Parameter1");
	std::cout << "Parameter1 key: " << std::boolalpha << exists << "\n";
	exists = Par.keyExists("Value1");
	std::cout << "Value1 key: " << exists << "\n";

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

PIEBALDconsult

Другим может быть полезно, если вы укажете, какой компилятор вы используете, и _full_ текст сообщения об ошибке.

FarhanShariff

Я использую блоки кода 13.2

1 Ответов

Рейтинг:
2

bling

Вот три варианта для вас:

Самое простое решение-избавиться от класса преобразования и написать специализированные версии getValueOfKey.

Альтернатива 2: Сделайте преобразование шаблонным классом (вместо класса с шаблонными членами).

template <typename T> class Conversion {

Альтернатива 3: Сделайте преобразование пространством имен.
<pre>namespace Conversion {

Дополнительный комментарий:

Значение, ключевые, пробелы, удалять комментарии, а validLine может быть статическим, а не функции-члены, константные.