如何确定实现fprint格式化字符串需要多少个参数?

时间:2013-01-16 18:46:58

标签: c++ c arguments printf

我指的是像"(%d%%%d) some text %s , %d%% %x %o %#x %#o \n"这样的字符串。 printf系列函数以某种方式知道它们需要从这个字符串中需要多少个args,因此不需要单独的参数。这个功能是用单独的函数在c / c ++中提供的,所以我可以编写自己的类似printf的函数吗? (是的,我故意将这些百分比用于强调它有多复杂,所以不是简单地计算字符百分比)

3 个答案:

答案 0 :(得分:2)

printf系列的问题在于它不安全,并且它确实知道或关心字符串或参数列表中有多少格式元素。

printf家庭使用名为"变量函数&#34 ;;只有一个参数被命名(格式字符串)而其他参数是从堆栈中获取的,不考虑它们的类型或大小 - 它们的类型是从格式字符串中推导出来的,这使得它类型不安全,并通过迭代来查找要使用的参数数量。字符串并查找所有格式说明符,这使得参数号不安全。你可以编写可变函数;语法是

void foo(...);

以后你可以使用those macros and types,虽然如果你使用C ++,你应该使用C ++ 11的可变参数模板而不是C变量函数,因为可变参数模板是类型安全的 - 你不要&# 39; t在任何地方放松类型信息,并且universal references(但不完全感谢他们)它们比可变函数更强大。

答案 1 :(得分:1)

printf系列函数只知道一个参数,第一个参数......

它基本上扫描字符串,每次遇到它理解的格式说明符,然后从参数列表中拉出那个大小的下一个参数......这是一个容易腐败的行为。 想象:

printf("%i",someInt); // fine
printf("%i",someLong); // depending on endianness and sized
                       // of those types could be the high or low 32 bits(probably)
printf("%i %i",someInt); // depending on abi could crash, read a int sized chunk
                         // of stack, or a register that would correspond to that 
                         // parameter.

因此本身就不安全..
你应该注意警告,并在编写可移植代码时执行以下操作:

size_t t = 5; //can be 32 or 64 bit depending on arch.
printf("%ull",(unsigned long long)t);

编辑。我想我只有一半回答了这个问题...... 您可以定义自己的可变参数函数,下面添加count个参数并返回结果。

int sumList(int count, ...);
int main(int argc, const char * argv[])
{   
    printf("the answer is: %i",sumList(4,1,2,3,4));
    return 0;
}
int sumList(int count, ...)
{
    va_list args;
    va_start(args, count);
    int sum = 0;
    for (int i = 0; i<count; i++) {
        sum += va_arg(args, int);
    }
    va_end(args);
    return sum;
}

答案 2 :(得分:1)

不,没有用于解析printf样式格式字符串的标准库函数。如果你想编写自己的字符串格式化函数,那么我强烈建议不要遵循printf示例。由于其他答案中提到的原因,它本质上是不安全的。由于某些语言中的词序变化,它也存在本地化问题。就个人而言,我会使用模板编写一个类型安全的函数,并复制.NET格式的字符串。 (实际上,我做了这样做 - 这是很多工作但也很有趣。)