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

📄 chap04.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:22
Translation Platform:Win32
Number of Output files:19
This File:C:\TEMP\TicV2\html\Chap04.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>4: Strings in Depth</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="Part2.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="Chap05.htm">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="_Toc519041924"></A><A NAME="Heading83"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H1 ALIGN="LEFT">
4: Strings in Depth</H1></FONT>
<DIV ALIGN="LEFT"><P><A NAME="fnB8" HREF="#fn8">[8]</A><FONT FACE="Verdana" SIZE=4>One
of the biggest time-wasters in C is character arrays: keeping track of the
difference between static quoted strings and arrays created on the stack and the
heap, and the fact that sometimes you&#8217;re passing around a <B>char*</B> and
sometimes you must copy the whole
array.</FONT><A NAME="StringsChapter"></A><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">(This is the general problem of
<I>shallow copy</I> vs. <I>deep copy</I>.) Especially because string
manipulation is so common, character arrays are a great source of
misunderstandings and bugs.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Despite this, creating string classes
remained a common exercise for beginning C++ programmers for many years. The
Standard C++ library <B>string</B> class solves the problem of character array
manipulation once and for all<B>,</B> keeping track of memory even during
assignments and copy-constructions. You simply don&#8217;t need to think about
it.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This chapter examines the Standard C++
<B>string</B> class, beginning with a look at what constitutes a C++ string and
how the C++ version differs from a traditional C character array.  You&#8217;ll
learn about operations and manipulations using <B>string</B> objects, and see
how C++ <B>string</B>s accommodate variation in character sets and string data
conversion.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Handling text is perhaps one of the
oldest of all programming applications, so it&#8217;s not surprising that the
C++ <B>string</B> draws heavily on the ideas and terminology that have long been
used for this purpose in C and other languages. As you begin to acquaint
yourself with C++ <B>string</B>s this fact should be reassuring, in the respect
that no matter what programming idiom you choose, there are really only about
three things you can do with a <B>string</B>: create or modify the sequence of
characters stored in the <B>string</B>, detect the presence or absence of
elements within the <B>string</B>, and translate between various schemes for
representing <B>string</B> characters.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You&#8217;ll see how each of these jobs
is accomplished using C++ <B>string</B>
objects.</FONT><A NAME="_Toc519041925"></A><BR></P></DIV>
<A NAME="Heading84"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
What&#8217;s in a string</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In C, a string is simply an array of
characters that always includes a binary zero (often called the <I>null
terminator</I>) as its final array element. There are two significant
differences between C++ <B>string</B>s and their C progenitors. First, C++
<B>string</B> objects associate the array of characters which constitute the
<B>string</B> with methods useful for managing and operating on it. A
<B>string</B> also contains certain &#8220;housekeeping&#8221; information about
the size and storage location of its data. Specifically, a C++ <B>string</B>
object knows its starting location in memory, its content, its length in
characters, and the length in characters to which it can grow before the
<B>string</B> object must resize its internal data buffer. This gives rise to
the second big difference between C <B>char</B> arrays and C++ <B>string</B>s.
C++ <B>string</B>s do not include a null terminator, nor do the C++
<B>string</B> handling member functions rely on the existence of a null
terminator to perform their jobs. C++ <B>string</B>s greatly reduce the
likelihood of making three of the most common and destructive C programming
errors: overwriting array bounds, trying to access arrays through uninitialized
or incorrectly valued pointers, and leaving pointers &#8220;dangling&#8221;
after an array ceases to occupy the storage that was once allocated to
it.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The exact implementation of memory layout
for the string class is not defined by the C++ Standard. This architecture is
intended to be flexible enough to allow differing implementations by compiler
vendors, yet guarantee predictable behavior for users. In particular, the exact
conditions under which storage is allocated to hold data for a string object are
not defined. String allocation rules were formulated to allow but not require a
reference-counted implementation, but whether or not the implementation uses
reference counting, the semantics must be the same. To put this a bit
differently, in C, every <B>char</B> array occupies a unique physical region of
memory. In C++, individual <B>string</B> objects may or may not occupy unique
physical regions of memory, but if reference counting is used to avoid storing
duplicate copies of data, the individual objects must look and act as though
they do exclusively own unique regions of storage. For example:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C04:StringStorage.cpp</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;string&gt;
#include &lt;iostream&gt;
#include <font color=#004488>"..</font><font color=#004488>/TestSuite</font><font color=#004488>/Test.h"</font>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> StringStorageTest : <font color=#0000ff>public</font> Test {
<font color=#0000ff>public</font>:
  <font color=#0000ff>void</font> run() {
    string s1(<font color=#004488>"12345"</font>);
    <font color=#009900>// Set the iterator indicate the first element</font>
    string::iterator it = s1.begin();
    <font color=#009900>// This may copy the first to the second or </font>
    <font color=#009900>// use reference counting to simulate a copy </font>
    string s2 = s1;
    test_(s1 == s2);
    <font color=#009900>// Either way, this statement may ONLY modify first</font>
    *it = '0';
    cout &lt;&lt; <font color=#004488>"s1 = "</font> &lt;&lt; s1 &lt;&lt; endl;
    cout &lt;&lt; <font color=#004488>"s2 = "</font> &lt;&lt; s2 &lt;&lt; endl;
    test_(s1 != s2);
  }
};

