免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 20272 | 回复: 39
打印 上一主题 下一主题

[C++] 考考大家对C++输出流的熟悉程度(附录:google c++编程风格指南、c++解答) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-02-09 00:55 |只看该作者 |倒序浏览
写出和下面C代码相同功能的C++代码
要求:
1、不查阅参考手册(很基本的格式化输出而已)
2、使用cout对象

  1. #include <stdio.h>

  2. int main()
  3. {
  4.     int i;
  5.     float f;

  6.     for (i = 0; i < 4; i++)
  7.         printf("%4d|", i);
  8.     printf("\n");

  9.     for (i = 0; i < 4; i++)
  10.         printf("%-4d|", i);
  11.     printf("\n");

  12.     for (i = 0; i < 4; i++)
  13.         printf("%04d|", i);
  14.     printf("\n");

  15.     printf("\n");
  16.     f = 3.14;

  17.     for (i = 0; i < 4; i++)
  18.         printf("%.4f|", f);
  19.     printf("\n");

  20.     for (i = 0; i < 4; i++)
  21.         printf("%8.4f|", f);
  22.     printf("\n");

  23.     for (i = 0; i < 4; i++)
  24.         printf("%8.4-f|", f);
  25.     printf("\n");
  26.     return 0;
  27. }
复制代码


感谢tyc给出的相同功能的c++版本:
PS:看了tyc的解答后,我就感到后悔了,应该这么出的:

  1. printf("%04d, %8.3f", 123,  3.14);
复制代码

一定会让使用cout的人吐血的,呵呵。


  1. #include <iostream>
  2. #include <iomanip>
  3. using namespace std;

  4. int main()
  5. {
  6.     for (int i = 0; i < 4; ++i)
  7.         cout << setw(4) << i << '|';
  8.     cout << '\n';

  9.     cout << left;
  10.     for (int i = 0; i < 4; ++i)
  11.         cout << setw(4) << i << '|';
  12.     cout << '\n';
  13.     cout << right;

  14.     cout << setfill('0');
  15.     for (int i = 0; i < 4; ++i)
  16.         cout << setw(4) << i << '|';
  17.     cout << '\n';
  18.     cout << setfill(' ');

  19.     cout << '\n';

  20.     const float f = 3.14f;

  21.     cout << fixed;

  22.     cout << setprecision(4);
  23.     for (int i = 0; i < 4; ++i)
  24.         cout << f << '|';
  25.     cout << '\n';

  26.     for (int i = 0; i < 4; ++i)
  27.         cout << setw(8) << f << '|';
  28.     cout << '\n';

  29.     cout << left;
  30.     for (int i = 0; i < 4; ++i)
  31.         cout << setw(8) << f << '|';
  32.     cout << '\n';
  33.     cout << right;

  34.     cout.unsetf(ios_base::floatfield);
  35. }
复制代码


程序输出:


附录:google c++编程风格指南
流(Streams):只在记录日志时使用流。
  
定义
流是printf()和scanf()的替代。

优点
有了流,在输出时不需要关心对象的类型,不用担心格式化字符串与参数列表不匹配(虽然在gcc中使用printf也不存在这个问题),打开、关闭对应文件时,流可以自动构造、析构。

缺点
流使得pread()等功能函数很难执行,如果不使用printf之类的函数而是使用流很难对格式进行操作(尤其是常用的格式字符串%.*s),流不支持字符串操作符重新定序(%1s),而这一点对国际化很有用。

结论
不要使用流,除非是日志接口需要,使用printf之类的代替。使用流还有很多利弊,代码一致性胜过一切,不要在代码中使用流。

拓展讨论
对这一条规则存在一些争论,这儿给出深层次原因。回忆唯一性原则(Only One Way):我们希望在任何时候都只使用一种确定的I/O类型,使代码在所有I/O处保持一致。因此,我们不希望用户来决定是使用流还是printf + read/write,我们应该决定到底用哪一种方式。把日志作为例外是因为流非常适合这么做,也有一定的历史原因。

