printf与std :: cout

时间:2011-01-24 12:13:57

标签: c++ printf cout

  

可能重复:
  Should I use printf in my C++ code?

如果我只是想在屏幕上打印string,我可以使用这两种方式来做到这一点:

printf("abc");

std::cout << "abc" << std::endl;

案例是,并且在上面显示的示例中,使用printf优于std::cout,反之亦然?

7 个答案:

答案 0 :(得分:31)

虽然cout是正确的C ++方式,但我相信有些人和公司(包括Google)继续在C ++代码中使用printf,因为格式化输出更容易使用printf而不是cout

这是一个有趣的例子,我找到了here

比较:

printf( "%-20s %-20s %5s\n" , "Name" , "Surname" , "Id" );

cout << setw( -20 ) << "Name" << setw( 20 ) << "Surname"  << setw( 5 ) << "Id" << endl;

答案 1 :(得分:16)

printf及其相关朋友是C函数。它们在C ++中工作,但没有C ++ std::ostreams的类型安全性。在使用printf函数根据用户输入(甚至从文件输入)格式化输出的程序中可能会出现问题。例如:

int main()
{
    char[] a = {'1', '2', '3', '4'}; // a string that isn't 0-terminated
    int i = 50;
    printf("%s", a); // will continue printing characters until a 0 is found in memory
    printf("%s", i); // will attempt to print a string, but this is actually an integer
}

C ++具有更强大的类型安全性(以及std::string类)来帮助防止出现类似这样的问题。

答案 2 :(得分:2)

实际上,对于您的特定示例,您应该询问哪个更好,放置或者cout。 printf打印格式化文本,但您只是将纯文本输出到控制台。

对于一般用途,流(iostream,其中cout是其中的一部分)更具可扩展性(您可以使用它们打印自己的类型),并且更通用,因为您可以生成要打印到任何类型的流的函数,不只是控制台(或重定向输出)。您也可以使用fprintf使用printf创建通用流行为,它将FILE *作为FILE *通常不是真正的文件,但这更棘手。

Streams是“类型安全”,因为您要打印的类型会重载。 printf使用省略号不是类型安全的,所以如果你把错误的参数类型放在与格式字符串不匹配的情况下你可能得到未定义的结果,但编译器不会抱怨。你可能甚至会得到一个seg-fault / undefined行为(如果你错误地使用cout就可以使用cout)如果你错过了一个参数或传入一个错误的参数(例如%s的数字并且它无论如何都将它视为指针)。 / p>

printf确实有一些优点:你可以模板化一个格式字符串,然后将该格式字符串重用于不同的数据,即使该数据不在结构中,并且对一个变量使用格式化操作也不会“粘贴”该格式进一步使用,因为您指定了每个变量的格式。 printf也被称为线程安全,而cout实际上不是。

boost将各自的优势与boost :: format库相结合。

答案 3 :(得分:2)

我自己也在努力解决这个问题。 printf通常更容易用于格式化打印,但C ++中的iostreams工具具有可以为对象创建自定义格式化程序的巨大优势。我必须在我的代码中使用它们。

使用和混合它们的问题是printf和cout使用的输出缓冲区不一样,所以除非你运行无缓冲或显式刷新输出,否则最终会导致输出损坏。

我对C ++的主要反对意见是没有类似于printf的快速输出格式化工具,因此无法轻松控制整数,十六进制和浮点格式的输出。

Java有同样的问题;语言最终得到了printf。

维基百科在http://en.wikipedia.org/wiki/Printf#C.2B.2B_alternatives_to_sprintf_for_numeric_conversion处对此问题进行了很好的讨论。

答案 4 :(得分:2)

{C}借用了printf并有一些限制。 printf最常见的限制是类型安全,因为它依赖于程序员将格式字符串与参数正确匹配。来自varargs环境的第二个限制是您无法使用用户定义的类型扩展行为。 printf知道如何打印一组类型,这就是你将从中获得的所有内容。尽管如此,它可以用于少数事情,使用printf格式化字符串比使用c ++流更快更简单。

虽然大多数现代编译器能够解决类型安全限制并且至少提供警告(编译器可以解析格式字符串并检查调用中提供的参数),但是第二个限制是无法克服的。即使在第一种情况下,编译器也无法真正帮助,因为检查空终止 - 但是如果使用它来打印相同的数组,那么std::cout也会出现同样的问题。

另一方面,对于任何给定的用户定义类型std::cout,可以通过重载std::ostream& operator<<( std::ostream&, type const & )扩展流(包括type)以处理用户定义的类型。它们本身是类型安全的 - 如果传入一个没有重载operator<<的类型,编译器会抱怨它。另一方面,它们产生格式化输出更麻烦。

那么你应该用什么?一般来说,我更喜欢使用流,因为我自己的类型的重载operator<<很简单,它们可以统一使用所有类型。

答案 5 :(得分:1)

这两个例子做了不同的事情。后者将添加换行符和flush输出(std::endl的结果)。 std::cout也比较慢。除此之外,printfstd::cout可以实现相同的目标,您可以根据自己的喜好选择。作为优先选择,我在C ++代码中使用std::cout。它更具可读性和安全性。

如果您需要使用std::cout格式化输出,请参阅this article

答案 6 :(得分:0)

一般来说,你应该更喜欢cout,因为它更安全,更通用。 printf不是类型安全的,也不是通用的。你可能喜欢printf的唯一原因是速度 - 来自内存,printf比cout快很多倍。