Возможно, вы захотите взглянуть на Boost.String . Это простая коллекция алгоритмов для работы с потоками, в частности функции trim
методы:)
Теперь перейдем к самому обзору:
Не беспокойтесь об удалении венгерской нотации, если это ваш стиль, тогда используйте ее, однако вы должны попытаться улучшить имена методов и переменных. processXXX
определенно ничего не значит полезного ...
Функционально меня беспокоят ваши предположения: главная проблема здесь в том, что вам не нужны последовательности пробелов (\n
использует, например, обратную косую черту), и вы не беспокоитесь о наличии строк символов: std::cout << "Process #" << pid << std::endl;
приведет к неверной строке из-за вашей предварительной обработки "комментария"
Кроме того, поскольку вы удаляете комментарии перед обработкой экранирования новой строки:
i = 3; # comment \
running comment
будет проанализирован как
i = 3; running comment
, что синтаксически неверно.
С точки зрения интерфейса: нет необходимости иметь здесь методы, являющиеся членами класса, вам не нужен экземпляр RecipeReader
на самом деле ...
И, наконец, мне неловко, когда два потока читают из потока.
Моя маленькая мозоль: возвращение на const
значение не служит никакой цели.
Вот моя собственная версия, так как я считаю, что показывать легче, чем обсуждать:
// header file
std::vector<std::string> readRecipe(const std::string& fileName);
std::string extractLine(std::ifstream& file);
std::pair<std:string,bool> removeNewlineEscape(const std::string& line);
std::string removeComment(const std::string& line);
// source file
#include <boost/algorithm/string.hpp>
std::vector<std::string> readRecipe(const std::string& fileName)
{
std::vector<std::string> result;
ifstream file(fileName.c_str());
if (!file) std::cout << "Could not open: " << fileName << std::endl;
std::string line = extractLine(file);
while(!line.empty())
{
result.push_back(line);
line = extractLine(file);
} // looping on the lines
return result;
} // readRecipe
std::string extractLine(std::ifstream& file)
{
std::string line, buffer;
while(getline(file, buffer))
{
std::pair<std::string,bool> r = removeNewlineEscape(buffer);
line += boost::trim_left_copy(r.first); // remove leading whitespace
// based on the current locale
if (!r.second) break;
line += " "; // as we append, we insert a whitespace
// in order unintended token concatenation
}
return removeComment(line);
} // extractLine
//< Returns the line, minus the '\' character
//< if it was the last significant one
//< Returns a boolean indicating whether or not the line continue
//< (true if it's necessary to concatenate with the next line)
std::pair<std:string,bool> removeNewlineEscape(const std::string& line)
{
std::pair<std::string,bool> result;
result.second = false;
size_t pos = line.find_last_not_of(" \t");
if (std::string::npos != pos && line[pos] == '\')
{
result.second = true;
--pos; // we don't want to have this '\' character in the string
}
result.first = line.substr(0, pos);
return result;
} // checkNewlineEscape
//< The main difficulty here is NOT to confuse a # inside a string
//< with a # signalling a comment
//< assuming strings are contained within "", let's roll
std::string removeComment(const std::string& line)
{
size_t pos = line.find_first_of("\"#");
while(std::string::npos != pos)
{
if (line[pos] == '"')
{
// We have detected the beginning of a string, we move pos to its end
// beware of the tricky presence of a '\' right before '"'...
pos = line.find_first_of("\"", pos+1);
while (std::string::npos != pos && line[pos-1] == '\')
pos = line.find_first_of("\"", pos+1);
}
else // line[pos] == '#'
{
// We have found the comment marker in a significant position
break;
}
pos = line.find_first_of("\"#", pos+1);
} // looking for comment marker
return line.substr(0, pos);
} // removeComment
Это довольно неэффективно (но я доверяю компилятору для оптимизации), но я считаю, что он ведет себя правильно, хотя и не тестировался, поэтому возьмите его с крошкой соли. Я сосредоточился в основном на решении функциональных проблем, соглашение об именах, которому я следую, отличается от вашего, но я не думаю, что это должно иметь значение.