2

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

4

3 回答 3

2

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

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

void foo(...);

后来你可以使用这些宏和类型,虽然如果你使用 C++,你应该使用 C++11 的可变参数模板而不是 C 可变参数函数,因为可变参数模板是类型安全的 - 你不会在任何地方丢失类型信息,并且通用引用(但不太感谢它们)它们比可变参数函数更强大。

于 2013-01-16T18:52:03.063 回答
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;
}
于 2013-01-16T19:02:03.643 回答
1

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

于 2013-01-17T16:01:46.783 回答