C++ / Boost: написание более мощной замены sscanf
Я хочу написать функцию на C++ для замены sscanf C, которая назначает совпадения итератору.
в принципе, я хочу что-то вроде:
string s = "0.5 6 hello";
std::vector<boost::any> any_vector;
sscanv(s, "%f %i %s", any_vector);
cout << "float: " << any_cast<float>(any_vector[0]);
cout << "integer: " << any_cast<integer(any_vector[1]);
cout << "string: " << any_cast<string>(any_vector[2]);
точные детали могут отличаться, но вы получаете идею. Есть идеи для реализации?
параметры до сих пор вместе с проблемами до сих пор:
- std:: istringstream: нет манипулятора для сопоставления постоянных выражений
- импульс.Regex: не уверен, что это сработает, и это кажется намного сложнее, чем необходимо для этого
- импульс.Дух!--12-->: не думаю, что это будет работать для динамически создаваемых строк формата, и это также кажется более сложным, то надо
- использования sscanf: это будет работать, но нестандартно и т. д., и использование его потребует много накладных расходов, так как количество аргументов определяется во время компиляции
2 ответов
что это?
void sscanf(std::string str,
const std::string& format,
std::vector<boost::any>& result)
{
std::string::const_iterator i = format.begin();
while (i != format.end())
{
if (*i == '%')
{
++i; // now *i is the conversion specifier
char specifier = *i;
++i; // now *i is the next seperator
std::string extract = str.substr(0, str.find(*i));
switch (specifier)
{
// matching an integer
case 'i':
result.push_back(boost::lexical_cast<int>(extract));
break;
// matching a floating point number
case 'a': case 'e': case 'f': case 'g':
result.push_back(boost::lexical_cast<float>(extract));
break;
// matching a single character
case 'c':
result.push_back(boost::lexical_cast<char>(extract));
break;
// matching a string
case 's':
result.push_back(extract);
break;
// Invalid conversion specifier, throwing an exception
default:
throw std::runtime_error("invalid conversion specifier");
break;
}
}
else
{
// if it's not a %, eat!
str.erase(0, str.find(*i)+1);
++i;
}
}
}
некоторые спецификаторы преобразований отсутствуют – но в основном это работает.
Если ваша строка формата определена во время компиляции, есть некоторые variadic-шаблон printf замена. Инвертирование должно работать достаточно хорошо.
затем вы можете использовать оператор istream >> для чтения или функции c-stdlib.