⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap05.htm

📁 C++编程思想第二版第二卷
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:C:\TEMP\TicV2\html\TicV2.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:09/26/2001
Translation Time:08:32:23
Translation Platform:Win32
Number of Output files:19
This File:C:\TEMP\TicV2\html\Chap05.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>5: Iostreams</TITLE>
</HEAD>

<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
    [ <a href="README.txt">Viewing Hints</a> ]
    [ <a href="RevisionHistory.htm">Revision History</a> ]
    [ <a href="http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html">Book Home Page</a> ]
    [ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
    [ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/Services">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  Thinking in C++, 2nd edition, Volume 2<br>
  <small>Revision 4.0</small></FONT></H2>
  <H3><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
  by Bruce Eckel &amp; Chuck Allison<br>&copy;2001 MindView, Inc.</FONT></H3>
  
    <FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
     [ <a href="Chap04.htm">Previous Chapter</a> ] 
    
    [ <a href="SimpCont.htm">Short TOC</a> ] 
    [ <a href="Contents.htm">Table of Contents</a> ] 
  
        [ <a href="DocIdx.htm">Index</a> ]
        
     [ <a href="Chap06.htm">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="_Toc305628662"></A><A NAME="_Toc312373873"></A><A NAME="_Toc519041941"></A><A NAME="Heading105"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H1 ALIGN="LEFT">
5: Iostreams</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>There&#8217;s much more you can do
with the general I/O problem than just take standard I/O and turn it into a
class. </FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Wouldn&#8217;t it be nice if you could
make all the usual &#8220;receptacles&#8221; &#8211; standard I/O, files and
even blocks of memory &#8211; look the same, so you need to remember only one
interface? That&#8217;s the idea behind iostreams. They&#8217;re much easier,
safer, and often more efficient than the assorted functions from the Standard C
stdio library.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Iostream is usually the first class
library that new C++ programmers learn to use. This chapter explores the
<I>use</I> of iostreams, so they can replace the C I/O functions through the
rest of the book. In future chapters, you&#8217;ll see how to set up your own
classes so they&#8217;re compatible with
iostreams.</FONT><A NAME="_Toc305628663"></A><A NAME="_Toc312373874"></A><A NAME="_Toc519041942"></A><BR></P></DIV>
<A NAME="Heading106"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Why iostreams?</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You may wonder what&#8217;s wrong with
the good old C library. And why not &#8220;wrap&#8221; the C library in a class
<A NAME="Index170"></A><A NAME="Index171"></A>and be done with it? Indeed, there
are situations when this is the perfect thing to do, when you want to make a C
library a bit safer and easier to use. For example, suppose you want to make
sure a stdio <A NAME="Index172"></A>file is always safely opened and properly
closed, without relying on the user to remember to call the <B>close(&#160;)</B>
function:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C05:FileClass.h</font>
<font color=#009900>// Stdio files wrapped</font>
#ifndef FILECLAS_H
#define FILECLAS_H
#include &lt;cstdio&gt;

<font color=#0000ff>class</font> FileClass {
  std::FILE* f;
<font color=#0000ff>public</font>:
  FileClass(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* fname, <font color=#0000ff>const</font> <font color=#0000ff>char</font>* mode=<font color=#004488>"r"</font>);
  ~FileClass();
  std::FILE* fp();
};
#endif <font color=#009900>// FILECLAS_H ///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In C when you perform file I/O, you work
with a naked pointer to a FILE <A NAME="Index173"></A><B>struct</B>, but this
class wraps around the pointer and guarantees it is properly initialized and
cleaned up using the constructor and destructor. The second constructor argument
is the file mode, which defaults to &#8220;r&#8221; for
&#8220;read.&#8221;</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To fetch the value of the pointer to use
in the file I/O functions, you use the <B>fp(&#160;)</B> access function. Here
are the member function definitions:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C05:FileClass.cpp {O}</font>
<font color=#009900>// Implementation</font>
<font color=#009900>//{-msc}</font>
#include <font color=#004488>"FileClass.h"</font>
#include &lt;cstdlib&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

FileClass::FileClass(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* fname, <font color=#0000ff>const</font> <font color=#0000ff>char</font>* mode){
  f = fopen(fname, mode);
  <font color=#0000ff>if</font>(f == NULL) {
    printf(<font color=#004488>"%s: file not found\n"</font>, fname);
    exit(1);
  }
}

FileClass::~FileClass() { fclose(f); }

FILE* FileClass::fp() { <font color=#0000ff>return</font> f; } <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The constructor calls
<B>fopen(&#160;)</B>,as you would normally do, but it also checks to ensure the
result isn&#8217;t zero, which indicates a failure upon opening the file. If
there&#8217;s a failure, the name of the file is printed and <B>exit(&#160;)</B>
is called.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The destructor closes the file, and the
access function <B>fp(&#160;)</B>returns <B>f</B>. Here&#8217;s a simple example
using <B>class FileClass</B>:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C05:FileClassTest.cpp</font>
<font color=#009900>//{L} FileClass ../TestSuite/Test</font>
<font color=#009900>//{-msc}</font>
<font color=#009900>// Testing class File</font>
#include <font color=#004488>"FileClass.h"</font>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>int</font> main() {
  <font color=#009900>// Opens and tests:</font>
  FileClass f(<font color=#004488>"FileClassTest.cpp"</font>); 
  <font color=#0000ff>const</font> <font color=#0000ff>int</font> bsize = 100;
  <font color=#0000ff>char</font> buf[bsize];
  <font color=#0000ff>while</font>(fgets(buf, bsize, f.fp()))
    puts(buf);
} <font color=#009900>// File automatically closed by destructor</font>
<font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You create the <B>FileClass</B> object
and use it in normal C file I/O function calls by calling <B>fp(&#160;)</B>.
When you&#8217;re done with it, just forget about it, and the file is closed by
the destructor at the end of the
scope.</FONT><A NAME="_Toc312373875"></A><A NAME="_Toc519041943"></A><BR></P></DIV>
<A NAME="Heading107"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
True wrapping</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Even though the FILE pointer is private,
it isn&#8217;t particularly safe because <B>fp(&#160;)</B> retrieves it. The
only effect seems to be guaranteed initialization and cleanup, so why not make
it public, or use a <B>struct</B> instead? Notice that while you can get a copy
of <B>f</B> using <B>fp(&#160;)</B>, you cannot assign to <B>f</B> &#8211;
that&#8217;s completely under the control of the class. Of course, after
capturing the pointer returned by <B>fp(&#160;)</B>, the client programmer can
still assign to the structure elements, so the safety is in guaranteeing a valid
FILE pointer rather than proper contents of the structure.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you want complete safety, you have to
prevent the user from direct access to the FILE pointer. This means some version
of all the normal file I/O functions will have to show up as class members, so
everything you can do with the C approach is available in the C++
class:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C05:Fullwrap.h</font>
<font color=#009900>// Completely hidden file IO</font>
#ifndef FULLWRAP_H
#define FULLWRAP_H

<font color=#0000ff>class</font> File {
  std::FILE* f;
  std::FILE* F(); <font color=#009900>// Produces checked pointer to f</font>
<font color=#0000ff>public</font>:
  File(); <font color=#009900>// Create object but don't open file</font>
  File(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* path,
       <font color=#0000ff>const</font> <font color=#0000ff>char</font>* mode = <font color=#004488>"r"</font>);
  ~File();
  <font color=#0000ff>int</font> open(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* path,
           <font color=#0000ff>const</font> <font color=#0000ff>char</font>* mode = <font color=#004488>"r"</font>);
  <font color=#0000ff>int</font> reopen(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* path,
             <font color=#0000ff>const</font> <font color=#0000ff>char</font>* mode);
  <font color=#0000ff>int</font> getc();
  <font color=#0000ff>int</font> ungetc(<font color=#0000ff>int</font> c);
  <font color=#0000ff>int</font> putc(<font color=#0000ff>int</font> c);
  <font color=#0000ff>int</font> puts(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* s);
  <font color=#0000ff>char</font>* gets(<font color=#0000ff>char</font>* s, <font color=#0000ff>int</font> n);
  <font color=#0000ff>int</font> printf(<font color=#0000ff>const</font> <font color=#0000ff>char</font>* format, ...);
  size_t read(<font color=#0000ff>void</font>* ptr, size_t size,
              size_t n);
  size_t write(<font color=#0000ff>const</font> <font color=#0000ff>void</font>* ptr,
                size_t size, size_t n);
  <font color=#0000ff>int</font> eof();
  <font color=#0000ff>int</font> close();
  <font color=#0000ff>int</font> flush();
  <font color=#0000ff>int</font> seek(<font color=#0000ff>long</font> offset, <font color=#0000ff>int</font> whence);
  <font color=#0000ff>int</font> getpos(fpos_t* pos);
  <font color=#0000ff>int</font> setpos(<font color=#0000ff>const</font> fpos_t* pos);
  <font color=#0000ff>long</font> tell();
  <font color=#0000ff>void</font> rewind();
  <font color=#0000ff>void</font> setbuf(<font color=#0000ff>char</font>* buf);
  <font color=#0000ff>int</font> setvbuf(<font color=#0000ff>char</font>* buf, <font color=#0000ff>int</font> type, size_t sz);
  <font color=#0000ff>int</font> error();
  <font color=#0000ff>void</font> clearErr();
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -