Как я уже сказал в своем ответе, parse_printf_format создан не для того, что вам нужно. Вы можете разобрать его самостоятельно, с помощью этого алгоритма:
- Поскольку символ после
%
либо модификатор или типа (не может быть одновременно), вы первый поиск %
полукокса в строке
- Если следующий символ является в массиве типов ('d', 's', 'f', 'g', 'u' и т. д.), тогда вы получаете класс типа (указатель, int, unsigned, double и т. д. ..). Этого может быть достаточно для того, что вам нужно.
- Если нет, то вы продолжаете следующий символ, пока не найдете один символ, который не допускается в массиве модификатора/типа.
- Если класса для этого типа недостаточно для ваших нужд, вам нужно будет вернуться к модификатору, чтобы настроить конечный тип.
Вы можете использовать множество реализаций для подлинного алгоритма (например boost), но так как вам не нужно, чтобы проверить строку ввода, это очень просто сделать вручную.
псевдокод:
const char flags[] = {'-', '+', '0', ' ', '#'};
const char widthPrec[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '*'}; // Last char is an extension
const char modifiers[] = { 'h', 'l', 'L', 'z', 'j', 't' };
const char types[] = { '%', 'd', 'i', 'u', 'f', 'F', 'e', 'E', 'g', 'G', 'x', 'X', 'a', 'A', 'o', 's', 'c', 'p', 'n' }; // Last one is not wanted too
const char validChars[] = { union of all arrays above };
enum Type { None = 0, Int, Unsigned, Float, etc... };
Type typesToType[] = { None, Int, Int, Unsigned, Float, Float, ... etc... }; // Should match the types array above
// Expect a valid format, not validation is done
bool findTypesInFormat(string & format, vector<Type> types)
{
size_t pos = 0;
types.clear();
while (pos < format.length())
{
pos = format.find_first_of('%', pos);
if (pos == format.npos) break;
pos++;
if (format[pos] == '%') continue;
size_t acceptUntilType = format.find_first_not_of(validChars, pos);
if (pos == format.npos) pos = format.length();
pos --;
if (!inArray(types, format[pos])) return false; // Invalid string if the type is not what we support
Type type = typesToType[indexInArray(types, format[pos])];
// We now know the type, we might need to refine it
if (inArray(modifiers, format[pos-1])
{
type = adjustTypeFromModifier(format[pos-1], type);
}
types.push_back(type);
pos++;
}
return true;
}
// inArray, indexInArray and adjustTypeFromModifier are simple functions left to be written.
Это, кажется, очень легко сделать вручную. Помните, однако, что нет никакого сопоставления 1: 1 между символом и типом, потому что, например, float повышается до double при передаче через va_args или /, и вы можете печатать float через «% g» или «% f» или «% a »и т. д. Это также зависит от платформы, на которой вы находитесь (% I64d для Windows, но% lld для linux) – xryl669
@ xryl669 Спасибо за комментарий. Я нахожусь в Linux и не забочусь о поддержке любой другой платформы. Когда вы говорите, что это легко сделать вручную, вы предлагаете анализировать строковый символ по символу без использования таких функций, как parse_printf_format()? – dshin
Можете ли вы уточнить свою потребность в использовании для этой информации немного? Есть шанс, что может быть гораздо лучший подход, чем синтаксический анализ строк printf. –