荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Second (石开), 信区: Program
标  题: C++语言常见问题解答(1-8) 输入/输出: 和
发信站: 荔园晨风BBS站 (Wed Sep 19 12:07:06 2001), 转信

====================================================
■□ 第8节:输入/输出: 和
====================================================

Q28:该怎样替 "class Fred" 提供输出功能?

用夥伴函数 operator<<:

        class Fred {
        public:
          friend ostream& operator<< (ostream& o, const Fred
& fred)
            { return o << fred.i; }
          //...
        private:
          int i;    //只为了说明起见而设的
        };

我们用夥伴而不用成员函数,因为 "Fred" 是第二个参数而非第一个。输入的功能亦

类似,只是要改写成:

        istream& operator>> (istream& i, Fred& fred);

// ^^^^^------- 不是 "const Fred& fred"!

========================================

Q29:为什麽我该用  而不是以前的 ?

增加型别安全、减少错误、增进效率、有延展性、提供衍生能力。

Printf 还好,而 scanf 除了容易写错之外也还算可以,然而和 C++ 的 I/O 系
统相
比,它们都有其限制。C++ 的 I/O(用 "<<" 及 ">>" ),和 C( "printf()
" 和
"scanf()" )相比:

 * 型别安全--要做 I/O 的物件,编译器会静态地事先得知其型别,而不是动态

   由 "%" 一栏查知。

 * 不易出错--冗馀的资讯会增加错误的机会。C++ 的 I/O 就不需要多馀的 "
%"。

 * 更快速--printf 是个小型语言的「解译器」,该语言主要是由 "%" 这种东
西
   构成的;在执行期它用这些栏位来选择正确的格式化方式。C++ 的 I/O 系统
则是
   静态的依各引数真正的型别来挑选副程式,以增进执行效率。

 * 延展性--C++ I/O 机制可在不改动原有程式码的情况下,就加进使用者新设计

   的型态(能想像如果大家同时把互不相容的 "%" 栏位塞入 printf 和 sca
nf,会
   是怎样的混乱场面?!)。

 * 可衍生(subclassable)--ostream 和 istream(C++ 的 FILE* 代替品)
都是
   真正的类别,因此可以被衍生下去。这意味著:你可以让其他自定的东西有著和

   stream 雷同的外表与行为,但实际上做的却是你想做的特定事情。你自动就重

   了数以万计别人(你甚至不认识它们)写好的 I/O 程式码,而他们也不需要知

   你所做的「延伸 stream」类别。

========================================

Q30:为什麽我处理输入时,会超过档案的结尾?

因为 eof(档案结尾)的状态,是到「将要超过档案结尾的动作」才会被设定。也就

是说,读档案的最後一个位元组并不会设定 eof 的状态。

【译注】这也是 C 常见的错误。

如果你的程式像这样:

        int i = 0;
        while (! cin.eof())  {
          cin >> x;
          ++i;
          // work with x
        }

你的 i 变数就会多了一。
你真正该做的是这样:

        int i;
        while (cin >> x)  {
          ++i;
          // work with x
        }

========================================

Q31:为什麽我的程式执行完第一次回圈後,会对输入的要求不加理睬?

因为读取数值的程式,把非数字的字元留在输入缓冲区 (input buffer) 里头了。


【译注】这也是 C,甚至 Pascal 常见的错误。

如果你的程式如下:

        char name[1000];
        int age;

        for (;;) {
          cout << "Name: ";
          cin >> name;
          cout << "Age: ";
          cin >> age;
        }

你应该这样写:

        for (;;) {
          cout << "Name: ";
          cin >> name;
          cout << "Age: ";
          cin >> age;
          cin.ignore(INT_MAX, '\n');
        }

========================================

Q32:在 DOS 及 OS/2 的 binary 模式下,要怎样来 "reopen" cin 及 cou
t?

有这个问题,最典型的情况就是:有人想对 cin、cout 做 binary 的 I/O,但是

业系统(像是 DOS 或 OS/2)却总是会做 CR-LF 的转换动作。

解决法:cin、cout、cerr 这些事先定义好的串流,都是 text 的串流,没有标准做

法能把它们弄成 binary 模式。把串流关掉再设法以 binary 模式 reopen 它们
,可
能会导致不可预期的结果。

在这两种模式有不同行为的系统上,一定有办法让它们变成 binary 串流,但是你得

去查查该系统的文件。


--
                            既然热爱生命
                            那么,
                            一切都在意料之中。

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.52.239]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店