printf暂时还不可替代!

JoeRen 2003-09-18 02:13:22
STL的目标之一就是用cout/cin代替printf/scanf。
用scanf输入确实不好,现在估计也没什么人在新的项目里面使用。
而printf虽然有很多缺点,但很多时候是无法替代的。

printf是一个参数个数可变的函数,无法做到类型安全,也无法扩充以支持更多的数据类型。这些是它的主要缺点。
但是它有两个优点,是其STL竞争对手无法做到的。
第一条是表示与代码分离。在printf中,格式字符串是相对独立的,你可以保存一个格式字符串,然后在多种场合下使用。也可以将格式字符串作为参数传递,以便同一个函数可以用不同的格式显示相同的数据。这点,cout无法做到。使用cout的时候,输出格式的表示跟代码紧密地耦合在一起,使用printf时我们得到的灵活性就这样失去了。
第二条是操作的原子性。只要printf函数的内部实现是线程安全的(这点可以轻易做到,只要printf先将输出字符串构造好才一次性输出),我们就可以保证printf操作的原子性(即,一个线程的输出不会被别的线程打断)。使用cout时,由于
cout<<"Hello I am "<<ThreadName<<endl;
这样最简单的输出都要被编译器理解成多个函数调用,而cout又是一个全局对象,这样就很容易被打断而出现类似于这样的输出:
Hello I am Hello I am Thread1 Thread2
鉴于此,我认为cout代替不了printf。
据说boost有Format对象,可能对此问题有帮助,那位朋友对此有了解,请赐教!
...全文
117 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
JoeRen 2003-09-21
  • 打赏
  • 举报
回复
boost中引入的面向对象的格式串有点像C#或java中的对应物:
"I like %1%,%2% and hate %3%,%1% is perfect!"
我相信,即使对于初学者,这样的格式也非常直观。

To lile2002(弯月):
“C++的new/delete就基本上取代了malloc/free”指的是这样一个事实:
当你编写一个新的程序,引入了一些类之后,发现需要对这些类进行动态分配的时候,你的首选将是new/delete。只有当需要跟现有代码交互,需要产生一个无类型指针(而且效率非常重要,不能间接通过new char[]转换),或者希望跳过构造函数,这样的特殊情况下采油必要考虑malloc/free。
JoeRen 2003-09-19
  • 打赏
  • 举报
回复
To liao2001(知之为知之,不知为不知。。。)
>iostream那么有优势,为什么还是逃不开系统调用,还是逃不开描述符?
很简单,C/C++不是操作系统,你可以用他实现操作系统,但别人还是需要你提供的系统服务。
>不同的情况下用不同的方式可能会得到不同的好处,没有谁能取代谁的。
我相信scanf是已经完全被取代了。没有哪个用C++开发新项目的人会用问题多多的scanf做输入。其他还有一些例子,如C++的new/delete就基本上取代了malloc/free。当然malloc/free仍在使用,但绝大多数的代码都是用new/delete的。
但是printf单单由于“表示与代码分离”这一条好处,就已经立于不败之地。举个例子,现在很多软件都把有关的格式字符串放在资源文件中。这为汉化(或多语言化)提供莫大的方便。因为现在可以只对EXE进行资源编辑,即可完成汉化。如果采用cout(或者stringstream)的话,这个好处就很难得到了。

看了一下Boost::formater,感觉到它基本上达到了将表示和代码分离的要求,甚至比printf更灵活。因为它可以让同一个参数显示多次。由于它最终以字符串形式输出,所以能够与cout一起实现原子性。
缺点是:它为了和printf兼容,提供了printf风格的格式字符串的支持。但printf风格的格式字符串天生就是难以扩充的。

所以,我产生了自行实现的想法。欢迎各位大侠参与设计:)
cxjddd 2003-09-19
  • 打赏
  • 举报
回复
cout 的一个最大的好处就是易用。%? 这样的对初学者不太友好。
ttlb 2003-09-19
  • 打赏
  • 举报
回复
up
lile2002 2003-09-19
  • 打赏
  • 举报
回复
"如C++的new/delete就基本上取代了malloc/free。"
这是不可能的
很多地方只有malloc/free最有效,最适合
liao2001 2003-09-19
  • 打赏
  • 举报
回复
to JoeRen(地球发动机) :
>>iostream那么有优势,为什么还是逃不开系统调用,还是逃不开描述符?
>很简单,C/C++不是操作系统,你可以用他实现操作系统,但别人还是需要你提供的系统服务。
我想你并没有明白我意思,你看到的书所说的“优势”,前面我已经对行缓冲和流缓冲的处理方式进行了描述,一个线程用流缓冲总的来说会比行缓冲的效率要高,因为它减少了系统调用的花销,我想这或许就是很多书上说的“优势”。至于取代,我还是坚持我的看法,不同的缓冲方式用于不同的地方会收到不同的效果。

>我相信scanf是已经完全被取代了。没有哪个用C++开发新项目的人会用问题多多的scanf做输>入。其他还有一些例子,如C++的new/delete就基本上取代了malloc/free。当然malloc/free>仍在使用,但绝大多数的代码都是用new/delete的。

首先,我既使用c又使用c++,或许c情结的存在,我在c++代码中,继续使用scanf,虽然通常我都不需要输入。至于malloc/free,当然我也不能丢弃。我还会用write/read的来开发项目。。。。。。呵呵,我看来要被时代淘汰了。
其次,你的论点我想进行一下修正,加上c++的范畴,因为c的存在。
JoeRen 2003-09-19
  • 打赏
  • 举报
回复
To sdtea(抗日统一联盟:衣田) :
格式化跟面向对象并不冲突。举例来说,java里面同样有格式化输出的函数。
字符模式编程是编写一些对界面要求不严但需要log输出的程序的一种选择。

即使是图形界面,恐怕sprintf/sscanf依然少不了吧?
sdtea 2003-09-19
  • 打赏
  • 举报
回复
看来大家都在字符模式下编程,我在windows下编程,不用printf/scanf的。
所谓的格式化一定是从结构化编程的角度考虑,我的每一个输出依靠的对象自己的输出,你说的需求还真没有遇到过。
wingfiring 2003-09-19
  • 打赏
  • 举报
回复
iostream是好,但是iostream格式化字符串不方便也是事实。
同样,string也是,根本就没办法简单的格式化字符串。
fishsward 2003-09-18
  • 打赏
  • 举报
回复
总的说来,iostream比printf好,除了Format比较麻烦外

并且很多经典书籍都推荐iostream
liao2001 2003-09-18
  • 打赏
  • 举报
回复
to JoeRen(地球发动机):
c#还在说他们什么什么比c++强呢?能取代吗?
iostream那么有优势,为什么还是逃不开系统调用,还是逃不开描述符?
不同的情况下用不同的方式可能会得到不同的好处,没有谁能取代谁的。
翻开任何一本unix的书,没听过说unix是用c++写的,难道就说明c++。。。
尽信书不如无书!
JoeRen 2003-09-18
  • 打赏
  • 举报
回复
To liao2001(知之为知之,不知为不知。。。)
你翻开任何一本C++编程的书籍,当提到iostream的时候,都会提到与printf的对比(指出printf的不足,和iostream的优势)。这还不能说明iostream是想要取代printf的吗?
cxjddd 2003-09-18
  • 打赏
  • 举报
回复
STL 的目标之一是 cout ?
熊主任 2003-09-18
  • 打赏
  • 举报
回复
0和1应该对应STDOUT和STDERR吧?你把他们都close了,嗨嗨~~
Yssss1980 2003-09-18
  • 打赏
  • 举报
回复
请问什么叫掐断他们?
liao2001 2003-09-18
  • 打赏
  • 举报
回复
一个是针对流的,一个是针对描述符的
一个是流缓冲,一个是行缓冲
有着不同的处理方式,互相之间根本就没有冲突,又何必考虑谁取代谁?
但有一点他们是紧密联系的是,都是操作的描述符0/1,都会系统调用,比如unix中有write,还有。。。
原子性操作是因为流缓冲的处理方式不同于行缓冲,后者是直接系统调用,而系统调用是原子操作,前者是等到缓冲区满或者刷新缓冲区是才会系统调用然后输出,因为系统调用是很费时的.
cout<<"Hello I am "<<ThreadName<<endl;
和 printf("Hello I am ");printf(“%s”,ThreadName);
都会引起同步问题,但同步的地方并不是相同的,一个在缓冲区,一个在系统调用。

“有全局对象的析构函数中调用cout时,cout可能已经析构,导致什么都打不出来“
呵呵,你试试掐断他们的根看看有什么反应:
close(0);close(1);

Yssss1980 2003-09-18
  • 打赏
  • 举报
回复
还有一个不可替代的地方

有全局对象的析构函数中调用cout时,cout可能已经析构,导致什么都打不出来

这时候只好使用printf了


shishiXP 2003-09-18
  • 打赏
  • 举报
回复
应该可以代替吧

我不是太清楚:)
l1ul1u 2003-09-18
  • 打赏
  • 举报
回复
up

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