<font color=#0000ff>int</font> main() {
  StringStorageTest sst;
  sst.setStream(&amp;cout);
  sst.run();
  <font color=#0000ff>return</font> sst.report();
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Reference counting may serve to make an
implementation more memory efficient, but it is transparent to users of the
<B>string</B>
class.</FONT><A NAME="_Toc424692472"></A><A NAME="_Toc519041926"></A><BR></P></DIV>
<A NAME="Heading85"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Creating and initializing C++ strings</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Creating and initializing <B>string</B>s
is a straightforward proposition, and fairly flexible as well. In the example
shown below, the first <B>string</B>, <B>imBlank</B>, is declared but contains
no initial value. Unlike a C <B>char</B> array, which would contain a random and
meaningless bit pattern until initialization, <B>imBlank</B> does contain
meaningful information. This <B>string</B> object has been initialized to hold
&#8220;no characters,&#8221; and can properly report its 0 length and absence of
data elements through the use of class member functions.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The next <B>string</B>, <B>heyMom</B>, is
initialized by the literal argument "Where are my socks?". This form of
initialization uses a quoted character array as a parameter to the <B>string</B>
constructor. By contrast, <B>standardReply</B> is simply initialized with an
assignment. The last <B>string</B> of the group, <B>useThisOneAgain</B>, is
initialized using an existing C++ <B>string</B> object. Put another way, this
example illustrates that <B>string</B> objects let you:</FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Create an empty
<B>string</B> and defer initializing it with character
data.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Initialize a
<B>string</B> by passing a literal, quoted character array as an argument to the
constructor.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Initialize
a <B>string</B> using
&#8216;<B>=</B>&#8217;.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Use
one <B>string</B> to initialize another.</FONT><A NAME="_Toc424692473"></A></UL>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C04:SmallString.cpp</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
<font color=#009900>//{-msc} Execution error</font>
#include &lt;string&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>int</font> main() {
  string imBlank;
  string heyMom(<font color=#004488>"Where are my socks?"</font>);
  string standardReply = <font color=#004488>"Beamed into deep "</font>
    <font color=#004488>"space on wide angle dispersion?"</font>;
  string useThisOneAgain(standardReply);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">These are the simplest forms of
<B>string</B> initialization, but there are other variations which offer more
flexibility and control. You can :</FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Use a portion of either a C
<B>char</B> array or a C++ <B>string</B>.
</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Combine different
sources of initialization data using
<B>operator+</B>.</FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Use
the <B>string</B> object&#8217;s <B>substr(&#160;)</B> member function to create
a substring.</FONT></UL>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C04:SmallString2.cpp</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
<font color=#009900>//{-msc} Execution error</font>
#include &lt;string&gt;
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>int</font> main() {
  string s1
    (<font color=#004488>"What is the sound of one clam napping?"</font>);
  string s2
    (<font color=#004488>"Anything worth doing is worth overdoing."</font>);
  string s3(<font color=#004488>"I saw Elvis in a UFO."</font>);
  <font color=#009900>// Copy the first 8 chars</font>

⌨️ 快捷键说明

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