cout<< "Hello";
printf("%s", "Hello");
两者都用于打印值,它们的语法完全不同。C++中两种方式都有,而C语言只有printf。
char coffee[10], sugar[10], milk[10];
unsigned char mac[6];
/* Initialize those things here. */
FILE * f = fopen("a.txt", "wt");
fprintf(f, "coffee=%s\nsugar=%s\nmilk=%s\nmac=%02X:%02X:%02X:%02X:%02X:%02X\n", coffee, sugar, milk, mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]);
fclose(f);
C++程序:
//Everything else is identical except:
std::ofstream f("a.txt", std::ios::out);
f << "coffee=" << coffee << "\n";
f << "sugar=" << sugar << "\n";
f << "milk=" << milk << "\n";
f << "mac=" << (int)mac[0] << ":"
<< (int)mac[1] << ":"
<< (int)mac[2] << ":"
<< (int)mac[3] << ":"
<< (int)mac[4] << ":"
<< (int)mac[5] << endl;
f.close();
real 0m 8.01s
user 0m 2.37s
sys 0m 5.58s
C++程序:
real 0m 6.07s
user 0m 3.18s
sys 0m 2.84s
C - 2,092 bytes
C++ - 3,272 bytes
结论:在我的特定平台、使用一个非常具体的处理器,运行一个非常具体的Linux内核版本,在编译了一个非常具体版本的GCC的程序中,为了完成一个非常具体的任务,我认为C++方法更适合,因为它运行速度更快,可读性更好。另一方面,C语言提供小的占用空间,但在我看来,这意味着几乎没有什么影响,因为程序大小不是我们关心的问题。
记住,你的情况可能有所不同。
sprintf()
和write()
进行基准测试呢? - Andrew Henle
#include <iostream>
#include <cstdlib>
using namespace std;
class Something
{
public:
Something(int x, int y, int z) : a(x), b(y), c(z) { }
int a;
int b;
int c;
friend ostream& operator<<(ostream&, const Something&);
void print() const { printf("%i, %i, %i\n", a, b, c); }
};
ostream& operator<<(ostream& o, const Something& s)
{
o << s.a << ", " << s.b << ", " << s.c;
return o;
}
int main(void)
{
Something s(3, 2, 1);
// Output with printf
s.print(); // Simple as well, isn't it?
// Output with cout
cout << s << endl;
return 0;
}
以下是关于cout和printf的扩展测试,包括一个对双精度浮点数的测试。如果有人想进行更多的测试(使用Visual Studio 2008,可执行文件的发布版本):
#include <stdio.h>
#include <iostream>
#include <ctime>
class TimedSection {
char const *d_name;
//timespec d_start;
clock_t d_start;
public:
TimedSection(char const *name) :
d_name(name)
{
//clock_gettime(CLOCK_REALTIME, &d_start);
d_start = clock();
}
~TimedSection() {
clock_t end;
//clock_gettime(CLOCK_REALTIME, &end);
end = clock();
double duration = /*1e3 * (end.tv_sec - d_start.tv_sec) +
1e-6 * (end.tv_nsec - d_start.tv_nsec);
*/
(double) (end - d_start) / CLOCKS_PER_SEC;
std::cerr << d_name << '\t' << std::fixed << duration * 1000.0 << " ms\n";
}
};
int main() {
const int iters = 1000000;
char const *text = "01234567890123456789";
{
TimedSection s("cout with only endl");
for (int i = 0; i < iters; ++i)
std::cout << std::endl;
}
{
TimedSection s("cout with only '\\n'");
for (int i = 0; i < iters; ++i)
std::cout << '\n';
}
{
TimedSection s("printf with only '\\n'");
for (int i = 0; i < iters; ++i)
printf("\n");
}
{
TimedSection s("cout with string constant and endl");
for (int i = 0; i < iters; ++i)
std::cout << "01234567890123456789" << std::endl;
}
{
TimedSection s("cout with string constant and '\\n'");
for (int i = 0; i < iters; ++i)
std::cout << "01234567890123456789\n";
}
{
TimedSection s("printf with string constant and '\\n'");
for (int i = 0; i < iters; ++i)
printf("01234567890123456789\n");
}
{
TimedSection s("cout with some stuff and endl");
for (int i = 0; i < iters; ++i)
std::cout << text << "01234567890123456789" << i << std::endl;
}
{
TimedSection s("cout with some stuff and '\\n'");
for (int i = 0; i < iters; ++i)
std::cout << text << "01234567890123456789" << i << '\n';
}
{
TimedSection s("printf with some stuff and '\\n'");
for (int i = 0; i < iters; ++i)
printf("%s01234567890123456789%i\n", text, i);
}
{
TimedSection s("cout with formatted double (width & precision once)");
std::cout << std::fixed << std::scientific << std::right << std::showpoint;
std::cout.width(8);
for (int i = 0; i < iters; ++i)
std::cout << text << 8.315 << i << '\n';
}
{
TimedSection s("cout with formatted double (width & precision on each call)");
std::cout << std::fixed << std::scientific << std::right << std::showpoint;
for (int i = 0; i < iters; ++i)
{ std::cout.width(8);
std::cout.precision(3);
std::cout << text << 8.315 << i << '\n';
}
}
{
TimedSection s("printf with formatted double");
for (int i = 0; i < iters; ++i)
printf("%8.3f%i\n", 8.315, i);
}
}
cout with only endl 6453.000000 ms
cout with only '\n' 125.000000 ms
printf with only '\n' 156.000000 ms
cout with string constant and endl 6937.000000 ms
cout with string constant and '\n' 1391.000000 ms
printf with string constant and '\n' 3391.000000 ms
cout with some stuff and endl 9672.000000 ms
cout with some stuff and '\n' 7296.000000 ms
printf with some stuff and '\n' 12235.000000 ms
cout with formatted double (width & precision once) 7906.000000 ms
cout with formatted double (width & precision on each call) 9141.000000 ms
printf with formatted double 3312.000000 ms
endl
比'\n'
低效那么多? - Nicholas Hamiltonendl
刷新了缓冲区,而 \n
没有刷新,尽管我不确定这是否是明确的原因。 - Caleb Xutemplate <class _Elem, class _Traits> basic_ostream<_Elem, _Traits> &__CLRCALL_OR_CDECL endl(basic_ostream<_Elem, _Traits> &_Ostr) { // insert newline and flush stream _Ostr.put(_Ostr.widen('\n')); _Ostr.flush(); return _Ostr; }
它会插入一个换行符并刷新流。 - avighnaccout << "y = " << 7;
不是原子的。
printf("%s = %d", "y", 7);
是原子的。"% d"
的 iostream 相当之处。cout
不返回任何内容,因为它是一个对象而不是函数。 operator<<
会返回一些内容(通常是其左操作数,但如果存在错误则返回false值)。那么,“原子”的意义是什么意思?在printf
调用中呢? - Keith Thompsonprintf("%s\n",7);
- artless noise%s
是什么? - Abhinav Gauniyalprintf
的%s参数必须具有指向空终止字符串的有效指针。内存范围“7”(一个指针)通常无效;分段错误可能会很幸运。在某些系统上,“7”可能会向控制台打印大量垃圾,您需要花一天时间查看它,然后程序才会停止。换句话说,这是关于printf
的一个坏事情。静态分析工具可以捕获许多这些问题。 - artless noiseprintf
不会进行类型检查,但我从来没有使用过一个编译器不会在使用printf
时警告我类型错误的情况... - CoffeeTableEspressoFoo bar;
...;
printf("%s",bar);
如果Foo重载了好的运算符,或者你编写了一个好的方法,那么可能是可以的。简而言之,对于我来说,printf
和cout
一样可扩展。
我能看到C++流(不仅仅是cout)的技术优势有:
类型安全。(顺便说一下,如果我想打印单个'\n'
,我会使用putchar('\n')
,不会用核弹炸死一只昆虫。)
更容易学习。(没有“复杂”的参数要学习,只需使用<<
和>>
操作符即可)
原生支持std::string
(对于printf
,只有std::string::c_str()
,但对于scanf
呢?)
对于printf
,我认为:
更容易或至少更短(在写入字符方面)的复杂格式。对我来说更易读(我想这是品味问题)。
更好地控制函数的作用(返回写入的字符数,有%n
格式化程序:“未打印任何内容。参数必须是指向已签名整数的指针,其中存储了迄今为止写入的字符数。”(来自printf - C++ Reference)
更好的调试可能性。出于同样的原因作为最后一个参数。
我的个人偏好是printf
(和scanf
)函数,主要是因为我喜欢短行,而且我认为在打印文本时类型问题并不难避免。
我唯一遗憾的是C风格的函数不支持std::string
。我们必须通过char*
才能将其传递给printf
(使用std::string::c_str()
进行读取,但如何编写?)
char*
不会被使用。 - Ben Voigtchar*
存在的位置和存活时间,以及用户定义的隐式转换的危险。 - Marcelo Cantosprintf
是一个函数,而 cout
是一个变量。
printf
是一个函数,但printf()
是一个函数调用 =) - vp_arth