从printf格式字符串中提取类型信息

时间:2015-10-07 16:27:36

标签: c++ printf

我想从printf格式字符串中提取c ++类型信息。例如,

Input: "%10u foo %% %+6.3f %ld %s"

Output:
  unsigned int
  double
  long
  char*

我尝试使用printf.h中的parse_printf_format(),但返回的argtypes似乎不包含有关签名/未签名的信息。

有没有办法获得签名/未签名的信息?

1 个答案:

答案 0 :(得分:1)

正如我在回答中所说,parse_printf_format并不是为了你所需要的。 你可以通过这个算法自己解析它:

  1. 因为%之后的字符是修饰符或类型(不能同时为两者),所以首先在字符串中搜索%字符
  2. 如果下一个字符在类型数组中(' d',' s',' f',' g', ' u'等...然后你得到类型的类(指针,int,unsigned,double等等)。这可能足以满足您的需求。
  3. 如果没有,那么继续下一个字符,直到找到一个在修饰符/类型数组中不允许的字符。
  4. 如果该类型的类型不足以满足您的需要,您必须返回修改器以调整最终类型。
  5. 您可以将许多实现用于正版算法(例如boost),但由于您不需要验证输入字符串,因此手动操作非常简单。< / p>

    伪代码:

    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.