使用流易造成的错误
流的支持者们主张流是不二之选,但观点并不是那么清晰有力,他们所指出流的所有优势也正是其劣势所在。流最大的优势是在输出时不需要关心输出对象的类型,这是一个亮点,也是一个不足:很容易用错类型,而编译器不会报警。使用流时容易造成的一类错误是:

  1. cout << this; // Prints the address
  2. cout << *this; // Prints the contents
复制代码

编译器不会报错,因为<<被重载,就因为这一点我们反对使用操作符重载。

可读性比较
有人说printf的格式化丑陋不堪、易读性差,但流也好不到哪儿去。看看下面两段代码吧,哪个更加易读?

  1. cerr << "Error connecting to '" << foo->bar()->hostname.first
  2. << ":" << foo->bar()->hostname.second << ": " << strerror(errno);
复制代码

  1. fprintf(stderr, "Error connecting to '%s:%u: %s",
  2. foo->bar()->hostname.first, foo->bar()->hostname.second, strerror(errno));
复制代码

你可能会说,“把流封装一下就会比较好了”,这儿可以,其他地方呢?而且不要忘了,我们的目标是使语言尽可能小,而不是添加一些别人需要学习的新的内容。

总结
每一种方式都是各有利弊,“没有最好,只有更好”,简单化的教条告诫我们必须从中选择其一,最后的多数决定是printf + read/write。

[ 本帖最后由 CRLF 于 2009-2-9 20:39 编辑 ]
单选投票, 共有 554 人参与投票
0.00% (0)
37.93% (11)
62.07% (18)
您所在的用户组没有投票权限

论坛徽章:
0
2 [报告]
发表于 2009-02-09 00:57 |只看该作者
如果有人熟悉C++的格式化输出,请把相同功能的c++也贴出来吧(谢谢),我刚学c++不久,还不是很了解。

论坛徽章:
0
3 [报告]
发表于 2009-02-09 01:02 |只看该作者

只能吐了

踏实点吧

论坛徽章:
0
4 [报告]
发表于 2009-02-09 01:12 |只看该作者
另外,还想请教一个问题:
endl的申明是什么样子的?书上讲endl是一个函数(可以用来flush),那么endl是这个函数的名字吗?如果是的化,cout是怎么调用这个函数的?

在下面的代码段中,我希望能test函数能够像endl那样被调用,怎样才能做到?

  1. void test()
  2. {
  3.        printf("test is called");
  4. }

  5. int main()
  6. {
  7.       cout << test;
  8. }
  9. 程序输出是:1
复制代码

论坛徽章:
0
5 [报告]
发表于 2009-02-09 01:13 |只看该作者
原帖由 mik 于 2009-2-9 01:02 发表

只能吐了

踏实点吧

老大什么意思?

论坛徽章:
0
6 [报告]
发表于 2009-02-09 01:17 |只看该作者
除非你真的能在不参考c++手册下轻松的完成顶楼的格式化任务,否则我觉得你是在吹牛!

论坛徽章:
0
7 [报告]
发表于 2009-02-09 01:20 |只看该作者
我给你15分钟吧,现在是北京时间2月9日01:20分,你要是有兴趣的化,你不妨做下,然后把代码贴出来,否则就别装大了。

论坛徽章:
0
8 [报告]
发表于 2009-02-09 02:00 |只看该作者
原帖由 CRLF 于 2009-2-9 01:17 发表
除非你真的能在不参考c++手册下轻松的完成顶楼的格式化任务,否则我觉得你是在吹牛!

我是不会用。。
不过,记得某牛人说,某种语言或库里有一样东西,让大家觉得很难用,
这就是语言或库的一个设计BUG。

我把的C++格式化选项是视为设计BUG的。

论坛徽章:
0
9 [报告]
发表于 2009-02-09 02:09 |只看该作者
原帖由 die 于 2009-2-9 02:00 发表

我是不会用。。
不过,记得某牛人说,某种语言或库里有一样东西,让大家觉得很难用,
这就是语言或库的一个设计BUG。

我把的C++格式化选项是视为设计BUG的。


我把C的格式化选项也视为设计BUG的。

论坛徽章:
1
天蝎座
日期:2013-08-25 10:27:22
10 [报告]
发表于 2009-02-09 08:57 |只看该作者
挂羊头卖狗肉
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP