7,361 2,068 150MB
Pages 1268 Page size 252 x 332.16 pts Year 2009
Programming
.t .
r-.
I
Programming Prin ciples and Practi ce Using C++
Bjarne Stroustrup
.'. Addison-Wesley Upper Saddle River, NJ • Boston • Indianapolis • San Francisco New York • Toronto • Montreal • london • Munich • Paris • Madrid
Capetown • Sydney • Tokyo • Singapore • Mexico City
~Ia.ny of the desigll3tions used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where t11O$C design'llions app:ar in this book, and tIu:: publisher was aware of 3 tT"Jdcmark claim. the designations h,l\'e been primed with initial capitalleu",rs or in all capitals.
A complete list o f photo sources and credits appears on pages 1235- 1236. TIte author and publisher have taken care in the preparation of this book, but make no expressed or into plied warranty of any kind and assume no respon!!ibi!iLy for errors or omissions. No liability is ass umed fo r incidental or comcqucntial damages in connection with or arising out of the usc of dte infonnation or prognum contained hcrein.
11lC publili her offcrs excclle nt discoun ts on thi!! book when ordered in quantity for bulk purchases or spccial sales, which may inelude electronic ver!!ions and/or custom C()\"crs and content particular to your busi· ness. training go.~ls. marketing focus. ~nd branding interests. For more info rmation. please: contact: U.S. Corpor~Le and Go\"ernment Sales (800) 382-3419 corpsalcs@pears01!tcchgroup.oont For salcs oULSide the United Statcs, please contact: Im",m:uional Sales imemational@p:arsolled.com Copyright 0 2009 Pearson EdUCllUon , Ill(:. StrouStrup. Bjame. Programming principia and practice using C++ I BjanlC Slroustrup. p. em. Includes bibliographical references and index. ISBN 978-{)'321·54372· 1 (pbk. : alk. paper) I. C++ (Cornputer program language) I. ·litle. Q.A76.73.C l535822008 005. 13'3-dc22 2008032595 All righLS rc:scr"\'ed. Printed in the United States of America. ·n tis pUblication is ]Itutectcd by copyright. and p:nnission mUSt be: obtained from tIte publisher prior to any prohibited reproduction, ~ tor.lge in a mric\'al syst"'m. or transmission in any fOnll or by any mcans. electronic, IlIcchani c.1l, photocopying. recording, or lik",wisc:. For infom13tion rcg-Mding penn.issions. write to : PearKltl Education. Inc.
RighLS and Contracts Departmcnt 50 1 Boylston Strc:ct, Suite 900 Boston. MA 02116 FaJ second) cout « first« " is a lphabetically afte r " «second «'\n ' : )
Here, we used an if-statement, which will be explained in detail in §4.4.1. 1, to se· lect actions based on conditions.
3.5 Assignment and initialization In many ways, me most interesting operator is assignment, represel1led as =. It gives a variable a new value. For example: inta=3:
/I a starts out with the value 3
a: a = 4:
/I a gets the value 4 ("becomes 4")
"' I intb=a;
b
a
=a+5:
=a+7;
3
4
/I b Slarts oul wilh a copy of a's value (that is, 4)
a:
4
b:
4
/I b gets the value a+5 (that is, 9)
a:
4
b:
9
/I a gelS the va lue a+7 (thai is, 11)
a:
11
b:
9
11mt last assignment deserves notice. First or all it clearly shows that = does not
mean equals - clearly, a does n't equal a+7. It means ass ignmelll, that is, to place a new value in a variable. What is done ror a=a+7 is the rollowing: I. First, get the value of a; that's the integer 4.
2. Next, add 7 to that 4, yielding the illlegcr II . 3. Finally, put that II into a.
70
CHAPTE R 3 • OBJECTS , TYPE S, AND VALUES
"Ve can also illustrate assignments using strings:
siring a = "alpha ";
/I a starts oul with the value u alpha ~
a:
a = "bela ";
/I a gets the value " beta ~ (becomes ~ beta" )
a: siring b = a;
b = a+ "gamma n ;
a = a+ "delta";
I alpha I beta
1/ b starts out with a copy of a's value (that is, "bela") a:
bela
b:
bela
II b gets the value a+"gamma" (that is, "bctagamma")
a:
bela
b:
belagamma
/I a gels the value a+"dclta" (that is, "betadclta")
a:
betadelta
b:
betagamma
Above, we usc "starts oU( with" and "geLS" to d istinguish twO similar, but logically distinct, operations: Initialization (giving a variable its initial value) Assignment (giving a variable a new value)
These operations arc so similar lhat C++ allows us to usc the same notat ion (the =) fOT both: inty = 8; )( = 9;
/I initialize y with 8 /I assign 9 to x
string t = " howdy! " ; s = " G'day ";
II assign "G'dayNto s
/I initiali ze I with "howdy!~
However, logically assignment and initialization are d ifferent. You can tcllthe two apart by the type specification (like inl or siring) that always starts an initialization ; an assignment does not have mal. In principle, an initialization always fi nds
3 .5
ASSIGNMENT AND IN ITI ALIZATI ON
the variable empty. On the other hand, an assigmnent (in principle) must clear out the old value from the variable before puuing in the new value. You can think of the variable as a kind of small box and the value as a concTCte thing, such as a coin, that you put into it. Before initialization, the box is empty, but after initialization it always holds a coin so tha t to put a new coin in, you (i.e., the assignment operator) first have to remove the old one ("destroy the old value") a nd you cannot leave the box empty. Things are not quite this literal in the computer's me mory, but it's not a bad way of thinking of what's going on.
3.5.1 An example: delete repeated words Assignment is needed when we want to put a new value into an object. When you think of it, it is obvious that assignment is most useful when you do things many limcs. \lVe need an assignment when we want to do something again with a different value. Let's have a look at a little program that detects adjacent repeated words in a sequence of words. Such code is part of most grammar checkers: inl mainO {
Siring pre vious =" "; II previous word; initial ized to Hnot a word" string c urre nt ; /I currenl word /I read a stream of words while (cin>>eurre nl) { if (previo us == c urre nt) II check if the word is the same as lasl cout « "re peated wo rd : "« curre nt « '\n' ; pre vio us = curre nt; )
This program is not the most helpful since it doesn't tell where the repeated word occurred in the text , but it'U do for now. We will look at this program line by line starting with siring Curre nt;
/I current word
11lis is the string variable into which we inunediatcly read the current (i.e. , most recently read) word using while (cin>>eurre nt) -Ibis ConSlnlct, called a while-st.1.tement, is interesting i.n its own right, and we'Uexami.ne it further in §4.4.2. 1. '11e while says that t.he statement after (cin»curre nt) is to be repealed as long as the input operation cin>>eurre nt succeeds, a nd cin»curre nt will succeed as long as there are characters to read on the st.andard
71
( HAPTER 3 • O BJECTS , TYPES. ANO VAL UES
72
input. Remember that for a string, » reads whitespace-scparatcd words. You terminate this loop by giving the program an end-oC-input character (usually referred to as end "file). On a Windows machine, lhat's C trl+Z (Control and Z pressed together) foUowoo by an Enter (return). On a Unix or Linux machine that's CLTl+D (Control and D pressed lOgether). So, what we do is to read a word into current and men compare it to the previous word (stored in pre vio us). U they aTC the same, we say so:
if (previou s == current) II check if the word is the same as last cout « "repeated word : "« curre nt « '\n ';
111cn we have to get ready to do this again for the next word. We do that by copying the cune nt word into previous :
previous =curre nt i This handles all cases provided that we can get started. 'What should this code do for the first word where we have no previous word to compare? 111is problem is dealt with by the definition of previo us : st ring previous =" ";
/I previous word; ini tialized to "not a word"
·nle " " contains only a single character (the space character, the one we get by hitting the space bar on our keyboard). Tbe input operator » skips whitespace, so we couldn't possibly read that from inpul. 111crcfore, the first time through the w hil e-statement, the test if (previous == current) fail s (as we wam it to). One way of understanding program now is to "play computer," that is, to follow the program line for line, doing what it specifies. Just draw boxes on a piece o f paper and write their values into them. Change the values stored as specified by the program.
TRY THIS Execute this program yourself using a piece of paper. Use the input "The cat cat jumped". Even experienced programmers use this technique to visualize the actions of small sections of code that somehow don't seem completely obvious.
1.6
COMPO SITE AS SIGNMENT OPERATORS
TRY THI S Get the "repeated word detection program" to run. Test it with the sentence "She she laughed He He He because what he did did nol look very ve ry good good". How many repeated words were there? Why? "What is the definition of word used here? What is the definition of repealed word? (For example, is "Sh e she" a repetition?)
3.6 Composite assignment operators incrementing a variable (that is, adding I to it) is so common in programs that C++ provides a special syntax for it. For example: ++counler means counle r =counle r + 1 lllerc are many other common ways of changing lhe value of a variable based on its currem value. For example, we mighllike to add 7 to it, to sublract 9, or to multiply it by 2. SUdl operations are also supported directly by C++. For example: a += 7; b-=9; c 2;
0=
/1 means a = = (greater than o r equal) also work for strings. '11e , etc. operators usc the lIsuaJ lexicographical ordering, so "Ape " comes before "Apple" and "Chimpanzee" .
TRY THI S Write a program that "bleeps" out words that you don't like; that is, you read in words using tin and print them again 0 11 coul. If a word is among a few you have defined, you write out BLEEP instead of that word. Start with one "disliked word " such as string disliked = "Broccoli"; When that works, add a few mOrt.
4.7 Language features ' 11e temperature and dictionary programs used most of the fundam ental language fealm'es we presented in this chapter: iteration (the for-sLatement and the while-s tatement), selection (the if-statement), simple arithmctic (the ++ and += operators), comparisons and logical operators (the ==, !=, and II operators), variables, and functions (e.g., mainO, sortO, and sizeO). In addition, we used standard library facilities, such as vector (a container of elements), cout (an output stream), and sort O (an aJgorithm). If you COU IlI , you'Ufmd lhat we aClllally achieved quite a lot wilh rather few fc., lUres. TIlal 'S the ideal! E.,ch progra.mm.i.ng language feallire exists lO express a fun damental idea, and we s.size O; H i) (
if(te mpsli j > high_te mp) high_te mp = te mpsl ij; ir(te mps[i] >op>>rval ; if (op=='+' ) res = Ivai + rval ; else if (op=='-') res = lval - rval;
/I addi tion /I subtract ion
coul « "Result : "« res« '\n '; keep_window_openO;
178
CHAPTER 6 • W RITI NG A PROGRAM
return 0; )
11lat is, read a pair of values separated by an operator, such as 2+2, compute the result (in this case 4), and pr int the resulting value. We chose the varia ble names Ivai for left-hand value and rva l for right.lland value. 'Illis (sort of) works! So what if this program isn't quite comple te? It fecls great to gel something running! Maybe this programming and computer scie nce stuff is easier than the rumors say. WcU, maybe, but let's not gel too c.micd away by an early success. Let's
1. C lean up the code a bit 2. Add multiplication and division (e.g. , rJ) 3. Add the ability to handle
mOTC
than one operand (e.g., 1+2+3)
In particular, we know that we should always check that our input is reasona ble (in our hurry, we "forgot") and that testing a value against many constants is best done by a switc h-statement rather than an if-state ment. lllC "chaining" of operations, such as 1+2+3+4, we will h,mdlc by adding the values as they are read; that is, we start with 1, see +2 and add 2 to 1 (getting an intenllediate result 3), see +3 and add that 3 to our intenllediatc resuh (3), a nd so on. After a few false starts and after cOlTecnng a few synta.:x and logic errors, we get: #include "std_lib_faeiliti es. h" int m ain O {
cout « " Please e nte r expression (we can ha ndle +, - , . , a nd /): "; int Ivai = 0; int rval; c ha r o p; /I read leftmost operand ein» lval; if (!ein) e rro r(" no first o pe ra nd "); while (ei n>>op) ( /I read operator and right-hand operand repeatedly ein» rval; if (lein) error(" no second o pe rand ") ; swilc h(o p) { case '+ ' : Iva i += rva l; /I add : Ivai ", Ivai + rval break; case '- ' : Iva l-= , val; /I subtract: Ivai = Iva i - rval break;
6.3
BA CK TO THE CALCULATOR !
case ' . ' : Ivai "= rval ; 1/ multiply: Ivai = Ivai ' rval break ; case 'f: Ivai 1= rval; /1 divide: Ivai = Ivai I rval break ; default : 1/ not another operator: print result cout « "Result : "« Ival « '\n '; keep_window_open O; return 0; } }
error{" bad expression ");
lllis isn't bad, but then we try 1+2·3 and see that the result is 9 and not the 7 our arithmetic teachers told us was the right ans wer. Similarly, 1-r3 gives -3 ralher than the -5 we expected. We are doing the operations in the wrong order: 1+2·3 is caJculated as (1 +2)"3 rather t.han as t.he conventionaJ 1+(2"3) . Similarly, 1-2·3 is calculated as (1-2)·3 rat.her than as the convemional 1- (2"3) . Bummer! We m.ight consider the convention that " multiplication binds tighter tha n additio n" as a silly old convention, but hundreds o f years of convention will not disappear just to simplify our programming.
6.3.2 Tokens $0 (somehow), we have LO '"'look ahead" on the line LO see if t.here is a " (o r a I) . If so, we have LO (somehow) adjust the evaJuatio n o rder from the simple and obvio us left -ta-right order. Unfortunately, trying to barge a head here, we immediately hit a couple of snags:
I. Vle don't actually require a n expression to be on one line. 1;or example: + 2
works perfectly with our code so far. 2. H ow do we search for a " (or a I) among digits and plusses on several input lines? 3. H ow do we reme mbe r where a " was? 4. H ow do we handle evaJuatio n that's not strictly left·to·right (e.g., 1+2·3)? H aving decided to be super-optimists, we'll solve problems 1-3 first and not worry abo ut 4 until la ter.
180
CHAPTER 6 • WRITI N G A I'ROGRAM
Also, we' ll ask around for help. Surely someone will know a convenlional way of rcading "stuff," such as numbers and operators, from input and storing it in a way that lets us look at it in convenient ways. The conventional and very usefu l allswcr is "tokcnize": first input characters arc read and assembled into IORellJ, so if you type in 45+11 .517
the program should produce a list of tokens representing
45 + 11.5
I 7
A token is a sequence of characters thaI represenLS something we consider a unit, such as a number or an operator. 11mt's the way a C++ compiler deals with its source. Actually, "LOkcnizing" in some form or anomer is the way most analysis o f text starts. Fo llowing the example of C++ expression, we sec the need for three kinds of tokens:
Floating-point-literals: as defined by C++, e.g., 3.14, O.274e2, and 42 Operators: e.g., +, - , . , I, % Parentheses: (, ) TIle nonling-point-literals look as if they may become a problem: reading 12 seems much easier than reading 12.3e-3, but calculators do tend to do noalingpoint arithmetic. Similarly, wc suspcct that we'll have to accept parenth eses to have our c.llculator dcemed useful. How do we represent such tokens in our program? We could try to keep track of where each tokcn startcd (and cnded), but that gets messy (cspecially if we allow expressions to span line boundaries) . Also, if we keep a number as a string of characters, we later havc to fi gu rc out what its value is; that is, if we sec 42 and store the characters 4 and 2 somewhere, we thcn later have to figu re out thalthose characters represent the numerical value 42 (i.e., 4-10+2). "The obvious - and conventional - solution is to represent cach token as a (kind,vallle) pair. TIle kind tells liS if a token is a number, an operator, or a parcmhesis. For a nUIll ber, and in th is example only for a number, we lise its numerical valuc as its wlue. So how do we express the idea of a (kilul,w/ue) pair in code? We define a type Toke n to represent tokens. Why? Remember why we lise types: they hold the data we need and give us uscful operations on that data. For example, ints hold inlegers and give us addition, subtraction, muhiplication, division , and remain-
6.]
BACK TO THE CA LCULATOR !
181
der, whereas strings hold sequences o r characters and give us concatcnation and subscripting. The C++ language and its standard library givc us many types such as char. inl, doubl e, siring, vector, and oslream, but not a Token type. In ract, there is a huge number or types - thOllsands or tens or thousands - that we would like to have, but the languagc and its standard library do not supply them. Amo ng our ravorite types that arc not suppo rted are Matrix (sec C hapter 24), Oate (sec Chapter 9), and infinite precision integers (try searching the web ror MBignum "). Ir YOll lhink about it ror a second , you' ll rcalize that a languagc can· not supply tens or thousands or types: who would defi ne theEll , who would im· plement them, how would you find thcm, and how thick would the manual have to bc? Like most modcrn languagcs, C++ escapcs that problcm by letting us define our own types (u.ser-liejilled type;) when we need them.
6.3.3 Implementing tokens What should a token look like in our program? In other words, what would wc like our Token type to be? A Token must be able to represent operators, such as + and - , and numeric values, such as 42 and 3.14. -nlC obvious implementation is something that can represent what "kind" a token is and hold thc numeric value ror tokens t h at have onc: Token : kind : value :
Token : plus
kind : value :
number 3.14
-n lcrc arc many ways th at this idea could bc reprcsentcd in C++ codc. Hcre is the simplest that we round userul: class Token { /I a very simple user-defined type public: char kind ; double value; },
A Token is a type Oike int or char), so it can bc used to define variables and hold val ues. It has twO parts (called mcmhn:s): kind and value. The kc)"vord class means "user·dcfined lypcn; it indicatcs that a type with z.cro or more members is being dcrmed. ' 11e fi rst member, kind, is a character, char, so that it conveniently can hold '+' and '. ' to represent + and *. We can use it to make types like this : Token I ; t.kind = '+'; Token 12;
/II is a Token /I t represents a +
II t2 is another Token
182
CHAPTER 6 • WRITING A PRO G RA M
12. kind = '8'; /I we use the digit 8 as (he 12. value = 3.14:
~ k i nd "
for numbers
We lise the member access notation, obftd_lUllfle . memlxr_'lIllJle, (0 access a member. YOll can read I.kind as "I's kind " and 12.valu e as "t2's valu e ." We can copy Tokens just as we can copy inls: Toke n II =I; /I copy ini(ialization if (lI .kind != I..kind) erro r(" impossible!"): t =t2; /I assignment coul « I.valu e; /I wi ll prim 3. 14 Given To ken , we can represent the expression (1.5+4)-11 using seven tokens like this:
I'I' I
'8' 1.5
'8' 4
1'·'1 "'1
'8' 11
Note that for simple tokens, such as +, we don't need the value, so we don't use its value member. We needed a character to mean "number" and picked '8' just because '8' obviously isn't an operator or a punctuation character. Using '8' to mean "number" is a bit cryptic, but it'll do for now. To ken is an example of a C++ user-defin ed lype. A user·defined type can have member fu nctions (operations) as well as data members. 111el"e ca n be many reasons fo r defining member functions. Here, we'll just provide two Jllem· ber fun ctions to give us a more convenient way of initializing Toke ns: class Token ( public: /I what kind of token char kind ; double value: /I for numbers: a value II make a Token from a char Token(char chI :kind (ch), value(O) {} Token(char ch, do uble val) II make a Token from a char and a double :kind(ch), valu e(val) {} ); ~nlese
two member funClions are o f a special kind called (Olu/ nll/Orl. ~nley have the same name as their type and are lIsed to iniliaJize ("conslnlct") Toke n objecLS. For example: Toke n 11 ('+'): Toke n t2('8',11 .5);
II initialize II so thalll .kind = '+' /I initial ize t2 so that t2.kind = '8' and t2.value = 11 .5
6 .3
BACK TO THE CALCULATOR!
183
In the first constructor, :kind (ch), value(O) means "Initialize kind 10 ch and set value to 0." In the second constructor, : kind(ch), value(val) means "Initialize kind to ch and set value to vat." In both cases, nothing more needs to be done to con· struct th e Token , so the body of the function is empty: { }. The special initializer syntax (a mt:mm.,,- illitialiur list) starting with a colon is used o nly in constructors. Note that a constructor docs not return a value. No return lype is requ ired (or allowed) for a constmctor. For more abolll constructors, sec §9.4.2 and §9.7.
6.3.4 Using tokens So, maybe now we can complete our calculator! However, maybe a small aillount of planning ahead would be worthwhile. How would we use Tokens in the calculator? 'We can read out input into a vector of Tokens: Token geC tokenO;
/I read a token from cin
veclor 10k;
/I we'll put (he tokens here
int main O {
while (ein) ( Token I =geClo ken() ; lo k.push_back(I); ) /I . ..
}
Now we can read an expression first and evaluate later. For example, for 11 -12, we gel '8' 11
1"'1
'8' 12
We can look at that to find the multiplication and its operands. Having done that, we can easily perform the multiplication because the numbers II and 12 are stored as nU llleric values and not as strings. Now let's look at more complex expressions. Given 1+2-3, 10k will contain five Tokens:
'8' 1
1'·'1
'8' 2
1'·'1
'8' ]
C HAPTER 6 • WRITING A PROGRAM
184
Now we could fmd the multiply operation by a simple loop: for (i nt i = 0; i 2+3; =5
> 5°7; =35
>
l 11is looks llIuch beuer, an d we can get it by a minor change to the main loop o f main() : double val = 0; whi le (dn) ( cout « "> ";
/I prin t prompt
221
( HAPTE R 7 • COMPLE TI NG A PR OG RAM
222
Token t
= ts.get();
if (t.kind == 'q 'l break ; if (t.kind == '; ') coul « "= " «val « '\n ' ; else
/I print result
Is.putback(l) ;
val = expression(); }
Unfortunately, the result of putting severaJ expressions on a line is still messy: > 2+3; 5°7; 2+9:
=s > =35 >= 11 >
' 11C basic problem is that we didn't think of multiple expressions on a linc when we started out (at least we pretended not to). YVhat we want is > 2+3; 5"7; 2+9;
=s =35 = 11
>
This looks right, but unforlunaLCly mere is no really obvious way of achieving il. We first looked at mainO. Is there a way to write out > only if it is not immediately followed by a =? We cannot know! We need to write > before the get(), but we do not know if gel() actually reads new characters o r simply gives us a Token from characters that it had already read from the keyboard. In other words, we would have to mess with Token_stream to make this fin al improvement. For now, we decide that what we have is good enough. If we find that we have to modify Token_stream, we'll revisit this decision . However, it is unwise to make major structural changes to gain a minor advantage, and we havcn't yct thoroughly tcsted the calculalOr.
7.3 Error handling TIle first thing to do once yOll have a program that "basically works" is to try to break it ; that is, we try to feed it input in the hope of getting it to misbehave. We say "hope" because the challenge here is to find as many errors as possible, so
7.3
ERROR HAND LIN G
that you can fix them befo re anybody else finds them. If you go into this exercise with the attitude that '" my program works and I don't make errors!" you won't find many bugs and you'll feci bad when you do find one. You'd be playing head games with yourseln The right auitude when tesling is "I'll break it! I'm smarter than any program - even my own!" So, we feed the calculator a mix of correct and incorrect expressions. For cxample: 1+2+3+4+5+6+7+8 1- 2- 3-4 !+2
."
(1+3 ; (1+); 1-2fJ%4+5-6;
0; 1+; +1
1++;
110 1/0; 1++2; -2 ; -2 · .. ·
1 ijl~~78901 23456;
'a' ; q
1+q 1+2 ; q
TR Y THI S Feed a few such "problematic" expressions to the calculator and try to figure out in how many ways you can get it to misbehave. Can you get it to crash, that is, to get it past our error handling and give a machine error? We don't think you c."ln. Can you get it to exit without a usdul error message? You can.
Technically, this is known as telting. '111ere are people who do this - break programs - for a living. 'lesting is a very important part of software development and can actually be fun. Chapter 26 exanlines tesling in some detail. One big
223
CHAPTER 7 • COMPLET ING A PROGRAM
224
question is: "Can we lest the program system atically, so thm we find all of the eTrors?" "Illerc is no general answer to this qucstion; that is, there is no a nswer that holds for all programs. H owever, you can do rather well for lUany prOb'Tams when you a pproach testing seriously. Yo u try to create test cases systcmaticaJly, and just in case your strategy [01' selecting tests isn't complete, you do some "'unreasonable" tests, such as
Mary had a little lamb s rtvrqliewcbet7rewaewre-wqcntrretewru 754389652743nvcqnwq ; !@#$%,.'\&"O- :;
Once, when testing compilers, I got
inLO
the habit of feeding email reporting COIll -
piler errors straight to the compiler - mail headers, user's explanation, and all. l1ml wasn't "sensible" because "nobody would do that." H owever, a program ideally catches all errors , not just the sensible ones, and soon that compiler was very resilient against "strange input." The fi rst really annoying thing we noticed when testing the calculator was that the window closed immediately after inpu ts such as +1 ; ()
!+2 A lillie thought (or some tracing of the progTam 's execution) shows that the problem is that the window is closed immediately after the error message has been written. This happens because our mechanism for keeping a window alive was to wait for you to e nter a dmracter. H owever, in all three cases above, the program detected a n error before it had read all o f the characters, so that there was a character left on the input line. 111e program can't tell such "leftover" characters fro m a character entered in response to the Ente r a c haracte r to close window prompt. That "left over" character then closed the window. We could deal with that by modifying ma inO (sec §5.6.3): catch (runtime_e rror& e) ( ce r, « e. what()« e ndl ; /I keep_windmv_opcnO: cout « "Please e nte r th e cha racte r - to close the window\n "; c ha r ch i while(ci n » ch) II keep reading until we find a if (ch== '-') re turn I; re turn 1; }
7. 3
ERR OR HANDLING
Basically, we replaced keep_window_openO with our own code. Note that we still have our problem ir a - happens to be the next character to be read after an error. bUl that's rather unlikely. When we encountered this problem we wrote a version or keep_win d ow_ope nO that takes a string as its argument and closes the window only when you enter that string arter getting the prompt, so a simpler solution is: catch (runtime_error& e) { cerr « e. whatO« e ndl ; keep_window_ope n(tI_tl) ; return 1;
Now examples such as .1 11_ ()
will cause the calculator to give the proper error mcssages, then say Please ente. - - to exit and not exit until you enter the string - . The calculator takes input rrom the keyboard. That makes testing tedious: each time we make an improvement, we have to type in a lOt or test cases (yet again!) 10 make sure we haven't broken anything. II would be much beller ir we could store our test cases somewhere and run them with a single conunand. Some operating systems (notably Uni.x) make it lrivialto get cin LO read rrom a rde without modir)'ing the program, ,md similarly to divelt the output rrom coul to a file. Ir that's not convenient, we must modify the program to usc a (ile (see Chapler 10). Now consider: 1+2; q
and 1+2 q
We wou ld like both to print the resu lt (3) and then exit the program. Curiously enough, t+2 q
225
CHAPTER 7 • CO MPLETIN G A PROGRAM
226
docs that, but the apparently cleaner 1+2; q cl iciLS a Primary expcCled error. Where would we look fo r this e rror? Ll main{) where ; and q are handled , of course. We added those "print" and "quit" CO Ill mands rather quickly to get the calculator to work (§6.G). Now we a rc paying for
that hastc. Consider again: double val = OJ while (dn ) {
cout « ">"; Token t = ts.geIO; if (t.kind == 'q 'l break ; if (I. kind == ';') coul « "= " « val « '\n ' ;
else ts. putback(t); val = expression j);
If we find a semicolon, we straightaway proceed to call expression O without checking for q . 111c first thing that expression does is to look for a primaryO, and now it fin ds q . 111c letter q isn' t a primary so we gel our er ror message. So, we should test for q after testing ror a semicolon. W hile we were at it, we rclt thc necd to simplify thc logic a bit, so the completc mainO reads:
inl mainO try {
while (cin ) { coul « "> "; Token I = IS. gel(); 1=ls.gel(); while (I.kind if (I .kind 'q ') { keep_window_openO; relurn 0;
==
== ';')
Ileal ';'
}
Is.pulback(t); coul« "= " « expressionO« endl ; }
kee p_window _open (); return 0; }
7.4
NEGATIVE N U MBERS
227
catch (exception& e) { cerr « e. whatO« endl ; keep_window_o pe n("-"); return 1; catch (..• ) { cerr « "exceptio n \n"; keep_window_o pen("-") i return 2;
111is makes for reasonably robust elTor handling. So we can start considering what else we can do to improve the calculator.
7.4 Negative numbers If you tested the calculator, you found that it couldn't handle negative numbers elegamly. For example, this is an error:
-,/2 We have to write 10-' )/2
..
11mt's not acceptable. Finding such problems during late debugging and testing is common. Only now do we have the opportunity to sec what our design really docs and get the feedb3%2; =1
>5%3; =2
..
How should we handle operands that are not integers? What should be the resu lt of > 6.7%3.3; ~11 1erc
is no really good answer, so we'll prohibit the lise of % on a floating·point argument . We check if the floating·point operands have fractional parts and give an error message if they do. Here is the resulting term (): do uble termO (
do uble left = primaryO; To ken t = ts.get(); while(true) { switch (I .kind) {
II gel the next token from Token_stream
CHAPTER 7 • COMPLETING A PROGRAM
230
case
I ",,:
.=
r.'....,..... ',
leU lefmO; 1 = Is.get()i break ;
case 't : ....... ( double d = term(); if (d == 0) e rror{"divide by zero ") ; left 1= d ; t = Is.get() ; break; }
case '0)/0': ( double d =,!erm(); int i1 = int(left); if (it != left) error ("Iefl-hand operand of % not int "); int i2 = inl (d); if (i2 != d ) error (" right-hand operand of % not int "); if (i2 == 0) e rror("%: divide by zero "); left = il %i2; t = ts .getO; break; }
default :
ts.putback(t); re lurn le ft i
II put! back into the Token_stream
} } }
What we do here is to usc != to check if lhe d o uble to int conversion changed the value. If not, a ll is well and we can use %. TIle problem of ensuring inl operands for % is a variant of the narrowing problem (§3.9.2 and §5.6.4), so we could solve it using na rrow_cast : case '0/0' : int il = narrow3 ast(left ); int i2 = narrow_cast(le rm()); A1 (i2 == 0) e rror("% : divide by zero"); left = il 0/0i2 ; 1= ts.geIO; break ; }
7. 6
ClEANING U P THE CO DE
231
That's certainly shorter, and arguably dearer, but it doesn't give quite as good elTor messages.
7.6 Cleaning up the code ""e have made several changes to the code. ~nley are, we think, all improvements. but the code is beginning to look a bit messy. Now is a good time to review the code to sec if we can make it clearer and shorter, add and improve comments, etc. In other words, we arc nm finished with the program until we have it in a state suitable for someone else to take over maintenance. Except for the almost tolal absence o f comments, the calculator code really isn't that bad, but let's do a bit o f cleanup.
7.6.1 Symbolic constants Looking back, we find the usc o f '8' to indicate a Token containing a numeric value odd. It doesn't really mailer what value is used to i.ndicate a number Toke n as long as the value is distinct from all other values indicating different kind of Toke ns. However, the code looks a bit odd and we had to keep reminding ourselves in comments: case '8' : /I we use '8' 10 represent a number /I return the number's value return t.value; case '- ' : return - primary() ;
•
-10 be honcst, we also made a few mistakes, typing '0' rather than '8', because we forgot which value we had chosen to use. In other words, using '8' directly in the code m.a nipulating Tokens was sloppy, hard to remember, and error-prone; '8' is one of U10se "magic constants" we warned against in §4.3. 1. \,yhat we should have done was to introduce a symbolic name for the constant we used to represent Ilumber : const char number
= '8';
/1 \.kind== numbcr means that 1 is a number Token
TIle consl modifier simply tells lhe compiler that we arc defining a number that is not supposed to change: number='O' would cause the compiler to give an error message. Civen that definition o r number, we don't have to use '8' expliciliy anymore. -n le code fragment from primary above now becomes: case number:
return t.value ; case '-' :
return - primary() ;
/I return the number's value
C HAPTER 7 • COMPLETIN G A PROGRAM
This requires no commem. We should not say in comments what can be clearly and directly said in code. Repeated commeills explaining something are often an indication that tile code should be improved. Similarly, the code in Token_stream : :getO that recognizes numbers becomes case '.': case '0': case '1 ': case '2' : case '3' : case '4': case '5' : case '6': case '7': case '8' : case '9': dn.putbackq; /I put digit back into the input stream double val; , ~ dn» val ; /I read a floating-point number return Token(number, val);
We could consider symbolic names for all tokens, but that seems overkill. After all, ' (' and '+' arc about as obvious a notation for ( and + as anyone could come up with. Looking through the tokens, only ';' for "print" (or "terminate expres· sion") and 'q ' for "qu it" seem arbitrary. \Vhy not 'p' and 'e' ? In a larger program, it is only a matter of time before such obscure and arbitrary notation becomes a cause of a problem, so we introduce const char quit = 'q '; const char print = ';';
lIt.kind==quit means that t is a quit Token II t.kind==print means that t is a print Token
Now we can write main O's loop like this : whil e (dn) { coul « "> "; Token t = ts.gel(); while (I. kind == print) t=ls.getO; if (I.kind == quit) { keep_window_opcnO; return 0; )
ts. putback(t); coul« "= " «ex pressionO « endl; )
Introducing symbolic names for "prim" and "quit" makes the code easier to read. In addition, it doesn't encourage someone reading mainO to make assumptions about how "print" and "quit " arc represeilled on input. For example, it should come as no surprise if we decide to change the represemation of "quit" to 'e' (for "exit"). That would now require no change in mainO .
7 .6
CLEANIN G U P THE CO DE
233
Now the strings "> " and "= " stand out. Why do we have these "magical" literals in the code? How would a new programmer reading main O guess their purpose? Maybe we should add a comment ? Adding a comm ent might be a good idea, but introducing a symbolic name is more effective: canst string pro mpt = "> "i ca nst string res ult = "= "i
/I used 10 indicate that what fo llows is a resul t
Shou ld we want to change lhe prompt or tile result indicator, we can JUSt modify those consts. 111e loop now reads while (ci n) { coul « pro m pi ; Token I = Is.getO; while (I. kind ==print) f=fs,gel(); if (I . kind == quit) { kcep_window_o pe n(); return OJ ts. putback(t); cout « result «expressionO« endl ; }
7.6.2 Us. of fU l1jlions TI1C fun ctions \\-·c usc should reflect the Slmcture of our program, and the names of the functions should identify the logically separate pans of ollr code. Basically, our program so far is rather good in this respect: cxpressio nO, termO, and primaryO directly reflect our understanding of the expression grammar, and gelO handles the input and token recognition. Looking at mainO, though, we notice that it docs two logically separate things: 1. main O provides general "scaffolding": start the program, end the pro-
gram, and handle "fatal " errors. 2. main() handles the c..1.1culation loop. Ideally, a fu nction performs a single logical action (§4.5.1 ). Having main O perform both of these actions obscures the stmcture of the program. TIle obvious solution is to separate out lhc e..l.lculation loop in a separate function calculaleO : void calculateO (
II expression eva luation loop
C HAPTER 7 • C OMP LETI NG A P RO GRAM
234
while (eio ) ( cout « prompt; Token t = ts.get(); while (t.kind == prinO I=ts.get() ; II first discard all "prints" if (I.kind == quit) re turn ; II quit Is .putback(l); cout « result «cx pressionO« e ndl ; }
int main()
try ( calculale() ; keep_window_openO; return 0 ;
II cope with Windows console mode
}
catch (runtimc_crror& e) {
cerr « e.whal ()« e ndl ; keep_window_opcn("- -"); return 1 ; }
catch (, .. ) ( eerr « "exception \nil ; keep_window_open ("-"); return 2; }
TIlis rcnccts the structure much morc directly and is therefore eas ier to understand.
7.6.3 Code layo ut Looking through the code ror ugly code, we find switch (ch ) { case 'q ': case ';': case '%': case 'I': case 'I': case '+' : case '_': case I.': case '/':
relurn Token(ch) ;
/I lei each character represent itself
This wasn't tOO bad bcfo~ we added 'q ', ';', an d '%', but now it's beginning to become obscure. Code that is hard to read is where bugs can more easily hide. And yes, a potential bug lurks here! Using one line per case and adding a couple of comments help. So, Toke n_stream's getO becomes
7.6
C LEANIN G U P THE CODE
Token Toke n_stream: :getO /I read characters from cin and compose a Token {
if (fu ll) { /I check if we already have a Token ready full=false; return buffe r; }
char Ch i cin » Chi
/I notc that » skips whitespace (space, newline, tab, etc.)
switch (ch) { case quit : case print : case '(' : case ')' : case '+' : case '- ' : case '.': case 'f : case '%': return Token(ch); /I let each cha racter represent itself case '.' : II a floa ting-point-literal can start with a dot case '0': case '1': case '2' : case '3' : case '4': case '5': case '6': case '7': case '8' : case '9': II numeric literal cin .putback(ch); /I put digi t back into the input stream do uble val ; cin » val ; II read a floa ting-point number return Token(number,val); de fault : e rror(" Bad token"); }
We could of course have PUt each digit case on a separate linc also, but that didn't seem to buy us any clarity. Also, doing so would prevent getO from being viewed in its entirety on a screen at once. Our ideal is for each function to fit on the screen: one obviolls place for a bug to hide is i.n the code that we can't sec becalise it's ofT the screen horizontally or vertically. Code layout mallers. Note also that we chan ged the plain 'q ' to the symbolic name quit. This improves readability and abo guarantees a compile-time error if we should make t.he mistake of choosing a value for quit that clashes wit.h another token name.
2J5
236
(HAPTER 7 • COMPLETING A PROGRAM
When we dean up code. we might accidentally imrodtiCC errors. Always retest the program after cleanup. Belter still, do a bit of testing after each set of minor improvements so that if something weill wrong you ca.n still remember exactly what you d id. Remember: Tcst early and often.
7.6.4 Commenting \oVc added a few comments as we went along. Good comments are an imponant pan of writing code. We tend to forgel about comments in the heat of programming. Wllcn yOll go back to the code to clean it up is an excellent time to look at each part of the program to sec if the comments yOll originally wrote arc
1. Still valid (YOLI might have changed lhe code since you wrolC the comment) 2. Adequate for a reader (they usually arc nOll 3. Not so verbose that th ey distract from the code ~Io
emphasize that last concern : what is best said in code should be said ill code. Avoid comments that repeat an action that's perfe ctly clear 10 someone who knows the programming language. For example: x = b+c;
II add band c and assign the result to x
You'll find sLich comments in this book, but only when we are trying to explain the use of a language fea ture that might not yet be familiar to you . Comments are for things that code expresses poorly. An example is intent: code says what it docs, not wha t it was intended to do (§5.g. t ). Look at the calculator code. ~111cre is something missing: the functio ns show how we process expressions and tokens. but there is no indication (except the code) what we meant expressio ns and to kens to be. TIle grammar is a good candidate for something to put in comments or into some documentatio n of the c.,lcu!ator.
'"
Simple calculator Revision history: Revised by Bjarne Slroustrup May 2007 Revised by Bjarne Stroustrup August 2006 Revised by Bjarne Stroustrup August 2004 Originally written by Bjarne Stroustrup (bsGlcs.lamu .edu) Spring 2004. This program implements a basic expression calculator. Input from c in; output to coul.
7 .6
ClEANING U P THE CO DE
237
The grammar (or input is: Statement: Expression Print Quit Print:
Quit:
q Expression: Term Expression + Term Expression - Term Term : Primary Term' Primary Term I Primary Term "/" Primary Primary: Number ( Expression ) - Primary + Prima ry Number: floating-poi nt-literal
Input comes from cin through the Token_stream ca l led Is.
'/
'*
Here we used the block commelll, which Slan s with a and cominues until a */. In a real program , the revision history would comain indications of what corrections and improvements were made. Note that the comments arc not the code. In fact , this grammar simpl ifie s a bit : co mpare the mle for Statement with what really happens (c.g., have a peek at the code in the followin g section). TIle comment fails to explain the loop in calculateO that allows li S to do several calculations in a single mn of the program. We'll return to that problem in §7.8.1.
C HAPTE R 7 • C OMPLETING A PRO G RAM
7.7 Recovering from errors Why do we exit when we find an error? T hat seemed simple and obvious at the time, bm why? Couldn 't wejust write an error message and carry on? After all, we often make little typing errors and such an error doesn't mean that we have decided not to do a calculation. So lct's try to recover rrom an error. l liat basi· cally means that we have to catch exceptions and cominue arter we have cleaned up any messes that were lcrt behind. Until now, all errors have beell represented as exceptions and handlcd by main O. Ir we want tD recover rrom elTors, cal eulaleO must catch exceptions and u-y to clean up the mess before trying to evaluate the next expressio n: vo id calculateO {
while (ein ) Iry { co ul « prompti Token t = Is.get() ; while (t.kind == print) t=ts,gelOi II fi rst discard all Hprints" if (I- kind quit) return ; /I quil Is. putback(l) i co ut « res ult « expressio nO «endl ;
==
}
calch (exception& e) { cerr « e.whatO« e ndl ; dean_up_messO;
/I write error ml.'SS3ge
} }
\oVe simply made the while-loop's block into a try·block that writes an error mes· sage and d eans up the mess. Once that's done. we carry on as always. \i and e , just as we have on scientific calculators. Adding variables and constants is a major extension to the calculatOr. It will touch most parts of the code. This is the kind of extension that we should not embark a ll without good reason and sufficient lime. H ere, we add variables and constants because it gives us a chance to look over the code again and try a lit some more programming techniques.
7.8.1 Variables and definitions Obviously, the key to both variables and built-in constants is for the c.-uculator program to keep (IUlIll£,l/{IJue) pairs so that we can access the value given the name. We can define a Variab le like this: class Variable { public: string name; double valu e; Variable (string n, double v) :name(n), value(v) () };
We will use the name member LO identify a Variable and the value member to SLOre the val ue corresponding to that name. TIle constnlctor is supplied simply for notational convenience. How Colll we store Variables so that we can search for a Variable with a given name string to fin d its value or to give it a new value? Looking back over the programming tools we have encOLintered so far, we find only one good answer : a vector of Variables: vector var_table; We can put as many Variables as we like into the vector var_table and search for a given name by looking at the vector clements o ne after another. We can write a get_valu eO function that looks for a given name string and returns its corresponding value :
241
C H APTER 7 • COMPL ETI NG A PROG RAM
242
double get_value(shing 5) II return the value of the Variable named s {
for (int i = 0; kvaUable .size(); Hi) if (va,_lable[iJ. name == 5) return var_table[il .valuei error("gel: undefined variable ". 5);
TIle code really is quite simple: go through every Varia ble in var_tabl e (starting with lhe first element and continuing until the last) and see if its name matches the argumcm string s. If that is the case, return its value . Similarly, we can define a seCvalue () function 10 give a Variable a new value : void scCvalue(slring s , do uble d) /I set the Variable named s to d {
for (int i = 0; iaaUable.size() ; ++i) if (vauableliJ .name s) (
==
var_lablel il.valu e = d ; return ; )
error(n set: undefined variable ". 5); )
We can now read an d write "variables" represented as Variables in var_lable. How do we gel a new Variable into var_lable? What docs a user or our calculator have to write to define a new variable and later to get its value? We could con· sider C++'s notation double va, = 7.2; lllat would work, but all variables in this calculator hold double values, so say· ing "double" would be redundant. Could we makc do with var = 7.2; Possibly, but then we would be unable to tcllthc differcllcc between the declaration or a new va!'iablc and a spelling mistake: var1 = 7.2; varl = 3.2;
II define a new variable ca lled varl /I define a new variable called var2
7.8
VARIAULES
243
Oops! C learly, we meant var2 = 3.2; but we didn't say so (except in the comment). We could live with this, but we'll follow the tradition in languages, such as C++, that distinguish declarations (with initializations) from assignments. We cou ld usc doubl e, but for a calculator we'd like something short, so - drawing on another old tradition - we choose the keyword let: let var =7.2; rnle grammar would be Calculatio n: Statement Print Q uit Calculation Statement Statement: Declaration Expressio n Declaration: "let" Name
"=" Ex pressio n
Calculatio n is the new top production (nile) of the grammar. It expresses the loop (in calculate(») that allows us to do several calculations in a run of the calculator , program . It relics on the Statement production to handle expressions and declarations. "Ve c.l n handle a statement like this: do uble slatementO {
Toke n t =ts.getO; switch (I. kind) ( case lei: return d eclarationO; d efault: ts. pulback(t) ; return expressio n(); ) )
Vlc can now lise slalement () instead of expressio n() in calculate() :
( HAPTER 7 • CO MP LETI NG A PROGRAM
244
void calculateO {
while (dn) try ( cout« prompt; Toke n I = ts.gel(); II first discard all while (I.kind == print) 1=ls.get() ; if (I. kind == quit) return ; II quit ts .pulback(t); cout« result « statementO« endl;
h prjnts ~
} catch (c)(ceplion& e) {
cerr « e.whatO« endl; clean_up_messO:
1/ write error message
}
We now have to wr ite d e claration() . \-Vhat should it do? It sh ould make slIre that what comes after a let is a Nam e followed by a = foll owed by an Expression . That's what our gram mar says. What should it do with the name? \P\'c should add a Varia ble with that name string and the value of the expression to OUI" veclor called var_table. Once that's do ne we can retrieve the value using get_valueO and cha nge it using set_valueO . H owever, berore writing this, we have to decide what should happen ir we defmc a variable twice. Fo r example :
letv1=7; letv1=8 ; We chose to consider such a redefinition an e rror. lyPically. it is simply a spelling m istake. Instead oh..,har we wrote, we probably meam le tv1= 7; le tv2=8 ; There arc logically two pans to defming a Variable with the name var with the va lue val : 1. Check whether there already is a Variable called var in var_table. 2. Add (var,val) to vaUable . We have no use rar uninitialized variables. We defined the runctions is_decla redO a nd define_nameO to represent those (wo 10gic.1.lly separate opera tions:
7.6
245
VA RI A B LES
bool is_declared(string var) /I is var already in vau.1ble? {
fo r (int i = 0; iutback();
1/ error: argument missing
111e compiler would immediately give errors; the header token .h gives it all the infonn ation it needs for checking.
264
( HAPTER 8 • TECHNICALITIE S: FUN CT IONS , ETC.
Our std_lib_facililies .h header contains declarations for me standard library facilities we lISC , slich as caut, vector, and sqrt() , together with a couple of simple u tility fUllct io ns, slIch as errorO, that are not part ofth e standard library. In § 12.8 we show how to lISC the standard library headers directly. A header will typically be included in Immy source mes. TImt means that a header should only contain declarations that can be d uplicated in several files (such
as functio n declarations, class definitions, and definitions of numeric conslll.llts).
8.4 Scope A scope is a region of program text. A name is declared in a scope and is valid (is "in scope") from the point of its declaration umilthc end of I,hc scope in which it was declared. For example: void fO {
gO;
II error: gO isn't (yet) in scope
}
void gO {
fO;
/I OK: f() is in scope
}
void hO {
inlx=y; inty=x ;
gO;
/I error: y isn't (yet) in scope /I OK: x is in scope /I O K: gOis in scope
}
Names in a scope can be seen from within scopes n ested within it. For example, the call of fO is within the scope of gO w hich is " nested" in the global scope. 11le glo bal scope is the scope that's nOl ncstcd in any Olher. 111C rule that a n ame must be declared be fore it can be used still holds, so fO cannot call g O. There are several kinds o f scopes that we use to control where our names can be u sed: TIle global JCOjJe: the a rea of text outside any other scope A IIflllll!JpaU JlojJe: a named scope nested in the global scope or in another namcsp ace ; see §8.7 A ,laJJ JrojJe: the area of text within a class; see §9.2
8. 4
2.5
SCO P E
A local scope: betwecn { . .. } braces of a block or in a function argument lisl A J/a/t11lt!11 / Jloj)(: e.g. , in a for-statement main pUll)Ose of a scope is to keep names local , so that they won't interfere with namcs declarcd elsewhere. For example :
rn l C
void f( inl xl
/I f is global; x is local to f
{
int z = x+7i
liz is local
)
inl g(int x)
/I g is global; x is local 10 g
{
int r = x+2; return 2*f;
/I f is local
)
Or graphicaUy: Global scope:
fD
gD Here f() 's " is difTerent from gO's x. ' nlCY don't "clash" because they arc not in the same scope: fO's " is local to f and gO's " is local to g. 1'\\'0 incompatible declarations in the same scope are often referred to as a claJlI.. Similarly, the f deHned and used within gO is (obviously) not the function fO. Here is a logically equivalent but more realistic example of the lise of local scope : int max(int a, inl b)
/I max is global; a and b are local
{
return (a>=b) ? a : b; )
inl abs(int a) {
return (.1 0) relurn Xi II error: no value returned if x is 0
Actually, the compiler probably won't notice that we "forgot " the case x==O. In principle it could, but few compilers arc that smart. For complicated functions, it ca.n be impossible for a compiler to know whether or not you return a value, so be careful. Here, "being careful" means to make real ly sure that you have a return statement or an errorO for every possible way out of the function. For historica.l reasons, mainO is a special case. Falling lhrough the boltOm of mainO is equivalent to returning the value 0, meaning "successful completion" of the program. In a function that docs not return a value, we can usc return without a value to cause a return from the function. For exalllple: void print_until_s(consl vcctor v, canst string quit) (
for (int i=O ; ivIites [rom the actual input and output devices used. If we had to dit'ecuy address eadl kind of device, we'd have to change our program each litne a new screen or disk came on the market, or limit our users to ule screens and disks we happen to like. llmt would be absurd. Most modern operating systems separate the detailed handling o f lIO devices into device drivers and then access the device drivers thro ugh an 110 Ii· brary that makes I/O fromlt o different sources appear as similar as possible. Generally, the device drivers arc deep in the operating system where most users don' t sec them, and the I/O library provides an abstraction o fl /O so that the programmer doesn' t have to think about devices and device drivers: Da ta source: Input device
Device driver
Input library
Our program Data d estination:
Output library
H
Device driver
H
Output device
10 .2
THE I/ O STREAM MODEl
When a model like tlus is used, all input and all output can be seen as streams of bytes (characters) handled by the input/output library. Our job as programmers of an application then becomes 1. 1b set up 110 streams to the appropriate data sources and destinations 2. To read and write fromlto those StreanlS
11le details of how our characters arc actually transmitted to/from the devices arc dealt with by the 110 library and the device drivers. In this chapter and the next, we'lI see how I/O consisting of streams of formatted data is done using lhe C++ standard library. From the programmer's point of view there arc many different kinds of input and output. One classification is Streams of (many) data items (usually to/from files, network connections, recording devices, or display devices) Interactions with a user at a keyboard Interactions with a user through a graphical imerfacc (outputting objects, receiving mouse clicks, etc.) ~11 1is
classification isn 't the only classification possible, and the distinction between the three kinds of 1/0 isn't as clear as it might appear. For example, if a stream of output characters happens to be an HTI1' document aimed at a browser, the result looks remarkably like user interaction and can comain graphical clements. Conversely, the results of interactions with a G UI (graphical user imerface) may be presellled to a program as a sequence of characters. However, this classification fi ts our tools: the fi rst twO kinds of 110 arc provided by the C++ standard library 110 streams and supported rather directly by most operating systems. We have been using the iostream library since Chapter I and will focus on that for this and the next chapter. The graphical output and graphical user interactions are served by a variety of different libraries, and we will focu s onlhat kind of 110 in Chapters 12 to 16.
10.2 The I/O stream model TIle C++ standard library provides the type istrea m to deal with streams of input and the type ostream to deal with streams of output. We have used the standard islream called cin and the standard oslream called cout, so we know the basics of how to usc this part of the standard library (usually called the iostream librmy). An ostream Turns values of various types into character sequences Sends those characters "somewhere" (such as to a console, a file , the main memory, or another computer)
341
CHAPTER 10 • INPUT AND O UTP UT STREAM S
342
We can represent an ostream graphically like this: Values of various types
Character sequences
;'; Somewhere" (12,34)
osloeam
Buffer TIle buffer is a data stnlcturc that the ostream uses intcmally to store the data you give it while conUllUnicaling with the operating system. If you notice a "delay" between your writing to an oslream and the characters appearing at their destination, it 's usually because they arc still in the bulTer. Buffering is imJXlrtant for pcrfonn. ance, and perfomuUlcc is important if you deal with large alllOunts of data. An istream Tums character sequences into values of various types Gets those characters from somewhere (such as a console, a fil e, the main memory, or another computer) We can represent an istream brraphicaUy like this: Values of various typcs
Charactcr sequences
"Somewherc" (12,34)
istream
Buffer
As with an ostream, an istream uses a buffer to conununicatc with thc operating systcm. "Vil.h an istream, the buffering can be quite visible to the user. When you usc an istream that is anached to a keyboard, what you type is left in the buffer until you hit Enter (return/ newline) and you can usc the erasc (Backspacc) kcy " to changc your mind" (until you hit Enter).
10 .3
FIl.ES
343
One of the m~or uses of output is to produce data for humans to read . 111ink o f email messages, scholarly articles, web pages, billing records, business reports, contact lists, tables of contents, equipment status readouts, etc. Therefore, oslreams provide many features for fOfll13tting text to suit various tastes. Similarly, much input is wTitten by humans or is fonnatled to make it easy for humans to read it. Therefore, istJeams provide features for reading the kind of output produced by oslreams. "\'e 'll discuss fonnatling in §ll .2 and how to read non-character input in §11.3.2. Most of the complexity related to input has to do with how to handle errors. To be able to give more realistic examples, we'll start by discussing how the iostream model relates to mes of data.
10.3 Files "Ve typically have much more data than can fit in the main memory of our COIllputer, so we store most of it on disks or other large-capacity storage devices. Such devices also have the desirable property that data doesn't disappear when the power is turned ofT - the data is persistent. At the most basic level, a file is simply a sequence of bytes numbered from 0 upward: 0:
I
I: 2:
1:::=::::::::::::,-1-'--'--'
A fi le has a forma t; that is, it has a set of rules that determine what the bytes mean. For example, if we have a text file , the first 4 bytes wiJ[ be the first four characters. On the other hand, if we have a file that uses a binary representation of integers, those very same fi rst 4 bytes will be taken to be the (binary) representation of the first integer (see § 11 .3.2). ~nle format serves the same role for fi les on disk as types serve for objects in main memory. We can make sense of the bits in a file if (and only if) we know its fo rmat (see §11.2-3). For a file, an ostream converts objects in main memory into streams of bytes and writes them to disk. An islream does the opposite; that is, it takes a Stream of bytes from d isk and composes objects from them:
E---~ iostreams
M ain memory Objects (o r various types)
Most of the time, we assume that these "bytes on disk" arc in fact characters in our usual character set. That is not always so, but we C.'lIl get an awfully long way
CHAPTER 10 • INPUT AND OUTPUT STREAMS
344
with thal assumption, and other representations afC not that hard to deal with. We also talk as if all rues were on disks (that is, on rotating magnetic storage). Again, that's not always so (think of fl ash memory), but at this level of programming the actual storage makes no difference. TImt's one of the beauties of the file and stream abstractions. To read a file , we must I . Know its name
2. Open it (for reading)
3. Read in the characters 4. Close it (though lim is typically done implicitly) To write a file , we must
1. Name it 2. Open it (for writing) or create a new rlle o f that name
3. Write
Out OUf
objects
4. Close it (though that is typically done implicitly)
We already know the basics of reading and writing because an ostream attached to a fLl e behaves exacliy as cout for what we have done so far, and an istream attached LO a behaves exactly as cin for what we have done so far. We'll present operations that can only be done for ftles later (§ 11.3.3), blll for now we'll j ust see how to open ftles and then concentrate on operations and techniques that apply to all ostreams and all istreams.
me
10.4 Opening a file If you want to read from a file or write to a file you have to open a stream specif· ically for that file. An ifstream is an islream for reading from a fil e, an o(stream is an ostream for writing to a file, and an (stream is an ioslream that can be used for both reading and writing. Before a file stream can be used it mUSt be attached to a fil e. For example: coul « "Please ente r input (ile name: It; string name; cin » name; ifsh eam ist(name ,c_str()); 1/ ist is an input stream for the file named name if (!ist) erro r("can 't o pe n input fil e ",name); Defining an ifs tream with a name string opens the file o f that name for reading. ~nl e function c_str() is a member of string that produces a low·level C·style string
10.4
OPENING A FilE
(rom a C++ string. Such C -style strings arc required by many system interfaces. l11e test o( !isl checks that the me was properly opened. After that, we can read (rom the file exactly as we would (rom any otller istream. For example, assuming that the input operator, » , was defin ed for a type Point , we could write vecto r po ints; Po inl p ; while (isl» p) points. push_back(p); Output to Hies is handled in a similar (ashion by ofstreams. For example: cout « "Please e nte r name of oulput rile: "; string o name; d n » ona me; ofsire am ost(ona me .c_str()); Ilost is an output Siream for a file named name if (!ost) e rror(" can't o pe n o utput fil e " ,ona me); Defining an ofstream with a name string opens the file with that name (or writ· ing. "nle test o( ! ost checks tha t the file was properly opened. After that, we can wlite to lhe fi le exactly as we would to any other ostream. For example: fo r (int i=O; iart. TIle result is that a window knows about iu widgets and that each widget knows about its window: Widget Wmdow
~ ~
Widget
Note thai a Window doesn' t know what kind of Widgets it deals with . As described in § 14.4-S, we arc using basic object-o riented programming to ensure that a Window can deal with every kind of Widget. Similarly, a Widget doesn't know what kind of Window it deals with_ We have been slightly sloppy, leaving data members accessible. TIle own and j>W members arc strictly for the implementation of derived classes so we have declared them j>rotected. The definitions o f Widget and of the widgets we lise here (Button , Menu , ctc.) arc found in CUI-h .
16.4.2 Bullons A Bullon is the simplest Widget we deal wilh. All it does is to invoke a callback when we click on it:
C H APTER 16 •
55ointed to by p II write to the 3rd objecl pointed to by p
=9.9;
A pointer poims to an object in memory. The "contents or n operator (also called the dmference operator) allows liS to read and write the object pointed to by a pointer p:
double x = .p;
. p = B.8;
/I read the object pointed to by p /I write to the object pointed 10 by P
\>\'hcn applied to a poimer, the t I operator (rcats memory as a sequence of obj ects (o f the type specified by the pointer dccla'dlion) with the first one paimed to by a pointer p:
double x = pIJ] ;
II read the 41h object pointed to by p
p ll]
/I write to the 4th object pointed \0 by p
=4 .4 ;
double y = pIO) ;
/I plO] is the same as ' p
l1lat's all. 111crc is no check ing, no implementa tion clcvcrncss, jusl simple access
to OLir computer's memory:
plOI:
pil I:
8.9
p121 : 9.9
p131: 4.4
~l1Us
is exactly the simple and optimally efficient mechanism for accessing melllory that we need to implemellt a vector.
17.4.3 Ranges The maj or problem with pointers is thai a pointer doesn't "know" how many clcmems it points to. Consider: double· pd = new doublel1l; pd [2] = 2.2; pd [4] = 4.4; pd [- ll = - 1.1; Docs pd have a third element pd [2]? Does it have a liftll element pd [4J? If we look at the delinition o f pd, we lind that the answers arc yes and no, respectively. However, the compiler doesn't know that ; it docs not keep track o f pointer val· ues. Qur code will simply access memory as if we had alloc.'ued enough memory. It will even access pd[- ll as if the location three doubles berore what pd poilllS to was part of our allocation:
17. 4
581
FREE STO RE AND POINTERS
pd : pdl-31 :
pd l-21:
pd l-11 :
pdlOI:
pdl1l :
pd121:
-3.3
pd131 :
2.2
pd141 : 4.4
We have no idea what the memory locations marked pdI-3] and pd[4] are used ror, H owever, we do know that they weren't meant 1.0 be lIsed as pan or ollr array or three doubles pointed to by pd . Most likely, they arc p.1.rts o r other objects ,md we just scribbled allover those. That's not a good idea. In ract, it is typically a disastrously poor idea: "disas trous" as in "My program crashes m ystel'iously'" or "My program gives wrong output." T ry saying that alo ud ; it doesn't sound nice at all. We'll go a long way to avoid that. Out-of-range access is particularly nasty because apparently unrelated parts or a program arc affected. An OUt-or-rangc read brlves us it "" lI1dom" value that may depend o n som e completely unrelated computation. An out-of-rangc write can put some o bject into an "impossible" state or simply give it a totally unexpected and wrong value. Such writes typically aren't noticed until long arter they occurred, so they arc particularly hard to find. Worse slill: nm a program with an out-or-ra nge error twice with sligluly different input a m i it m ay give different results. Bugs or this kind ("transient bugs") are some or the most diffi cult bugs to find . We have to ensure that such Out-or-range access doesn't happen. O ne or the reasons we usc vector rather than directly using m emory alloc.-lI.ed by ne w is tllat a veclor knows its size so that it (or we) can easily prevent o ut-or-range access. One thing that can make it hard to prevent out-or-rangc access is that we can assign one double· to a nother do uble independently o r how many objects each points to. A pointer really doesn't know how many objects it points to_For example: do uble· p = ne w do uble; double* q = ne w do uble[1OOO]i q [700] = 7.7; q = p; do uble d = q[700];
/I allocate a double /I allocate 1000 dou bles
/I fine
II lei q point to the same as p /I out-of-range access!
H ere, in just three lines or code, q[700] rcrers to twO different memory 10Cl.ltions, and the last usc is an out-of-range access and a likely disaster.
Second value or q l j this destnlctor in tum invokes the destructor for its vector clements, ,md all is neatly cleaned up, leaving no object undestroyed and leaking no memory. Bcc.'luse d elete invokes destmctors (for types, such as vecto r, that have one), delete is often said to destroy objects, not JUSt deallocate them. k usual, please remember that a "naked" new o uts ide a constmctor is an opportunity to forget to de lete it. Unless you have a good (that is, really simple, such as Vector_,e f from § 13 .1O and §E.4) strategy for deleting objects, try to keep news in constmctors and de letes in destructors. So far, so good, but how do we access the members ofa vector, brlven only a pointer? Note that all classes support the operator. (dot) for accessing members, given the name of an object:
17.8
M ESS IN G WIT H TYPE S: VOIO' ANO CAS TS
vector v (4 ); int " = v.size(); double d = v_gel(3); Similarly, all classes support the operator - > (arrow) for accessing members, given a pointer to an obj ect: vector· p = new veclor(4); inl " = p->size(); double d = p->geH3); Like . (dot), -> (arrow) can be used for both data members and fu nction members. Since built-in types, such as inl and do uble , have no members, -> does n't apply to buih-in types. D OL and arrow are often called member access operatorJ.
17.8 Messing with types: void ' and casts Using pointers and free-slore-allocated arrays, we are very close to the hardware. Basically, our operations on pointers (initialization, assignment, -, and I J) map d irectly to machine instructions. At this level, the language alTers only a bit of notationa.! convenience and the compile-time consistency offered by the type system. O ccasionally, we have to give up even tlmt last bit of protection. Naturally, we don't wam to make do without !.he protection of !.he type system, but sometimes there is no logical altemative (e.g. , we need to interact with anotl,er language tlmt doesn't know about C++'s types). TI,ere arc also an unfortun ate number of cases where we need to interface with old code that wasn't designed with static type safety in mind. For that, we need twO things: A type of pointer that points lO memory without knowing what kinds of objects reside in lhat memory An operation to tell the compiler what kind of type to assume (withoUl proof) for memory pointed to by one o f those pointers 11,e type void" means "pointer to sOllle melllory that the compiler doesn't know the type of." We usc void - when we wam to transmit an address between pieces of code that really don't know each other's types . Exam plcs are the "address" arguments of a callback function (§ 16.3.1) and the lowest level of memory allocators (such as the implementation of the new operator). 'n lere arc no objects of type void , but as we have seen, we usc void to mean "no value relUrned": void v; void fO;
/I error: there are no objects of type void /I fO rclurns nothing - fO does not return an object of type void
(HAPTER 17 • VECTO R AND FREE STOR E
594
A pointer to any object type can be assigned to a void ". For example: void " pvl = new int i void" pv2 = new doubleflO];
/I O K: int· converts to void ' /! OK: double" converts to void"
Since the compiler doesn't know what a void" points to, we must tell it : void f(void " pv) {
void" pv2 = pv; double* pd = pV i ' pv = 7;
1/ copying is OK (copying is w hat void's are for) /I error: cannot conven void ' to double"
I! error: cannot dereference a void'
/! (we don't know what type of object it points to) 1/ error: cannot subscript a void' in to pi = static_cast(pv); II OK: explicit conversion II ... pv{2J = 9;
}
A static_cast can be used to explicitly convert between relaled pointer types, stich as void" and double (§A.5.7) . The name "static_cast" is a deliberately ugly name ror an ugly (and dangerous) opeJsucc Pi p->prev->succ = n ; n->pre v = p ->pre v; p ->prev = n: re turn n:
/I P comes after n /I n comes after what used to be p's predecessor /I p's predecessor becomes n's predecessor /I n becomes p's predecessor
111is works provided that p really points to a link and t1mt the link pointed to by p really has a predecessor. Please convince yourself that this really is so. Whe n t11inking abom pointers and linked structures, such as a list made out of links, we invariably draw litt1e box-and-arrow diagrams on paper to verify that o ur codc works fo r small examples . Please don't be too proud to rely o n this efTective low· tech design technique. That version of in sertO is incomplete because it doesn' t handle the cases where n, p, or p ->prev is O. We add the appropriate tests for the null pointer and gel the m essier, but COlTect, version:
600
C HAPTER 17 -
link - insert(link - p, link · n)
VE C TOR AND FREE STO RE
II insert n before p; relurn n
(
if (n==O) return Pi if (p==O) return n; n->succ = Pi II P comes after n if (p->prev) p->prev->s ucc = n j n->prev = p->prevj /I p's predecessor becomes n's predecessor II n becomes p's predecessor p->prev = n j return n j )
Given that, we could write link e norse_sods = new link("Thor ") i norse-8ods = inserl (norse....gods,new link(nOdin ")); norse-8ods = inserl (norse....gods, new Link(n Freia"»; Now all the error-prone liddling with the prey and succ poimers has disappeared from sight. Poimer liddling is tedious and error-prone and Jhouid be hidden in well-written and well-tested fun ctions. In panicular, many errors in conventional code come from people forgetting to test pointers against 0 - JUSt as we (deliberately) did in the lim version of insert() . Note that we used default arguments (§15.3.1 , §A.9.2) to save users from mentioning predecessors and successors in every constructor use.
17.9.4 List operations The standard library provides a list class, which we will describe in §20.4-. It hides all link manipulation, but here we will elaborate on our notion of list based on the link class to get a feci for what goes on "under the covers " of list classes and sec more examples of pointer usc. What operations docs our link class need to allow its lIsers to avoid "pointer liddling"? 111m's to some extent a matter of tasle, but here is a useful set: '11e constructor insert : insert before an element add : insert after an clement erase : remove an cIemem find : find a Link with a given value advance : get the 11th slIccessor We could write these operations like this:
17.9
POINTERS AND REFER ENC ES
link " add{link " p, link · n)
60'
/I inserl n after p; return n
{
1/ much like inserl (see exercise
11)
)
link " erase(link " p)
/I remove 'p from li sl; return
p's successor
{
if (p==O) return 0; if (p->su cc) p->succ- >prev = p->prev; if (p->prev) p->prey->succ = p ->succ; return p- >succ; )
Link" find (link · p. const string& s)
/I find s in list; /I return 0 for "nol
found ~
while (p) ( if (p->value == 5) return p; p = p ->succ ; )
return 0;
link" advance(link" p. int n)
/I move n posilions in lisl /I relurn 0 (or "not found "
/I posi1ive n moves forward, negative backward {
if (p==O) return 0; if «kn ) { while (n-- ) { if (p ->s ucc == 0) return 0; p = p->s ucc; ) )
if (nprev == 0) return 0; p = p->prev; )
return p; )
( HAPTER 17 • VECTO R AND FREE STO RE
602
NOle the lise of the postfix n++ . This form of increment ("posl·incremcm") yields the value before the incrcmelll as its value.
17.9.5 list use
ru a little exercise, let's build 1'.\10 lists: link· no rsc-!;ods
=ne w Link("Tho r");
no rsc....god s = insert( no rsc....gods,new Link(" Odin "»; no rsc....gods = insert(no rsc....gods,new link(" Zeus" »i
no rse....gods = inse rt(norsc....gods, new Link("freia "»: Link " greek....gods
=new Link(tl Hera
tl );
grec k....god s = insert(gree k....gods, new link("Ath ena ")): gree k-sod s = inserl(gree k....gods,new Link("Mars")); gree k....gods = insert(gree k....gods, new Lin k(II Poseido n"» ;
"Unfortunatcly," we made a couple of mistakes: Zeus is a Greek god, rather than a Norse god, and the Greek god of war is Ares, not Mars (Mars is his L1.tin/ Roman name). We can fIX that: Lin k- p = fin d (greek-J;ods, "Mars"); if (p) p->value = "Ares"; NOlC how wc wcre cautious about fin d O rcturning a o. Wc think that wc know that it can't happen in this case (aftcr all, we just inserted M ars into grcck_gods), but in a rcal example somconc might change that code. Similarly, we can move Zeus into his correct Pantheon:
Lin k- p = fi nd(norse-8od s, "Ze us") ; if (p) { e rase(p); inse rt(gree k-8ods, p); )
Did you notice the bug? It's quite subtle (unless you are used to working directly with links). What if the Link we e raseO is the one pointed to by norse _sods? Again, that doesn 't actually happen here, but to write good, maintainable code , we have to take that possibility into account: Link - p = find (no rse-8ods, "Ze us"); ;f (p ){ if (p==no rse-8ods) norse _god s = p ->succ;
17.10
THE THIS POINTER
erase(p); greek_gods = inserl(greek_gods, p); )
While we were at it, we also corrected the second bug: when we insert Zeus IxjQl"e the first Creek god, we need to make gree k--sods point LO Zeus's Link. Pointers are extremely useful and nexible, but subtle. Finally, let's print out those IisLS: void pri nt_all(Li nk- p) {
coul «"{ "; while (p) ( coul « p->value ; if (p=p->succ) coul « ", "; )
coul «" }";
prinCall(n orse--S0d s); cout«"\n"; print_aU(greek--sods) ; cout«"\n" ; 111is should give { Freia, Odin , Thor } { Zeus, Poseid on, Ares, Athena, He ra }
17.10 The this pointer Note that each of our list functions takes a l ink - as its first argument and accesses data in that object. That's the kind of fun ction that we oft en make member functions. Could we simplify Link (o r link lI SC) by making the operations members? Could we maybe make the pointers private so that only the member functions have access to them? We could: class Link ( public: string value;
603
CHAPTER 17 • VECTO R AND FREE STO RE
Link(const string& v, Link · p = 0, Link " s = 0) : value(v), prev(p), succ(s) ( ) Link " insert(Link " n) ; /I insert n before this object Link " add(Link" n) ; /I insert n after this object Link " erase() ; /I remove this object from list Link " (ind(const string& s); /I find s in list canst Link· find (const string& s) con st; /I find s in list Link " advance(int n) const;
/I move n positions in list
Link " nextO canst { return SUCC i } l ink " previou sO const ( return prev; ) private : link " prev; link " S UCC; );
This looks promising. We defined the operations that don't change lhe state of a link into canst member functions. \Ve added (nonmodifying) nextO and previous() functions so that users could iterate over lists (of Links) - mose arc needed now that direct access to succ and prev is prohibited. We left the value as a public member be· cause (so far) we have no reason not to ; it is "jUSt data." Now let's try 10 implement Link : :insertO by copying our previous global in sertO and modifying it suitably: Link · Link : :inserI(Link " n)
II insert n before p; return n
{
II pointer 10 this object II nothing to insert if (p==O) return n ; II noth ing to insert into n- >s ucc = Pi II P comeS after n ir (p->prev) p->prev->succ = n; n- >prev = p->prev; II p's predecessor becomes n's predecessor p->prev = ni II n becomes p's predecessor return n ;
Link " p = this;
ir (n==O) return p ;
)
But how do we get a pointer to the object fo r which Link :: insertO was called ? Without belp from the language we ea.n' t. However, in every member function. the identifier this is a pointer th at points to the object for which lhe member funelion was called. Alternatively, we could simply usc this instead o f p:
1 7. 10
605
THE T HI S PO INTER
Link - Link :: insert(Link- n)
/I insert n before this object; return n
{
if (n==O) return thi s; if (this==O) return n; n->su cc = this; II this object comes a(ter n if (t his- >prev) this- >prev->succ = n; n->prev = this->prev; /I this object's predecessor /I becomes n's predecessor this->prev = n; /I n becomes this object's predecessor return n i }
T his is a bit verbose, but we don't need to mention th is to access a member, so we can abbreviate: link - link: :insert(link - n)
II insert n before this object; return n
{
if (n==O) return this; if (this==O) return n; n->succ = this; /I this object comes after n if (prev) prev->succ = ni n- >prev = prey; /I this object's predecessor becomes n's prt"CIecessor prev = ni /I n becomes this object's predecessor return ni }
In other words, we have been using the this pointer - the pointer to the currelll objcct - implicitly every time we accessed a member. It is only when we need to refer to the whole obj ect that we need to mention it explicitly. Note tllat this has a specific meaning: it points to the object for which a memo ber fu nction is called . It docs not point to any old obj ect. The compiler ensures tlmt we do not change the value of this in a member function. For example: slruct S ( 1/ . .. void mutate(S - p) {
this = Pi II ... }
};
/I error: "this" is immutable
CHAPTER 17 - VECTOR AND FREE STORE
17.10.1 More link use Having dcalt wilh the implemcntation issues, we can see how the use now looks: Linke norse....gods = new Link( tlThor"); norse....gods = norse....gods->insert(new Link("Odin tl norse_god s = norse....gods->inserl(new Link(tlZeus tl norse....gods norse....gods->i nse rl(new Link(" Freia "));
=
»; »;
Linke greek....gods = new Link(" Heralt ); gree k....gods = greek....gods->inserl (new Link("Alhenalt grcek....gods = greek....gods->inserl (new Link("Marslt»; greek....gods = greek....gods->inserl(new Link("Poseidon lt ));
»;
That's very much like before. As before, we correct our "mistakes." Correct the name of the god of war: Link - p = greek....gods->find( HMars"); if (p) p->value = "Ares";
Move Zeus into his correct Pantheon: Linke p2 = norse....gods->find(" Zcus"); ;f(p2) ( if (p2==norse....gods) norse_sods = p2->nextO; p2->erase()i greek....gods = greek....gods->insert(p2); )
Finally, let's print out those lists: void prinl_all(Link- p) {
coul « "{ to; while (p) ( coul « p->valuei if (p=p ->ncxl ()) coul « ", " ; )
coul «
"}" ;
C H APTER 17 DR ILL
prinCall(norsc_sods); (out«''\n ''; pri nt_all(greek-8ods); cout«"\n"; 111is should again hrive { Freia, Odin , Thor) { Zeu s, Poseidon, Ares, Athena, Hera } So, which version do you like better: the one where insertO, etc. arc member fu nctions or the one where they are freestanding functions? In this case the dif· ferences don't matter much, but see §9.7.5 . One thing to observe here is that we still don't have a list class, o nly a link class. 11mt forces us to kecp worrying about which poimer is the pointer to the fi rst clement . \ oVe can do better than that - by defini ng a class List - but designs along the lines presented here arc very conmlo n. -The standard library list is presented in §20.4.
~ Drill 111is drill has twO parts. TIle fi rst exerciseslbuilds your understanding of freestore-allocated arrays and contrasts arrays with vectors: I. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Allocate an array of ten inls on the free store using new. Print the values of the ten ints to caul. Deallocate the array (using delete[ J). Write a fun ction print_array10(ostream& os, int· a) that prints out the values of a (assumed to have ten clements) to os. Allocate an array of ten ints on the free store; initialize it with the values 100, 10 I, 102, etc.; and print out its values. Allocate an array of II ints on the free store; initialize it with the values lOO, lO I, lO2, etc.; and print alit its values. Write a function prinCarray(ostream& as, int- a, int n) that prints out the values of a (assumed to have n clements) to as. Allocate an array of 20 ints on the free store; initialize it with the values 100, 10 1, 102 , etc.; and print out its values. Did you remember to delete the arrays? (If not, do it.) Do 5, 6, and 8 using a vector instead of an array and a print_vectorO in· stead of prinCarrayO.
607
CHAPTER 17 • VEC TOR AND FREE STORE
The second part focuses on pointers and their relation to arrays. Using print_array() from the last drill: l. Allocate an int , i11itialize it to 7, and assign its address to a variable pl . 2. Print out the value o f pl and of the int it points to. 3. Allocate an array of seven ints; initialize it to 1,2,4,8, etc.; and assign its address to a variable p2 . 4. Print out the value o f p2 and of the array it points to. 5. Declare an int · called p3 and uutialize it with p2. 6. Assign pl to p2 . 7. Assign p3 to p2. 8. Print out the values of p1 and p2 and of what they point 10. 9. Deallocate all the memory you allocated from the free store. 10. Allocate an array of ten ints; initiaJize it to 1, 2,4, 8, etc.; and assign its address to a variable pl . II. Allocate an array of ten ints, and assign its address to a variable p2 . 12. Copy the vaJues from the array pointed to by pl into the army pointed to by p2. 13 . Repeat 10- 12 using a vector rather than an array.
Review I. Why do we need data structures with varying numbers of elements? 2. What four kinds of storage do we have fo r a typical program? 3 . What is free store? What other name is commonly used for it? "\'\'hat operators support it? 4. What is a derefcrence operator and why do we need one? S. "What is an address? How are memory addresses manipulated in C++? 6. What infonnation about a pointed-to object does a pointer have? What useful information does it lack? 7. "\'\'hat Cc"1I1 a pointer point to? 8. What is a leak? 9. What is a resource? 10. How C
{O));
25 .(reinterpreCcast(P),SZ) i )
/I as before );
This is headache-inducing, but basically: ~nl e
oper:nor casts to Array_,ekcost Q > for every type Q provided we can cast an clement o f Array_rckY> LO an clement of Array_rekQ> (we don't use the result of that cast; we just check that wc can cast the clement types). We construct a new Array_rek const Q > by using brute force (rcinte rprcc casl) to get a pointer to the desired clement type. Brute-force solulions oft en cOlile at a cost; in tltis c.'lse, never use an Array_re f conversion from a class using multiple inheritance (§A.12.4). Note that const in Array_rekcon5t Q>: that's what ensures that we cannot copy a Array_rekco nst Q> into a plain old mutable Array_rekQ>.
\ Ve did warn you that this was "expert territory" and "headache-inducing." However, this version of Array_rcf is easy to use (it's only the definition/implementalion that is tricky): void f(S ha j>e- q, vcctor& s2) (
Po lygon - s1(10); Shape 52(20); /I initia lize Shapc · p1 = new Rectangle (Point(O,O),10); betler2(make _ref(sO»; II O K: converts to Array_rekShape ' consl> betle r2(make _ref(s1) ; II O K: converts to Array_rekShape'consl> betler2(make_,ef(s2»; /I OK (no conversion needed) betler2(make_ref(p1 ,1» ; II error betler2(make_ref(q, max» i /I error
rn le altempts to lise pointers result in errors because they are Shape s whereas better2() expects an Array_,ekShapc · >; that is, betler2() expects something that holds pointers rather than a pointer. If we want to pass pointers to betler2(), we have to put them into a container (e.g., a built-in array or a vector) and pass that. For an individual pointer, we could lise the awkward make_,ef(&p1 ,1)_However,
915
C HAPTER 25 • EMBEDDED SYSTEMS PR OG RAMM ING
9"
there is no solution for arrays (with morc than onc element) that doesn't involve creating a container of pointers to objects. In conclusion, we can creale simple, safe , easy-to-uSc, and efficient interfaces to compensate for the weaknesses of arrays. That was the major aim of this section. "Every problem is solved by another indirection" (quote by David Wheeler) has been proposed as "the fi rst law o f computer science," That was the way we solved this imcrfacc problem.
25.5 Bits, bytes, and words We have talked about hardware memory concepts, such as bilS, bytes, and words, before, but in general programming those arc nOt the ones we think much about. In stead we think in tenus of objects of specific types. SUdl as double, string, Matrix, and Simple_window. Here, we will look at a level of programming where we have to be more aware of the realities of the underlying memOll" 1f you are uncertain about your knowledge of binary and hexadecimal representations of integers, this may be a good lime to review §A.2.1.1.
25.5.1 Bits and bit operations ·n link of a byte as a sequence of 8 biLS: 7: 6: 5: 4: 3: 2: 1: 0:
J. JoJ. JoJoJ· JITD NOle the convention of numbering biLS in a byte rrom the right (the least signifi· cant bit) to the lert (the most significant bit). Now think or a word as a sequence or 4 bytes:
J
Oxll
J
0,'0
J
O,de
J
Oxad
Again , we number right 10 lert, that is, least significant byte to most significant byte. 111ese pictures oversimpliry what is round in the real world : there have been computers where a byte was 9 biLS (but we haven't seen one ror a decade), and machines where a word is 2 bytcs are nOt rare. However, as long as you remember to check your systems manual before taking advantage or "8 bits" and "4 bytes," you should be fme. In code meant to be portable, use (§24.2. 1) to make SUfe youI' assumptions abo ut sizes are co rrect. How do we represent a set of bits in C++? TIle answer depends a ll how mall)' bits we need and what kinds o f operations we want to be convenient and efficient. We call use the integer types as seLS o f bits :
2 5.5
BIT S, BYTES, AND WORDS
bool - I bit, but takes up a whole byte of space char - 8 bits short - 16 bits int - typically 32 bits, but many embedded systems have l6-bit inls long int - 32 bits or 64 bits 111e sizes quoted are typical, but d ifferent implementations Illay have different sizes, so if you need to know, test. In addition, the standard library provides ways of dealing with bits: sld ::veclor - when we need more than 8·sizeof(long) bits sld : :bilsel - when we need more than 8·sizeof(long) bits sid : :sel - an unordered collection of named bits (see §21.6.5) A file: lots of bits (sec §25.5.6) Furthennore, we can usc two language features to represent bits: Enumerations (enums); see §9.5 Bitfic1ds; see §25.5.5 ' 111is variety of ways to represent "bits" reflects the fact that ultimately everything in computer memory is a set of bits, so people have felt the urge to provide a variety of ways of looking at bits, naming bits, and doing operations on bits. Note that the built·in facilities all deal with a set of a fixed number of bits (e.g., 8, 16, 32, and 64) so that the computer can do logical operations on them at optimal speed using operations provided directly by hardware. In contrast, the standard libr:uy fa cilities all provide an arbitrary number of bilS. This may limit perfomlance, but don't prej udge efficiency issues: the library facilities can be - and often are - optimized to nm well if you pick a Ilumber of bits that maps well to the un· derlying hardware. Let's first look at the illlegcrs. For these, C++ basically provides the bitwise logical operations that the hardware directly implements. '111ese operations apply to each bit of their operands: Bitwise operations 0'
Bit n of xly is 1 ifbit n of x orbit n of y is I.
ood
Bit n of x&y is 1 if bit n of x and bil n of y is 1.
exclusive or
Bit n of x"y is 1 if bil n of x or bit n of y is 1 but not if bolh are 1.
«
left shifl
Bil n of xS is bil n-5 of x.
complement
Bit n of -x is the opposite of bit n of x.
&
,
917
.,.
C HAPTER 25 • EMBED DED SYS TEM S PR OG RAMMIN G
You might find the inclusion of "exclusive or" (" , sometimes called "xor") as a fundamental operation odd. However, that's the essential operation in much graphics and encryption code. The compiler won 't confuse a bitwise logical « for an output operator, but you might. To avoid confusion , remember that an output operator takes an ostream as its left-hand operand, whereas a bitwise logical operator takes an integer as its left-hand operand. Note that & difTers from && ,md I difTers from II by o perating individually all every bit of its operands (§A.5.5), producing a result with as many bits as its operands . In contrast, && and II jusl rctum true or raise. Let's try a couplc of examples. We usually express bit pattem s using hexadecimal notation. For a half byte (4 bits) we have
He
All other operators can be defined as member functions or as freestanding functions. Note that every user-defined type has = (assignment and initialization), & (address of) , and , (comma) defined by default Be restrained and conventional with operator overloading.
A.11 Enumerations An ellumeratiOIl defines a type with a set of named values (t:1IulIIeraJo/,,S): e num Colo r (green, yellow, red }; By defauh the value o f the first enumerator is 0, so that gree n==O, and the values increase by one. so that yellow==l and red==2 . It is also possible to expl icitly defin e the value of an enumerator: e num Day { Monday=l , Tuesday, Wedn esday}; Here, we get Monday==l , Tuesday==2, and Wednesday==3. NOle that enumerators arc not in the scope o f their enumermion but belong to its enclosing scope: int x = green; /I OK int y = Colo r: :green; /I error Enumerato rs and enumeration values implicitly convert to integers, but integers do not implicitly convert to enumeration lypes: inl x = green; Co lor c = green; c = 2; c = Color(2); int y = C;
II OK: implicit Color-la-in! conversion /10K // error: no implicit int-to-Color conversion II OK: (unchecked) cxplicit convcrsion 1/ OK: implicit Color-ta-int conversion
A.12
CLASSES
1071
Fo r a discussion of the uses of enumerations, see §9.5.
A.12 Classes A dms is a type fo r which the user defin es the representation of iLS objeclS and the operations allowed on those objecLS: class X ( public: /I user interface
private : /I implementation );
A variable, fu nction, or type defined within a class declaration is called a member o f lhe class. See C hapter 9 for class technicalities.
A.12.1 Member access A publi c member can be accessed by users; a private member can be accessed only by lhe class's own members:
class Date { public : /I.
int nexl_dayO; private : int y, m, d ;
}; void Dale : :nexCdayO { return d+1 ; }
/I OK
void f(Date d) (
int nd
=d .d+1;
II error: Date::d is private
1/ . . .
A strud is a class where members arc by default public: slrud S { /I members (public unless expl icitly declared private)
};
APPENDIX A • LANGUAGE SU MMARY
10n
For morc details of member access, including a discussio n of prote cted , see §14.3.4. Members of an object can be accessed through a variable or referenced using the . (dot) operator or through a pointer using the -> (arrow) operator:
slru ct Date { int d, m, y; int darO const { return d ; } /I defined in-class int month() const; /I just declared; defined elsewhere int yea r() canst; II just declared; defined elsewhere
}; Date Xi
x.d = 15; int y = x.dayO; Date* p = &x; p ->m = 7; int z = p ->month();
/I access through variable /I ca ll1hrough va riable
1/ access through pointer /I call through pointer
Members of a class can be referred to using the : : (scope resolution) opcramr: int Date: :yearO const { return Yi } 1/ out-of-class definition
Within a member function , we can refer to other members by their unqualified name: struct Date ( int d , m , y; int dayO consl ( re turn d; } /I .
}; Such unqualified names refcr to the member of the object for which the mcmber fUIlClion was called: void f(Date d1 , Date d2) {
d1 .dayO; d2.dayO; /I . .. }
1/ will access dl.d I/will access d2.d
A.1 2
ClAS SES
A.12.1.1 The this pointer If we wam to be explicit when referring to the object for which the member funccion is called, we ean use the predefined poilllcr this :
struct Date { intd , m,y; int mo nthO ca nst { return this->m; } II ... };
A mcmber function declared canst (a canst member function) cannOl modify the value of a member of the object for which it is called : struCi Date { int d, m, Yi int mo nth O canst { ++m; } /I error: monlhO is canst II ... };
For more information about canst member fun ctions, see §9.7.4.
A.12 .1.2 friends A function that is not a mcmber of a class can bc grallled access LO all members through a friend declaration. For example:
II needs access to Matrix and Vector members:
Vector o perator- (const Matrix&, consl Veclor&); class Vector ( fri e nd Vector ope rator -(const Matrix&, const Vector&); /I grant access II ... };
class Matrix { fri end Veclor operator-(const Matrix&, const Veclor&)i II grant access II ... };
1073
1074
APP ENDIX A • LANGUAGE SU MMARY
As shown, this is usually done for fun ctions that need to access two classes, AnOlher usc of friend is to provide an access function that should not be c.'d led using the member access syntax, For example: class Iter { public : inl distance_to(const iter& a) canst; friend int diHere nce(const Iter& a, const Iter& b); II . );
void f( lte r& p, lIer& q ) {
int x = p ,d istance_to (q); int y = differe nce(p,q);
II invoke using member syntax II invoke using "mathemalical synlax"
1/ , , , )
Note that a function dcclared fri e nd cannot also be declarcd virtual.
A.12.2 Class member definitions Class members that arc integer constants, functions, or types can be defincdlinitialized either ;1I-C1as.s or oul-o/-cIaJ.S: slru ct S { sialic const int c = 1; static consl inl c2; void fO { } void f20 ; struct SS { int a; }; slru ct SS2; );
The members that were not defined in-class must be defined "elsewhere": constint S:: c2 =7; void S: :f20 { } slru ct S: :SS2 { int m; };
A. 12
( LA SS ES
107S
TIle stati c canst int members arc an odd special case. TIley just derUle sym bolic integer constaills and do not take up memory in the object. Non·static data memo bers do not require separate definition , cannot be separately defined, and cannot have in·class initializers: strucl X { inl Xi int y=7; sialic inlz = 7i Sialic consl string ae = "7" ; static const inl oe = 7;
/I error: non·slatic data members /I cannot have in·elass initializers /I error: non·const data members
1/ cannot have in-class initializers /I error: non.integrallypc /I cannot have in-class initial izers /I OK: slatic canst integral type
};
inl X::x = 7; /I error: non-stalic data members cannot be defined oul-of-class If you want to ensure initialization of non-Siali c, non·consl data members, do it
in constJ"tlctoTS. Function members do not occupy space in an object: struct S { int m; void fO; };
Here, sizcof(S)==sizof(i nt) . TIlat's not actually guaranteed by the standard, but it is true for all implementations we know of. But nOte that a class with a virtual function has one "hidden" member to allow virtual calls (§ 14.3. 1).
A.12.3 Constru ction, destruction, and co py You can define the meaning of i.nitialization for an object of a class by defining one or more amJ/rucJors. A constructor is a member fun ction with the same name as ilS class and no return type: class Date { public: Oate(int yy, int mm , int dd) :y(yy), m(mm), d(dd) { } II ... private : int y, m,d;
};
1076
AP P ENDIX A • LANGUAGE SUMMA RY
Date d1 (2006,11, 15); Date d2; Date d3(11 ,15);
II OK: initialization done by the constructor /I error: no initializers /I error: bad initializers (three initia lizers required)
Note thai data members can be initialized by using an initializer list in the constructor (a base and member initializer list). Members will be initialized in the order in which they arc declared in the class. C onstructors are typically used to establish a class's invanalll and to acquire resources (§9.
file streams (§S.7. 11
string streams (§ B.7. 1)
declare (but don', define) 110 stream fa cilities
I/O streams base classes
random number generation (C++Ox)
numeric arrays
< numeri c>
generalized numeric algorithms, e.g., accumulateO (§B.9.5)
numerical limits (§B.9.1)
3. 1
'09'
OVERVIEW
Utility and language support
exception types (§B.2.1)
exception hierarchy (§B.2. 1)
culture-specific formatting
standard type information (from typeid)
allocation and deallocation functions
C standard libraries
C-style string manipulation (§B. l 0.3)
C-style 1/0 (§B.l 0.2)
clockO, time(), etc. (§B. l 0.5)
standard floating-point math fu nd ions (§B.9.2)
elc. functions: abortO, abs(j, malloc(), qsorl(), etc. (Chapter 27)
C-style error handling (§24.8)
assert macro (§27.9)
culture-specific formalling
C-style numerical limits (§8.9.1)
C-style floating-poi nt limits (§B.9.1 )
C language support; size_I, etc.
macros for variable argument processing
slejmp() and longjmpO (never use those)
signal handling
wide characters
character type classification (§B.8. 1)
wide character type classification
For each of the C standard librmy headers, there is also a version witholll the initial c in its name and with a trailing . h, such as for . 111e .h versions define global names rather than names in names pace std. Some - but not all - of the facilities defined in these headers are described in the sections below and in the chapters. If you need more information, look at your online documentation or an expert·level C++ book.
AP P ENDIX B • STANDA RD LIBRARY SUMMARY
1098
B.1.2 Namespace sId The standard library facilities a rc defin ed in namcspacc Sid, so to usc them, you need an explicit qualification, a using declaration, or a using directive : sid : : slring s;
/I explicit qualifica tion
using sid : :veclof;
II using declaration
veclorv(7);
using namespace sid ; map m;
II using directive
In this book, we have used the using dircClivc for sid . Be very fm gaJ with using directives ; sec §A.15.
8.1.3 Description style A fu ll description of even a simple standard library operation, such as a cons tructor or an algorithm, can take pages. Consequently, we usc an extremely abbreviated sty le o f prcsemation. For example: Examples of notatio n
p=op(b,e,x)
op does something to the range Ib : e j and x, returning p .
foo(x)
foo doc'S something to x, but returns no result.
bar(b ,e ,x)
Does x have something to do with Ib :e jr
We cry to be mnemonic in our choice of idemifiers, so b,e will be iterators specifying a range, p a poimer or an iterator, and x some value, all depending Oil COIl text. In this notation, only the commentary distinguishes no result from a Boolean result, so you can confuse those if you try hard enough. For a n operation retuming bool, lhe explanation usually ends with a question mark. Where an algorithm foll ows the usual pattem o f returning the end of an inpm sequence to indicate "failure," "not found ," etc. (§B.3. 1), we do not mention that explicitly.
B.2 Error handling The standard library consists of components developed over a period of almost 40 years. 111l1s, their style and approaches to error handling are not consistent.
B.2
ERROR HANDLING
Gstyle libraries consist of functions, many of which set e rmo to indicate that an error happened; see §24.8. Many algorithms operating on a sequence of clements return an iterator to the one-past-the-Iast clement to indicate "not found " or "fail ure." The 110 streams library relies on a state in each stream to reflect errors and may (if the user requests it) throw exceptions to indicate errors ; see
§' O.6, §B.7.2. Some standard library components , such as vector, string, and bitset, throw exceptions to indicate errors. TIle standard library is design ed so that all facilities obey "the basie guarantee'" (sec §19.5.3); that is , even if an exception is thrown, no resource (such as memory) is leaked and no invariant for a standard library class is broken.
8,2,1 Exceptions Some standard library faci lities rcpon errors by throwing exceptions: Standard library exceptions bitset
throws invalid_argument, ouCoCrange, overflow_error
dynamic_cast
throws bad_cast if it cannot perform a conversion
iostream
throws ios_base : :failure if exceptions are enabled
new
throws bad_alloc if it cannot allocate memory
regex
throws regex_error
string
throws length_error, ouCoCrange
typeid
throws bad_typeid if it cannot deliver a type_info
vector
throws ouCoCrange
"I11ese exceptions may be encountered in any code that directly o r indirccuy uses these facilities. Unless you ImUla that no facility is used in a way that could throw an exception, it is a good idea to always catch one o f the root classes of the standard libnuy exception hierarchy (such as exception) somewhere (e.g. , in mainO). We strongly recommend that yOLl do not throw built-in types, such as int and C-slyle strings. Instead , throw objects of ty pes specifically defined to be used as exceptions. A class derived from u1e standard library class exception can be used for that: class exce ption { publi c:
1099
APPEND IX B • STANDARD LI BR ARY SU MMARY
1100
cxceplio n(); exceplio n (con st exception&)i
exceplio n& o perato r=(co nsl exceptio n&); vi rtual -exceptionO; vi rtual const cha r· what() const; };
The whatO fun ction can be used to obtain a string that is supposed to indicate something about the error that caused the exception. This hierarchy of standard exception classes may help by providing a classifi· cation of exceptions:
--Iensth--
-
--
You can define an exception by deriving from a standard library exception like this: struet M y_erro r : run l ime_error { M y_erro r (int x): interesti n&-.value(x) () inl inlerestins-valu ei
consl cha r· whatO const { re turn "My_e rro r"; }
};
B.3 Iterators Iteralors arc the glue that lics standard library algorithms to their data. Conversely, you can S3Y that iterators are the Illechanism used to minimize an algorithm's dependence on the data structures on which it operates (§20.3):
B. 3
ITERATO RS
1101
sort, find , search, copy, . .. , my_very_own _algorithm, your_code, ...
vector, list, map, array, ... , my_container, your_container, .. .
B.3.1 Iterator model An iterator is akin to a poimer in tbat it provides operations for indirect access (e.g., • for dercferencing) and for moving to a new clement (e.g., ++ for moving to the next clement). A sequence of clements is defined by a pair of iterators defining a half-open range [begin: end):
TImt is, begin points to the first element of the sequence and end points to one beyond the last elemelll of the sequence. Never read from or write to ·end. Note that the empty sequence has begin==end ; that is, [p : p) is the empty sequence for any iterator p. To read a sequence, an algorithm usually takes a pair of iterators (b ,e) and iterates using ++ until the end is reached: whi le (b!=e) { /I use! = rather than < /I do something ++b ; /I go to next element )
Algorithms that search for something in a sequence usually return the end of the sequence to indicate "not found "; for example: p = find(v.begin (),v.end (),x); if (p!=v.end(» { II x found at p
II look for x in v
)
else { 1/ x nOt found in Iv.begin() :v.end()) )
11 02
APPENDIX B • STANDARD llBRARY SUMMARY
So< §20.3. Algorithms that write to a sequence orten arc given only an itcrator to its first clement. In that case, it is the programmer's responsibility not to write beyond the end of that sequence. Fo r example: template void (Iter p, int nl {
while (n>O)" p
= --n;
}
veclor v (10);
f(v.begin(), v.s ize()); f(v. beginO, 1000);
/10K /I big trouble
Some standard library implementations range check - that is, throw an exception - for that last call o f (0 , but you can't rely on that for portable code; many implementations don't check. 111C operations on iterators arc:
Iterator operations
++p
Pre-increment: make p refer to the next element in the
sequence or to one-beyond·thc-Iast-elemcilt (~a dvance one element"); the re§ulting value is p+1 .
p++
Post-increment: make p refer to the next element in the sequence or to one-beyond·the-Iast-element ("advance one elemcnn; the resulting value is p (before the increment).
--p
Pre-decrement; make p point to previous element ("go back one element"); the resulting value is p - 1.
p--
Post-decrement: make p point to previous element (~go b.lck one element"); the re§uiting value is p (before the decrement).
'p
Acce§s (dereference): "p refers to the clement pointed to by p .
pin]
Acce§s (subscripting); pin] refers to the element pointed to by p+n; equivalent to "(p+n).
p- >rn
Acce§s (member access); equivalent to (·pl.m .
p==q
Equality: true if p and q point to the same element or both point to o ne-beyond-the-Iast-element.
p! =q
Inequality: ! (p==q ).
B.3
lTERATORS
1103
Iterator operations (continued)
p=q
p>q
p+=n
Advance n: make p point to the nth element after the one it points to.
p -=n
Advance - n: make p poinl to the nth element before the one it points 10.
q=p+n
q points to the nth element after the one pointed to by p.
q=p-n
q points to the nth element before the one pointed to by p; afterward, we have q+n==p.
advance(p,n)
Advance: like p+=n; advanceO can be used even if p is not .1 random-access iterator; it may take n steps (through a lis!).
x=difference(p,q)
Difference: like q-P i differenceO can be used even if p is not a random-access iterator; it may take n steps (through a list).
II p==q
Note that nOI every kind of iterator (§B.3.2) supports every ileralor operation.
8.3.2 Iterator categories TIle standard library provides five kinds of iterators (five I; iterator categories"): Iterator categories input iterator
We can iterate forward using ++ and read each element once only uSing · . We can compare iterators usi ng == and !=. This is the kind of iterator that islream offers; see §21.7.2.
output iterator
We can iterate forward using ++ and write each element once only using ' . This is the kind of iterator that ostream offers; see §21 .7.2.
forward iterator
We can iterate forward repeatedly using ++ and rcad and write (unless the elements are consl) elements using · . If it points to a class object, it can use -> to access a member.
1104
APPENDIX B • STANDARD LI BRARY SU MMARY
lIerato, categories (continued )
We can iterate fOl'\va rd (using ++) and backward (using --)
bidirectional iteratar
and read and write (unless the elements arc const)
elements using
*,
This is the kind of iterator that list, map.
and set offer.
randomaccess iteratar
We can iterate forwa rd (using ++ or +=) and backward (using - or -=) and read and write (unless the elements are consl) elements using · or n. We can subscript, add an integer to a random-access iteralor using +. and subtract an integer using - . We can find the distance between two random-access iterators to the sa me sequence by subtracting one from the other. We can compilre ilcrators using = .1his is the kind of iterator that vector offers.
-
Logically, these iterators arc organized in a hierarchy (§20.8):
Input-
.........
_ ....
Nme that since the iterator categories are not classes, this hierarch y is nm a class hierarchy implemented using derivation. If you need to do something advanced with iterator categories, look fo r ilerator_trails in an advanced reference. Each container supplies iterators of a specified category: vector - random access list - bidirectional deque - random access bitsel - none
11.'1
1105
CONTA INERS
set - bidirectional mulliset - bidirectional map - bidirectional multima p - bidirectional uno rdered _set - forward uno rdered multiset - forward unordered_map - fonvard un ord ered_multimap - fonvard
B.4 Containers A container holds a sequence o f objects. The clements of the sequence are of the member type called value_t ype. The most commonly usefu l containers are: Sequence containers array
fixed-size array of N elements of type T (C . . Ox)
deque
double-ended queue
list
doubly-l inked list
vector
dynamic array of elements of type T
Associative containers map
map from K to V; a sequence of (K,V) pairs
multimap
map from K to V; duplicate keys allowed
set
sel of K
muJtiset
set of K (duplicate keys allowed)
unordered_map
map from K to V usi ng a hash function (C++Oxj
unordered_multi map
map from K to V using a hash fun ction; duplicate keys allowed (C++Ox)
unordered_set
set of K using a hash function (C . . Ox)
unordered_multiset
set of K using a hash function; duplica te keys allowed (C++Oxj
APPENDIX B • STA NDARD LIBRARY SUMMA RY
1106
Containe r adaptors priority_que ue
priority queue
queue
queue with pushO and popO
stack
stack with pushO and popO
111csc containers arc defined in second« '\n'; We could equivalently havc used: pair pp = make_pair(m.lower_bound(k),m.uppe r_bound(k»; However, that would take about nvicc as long to execute. TIle equal_range, lower_bo und, and upper_bound algorithms are also provided for sorted sequences (§B.5.4). TIle definition of pair is in § B.6.3 .
8.5 Algorithms "There are about 60 standard algorithms defined in . TI1CY all opel" ate on sequences defi ned by a pair of iterators (for inputs) or a single iterator (for outputs). When copying, comparing, etc. two sequences, the first is represented by a pair of iterators [b:e) but the second by just a single iterator, b2, which is consid· ered the start of a sequence holding sufficient elements for the algorithm, for ex· ample, as many clements as the first sequence : [b2:b2+(e-b»). Some algorithms, such as sort, require random-access iterators, whereas many, such as find , only read lheir elements in order so that they can make do with a forward iterator.
B.5
ALGO RI THM S
1113
Many algorithms rollow the usual convention o r returning the end or a se· quence to represent "not round." We don' t mention that ror each algorithm.
B.S.l Nonmodifying sequence algorithms A nonmO(:liryillg algolithm juSt reads the clements or a sequence; it does not rearrange the sequence and docs nOt change the value o r the elements: No nmodify ing seque nce algorithms f=fo r_each(b,e,O
Do f for each clement in [b :e); return f.
p=find (b,e,v)
p points 10 Ihe first occurrence of v in [b :e).
p=find_if(b,e ,O
p points to the first clement in [b :eJ so that W p).
p=find_firsCof(b,e,b2,e2)
p points 10 the first element in [b :e) so that "p=="q for some q in [b2:e2).
p=fin d_firscof( b,e,b2,e2,O
p poi nts to the fi rst clement in [b :e) so that «. p, "q ) for some q in [b2:e2).
p=adjacenC find (b,e)
p points to the first p in [b :e) such that · p=="(p+l ).
p=adjace nC find (b,e,O
p points to the fi rst p in (b :e) such that f(·p, "(p+l » .
equaHb,e ,b2)
0 0 all elements of [b :e) and [b2: b2+(e-b)) compare equal ?
equal(b,e,b2,f)
Do all elements of [b :e) and [b2: b2+(e-b») compare equal using {(" p, "q ) as the test?
pair(pt ,p2)=mismatch(b,e,b2)
(pl , p2) points to the first pai r of ele ments in Ib :e) and [b2: b2+(e- b» for which !(" pl ==" p2).
pair(p 1,p2)=mismatch(b,e, b2,f)
(pl , p2) points to the first pair of elements in Ib :e) and (b2 :b2+(e-b» for which !Wpl , "p2).
p=search(b,e, b2,e2)
P points to the first . p in [b :e ) such that . p equals an element in Ib2 :e2).
p=search(b.e,b2,e2,f)
p points to the first . p in [b :e ) such that {(- p, 0q ) for an element "q in Ib2: e2).
p=find_e nd(b,e, b2,e2)
p points to the last · p in [b :e) such that · p equals an element in Ib2:e2).
p=find_end( b,e,b2,e2,f)
p points to the lasl . p in [b :e) such that f(- p: q ) for an ele ment 0q in [b2: e2).
p=search_n(b,e, n,v)
p points to the first element of Ib :e) such that each element in Ip :p+n) has the value v.
p=search_n(b,e, n,v,f)
p points to the first element of Ib :e) such that for each element "q in [p :p+n) we have f(O q,v) .
x=counl(b,e,v)
)( is the number of occurrences of v in Ib :e).
x=counC if(b,e,v,f)
x is the number of elements in Ib :e) SO that W p,v).
APPEND IX B • STANDARD LIBRARY SUMMARY
1114
Note that nothing stops the operation passed to fO f_each from modifying clements ; that's considered acceptable. Passing an operation that changes the clements it examines to some other algorithm (e.g. , count or ==) is not acceptable. An example (of proper use): bool odd(int xl { fe turn x&l ; } int n_even(const vecto r& v)
/I count the number of even values in v
{
re turn v.s ize()- counUf(v.begin O,v.e ndO,odd); }
B.5 .2 Modi fying sequence algo rithms The modifying algorililllls (also called /JIulaling Jequenu algorilhllu) can (and often do) modify the clements of their argument sequences.
Modifying sequence algorithms p=tra nsform(b,e,out,f)
Apply · p2=f(-p1) to every · pl in Ib :e) writing to the corresponding · p2 in [o ut :out+(e- b)); p=out+(e- b)
p=lra nsform(b,e, b2,out,f)
Apply · p3=W pl , · p2) to every element in "pl in Ib :e) and the corresponding element "p2 in Ib2:b2+(e-b» , writing to . pJ in [out :oul+(e- b»; p=oul+(e-b)
p=eopy(b,e,out)
Copy [b :e) to [OUI :p).
p=copy_baekward(b,e,out)
Copy Ib: e) to loul :p) starting with its last element.
p=unique(b,e)
Move elements in [b :e) so that Ib :p) has adjacent duplicates removed (== defines ~duplicale~).
p=unique(b,e,f)
Move elements in Ib: e) SO that Ib:p) has adjacent duplicates removed (f defines "duplicate"').
p=unique_eopy(b,e,out)
Copy Ib:e) to 10ut :p); don't copy adjacent duplicates.
p=uniquc3 0py(b,e,oul,f)
Copy [b:e) to lo ul :p); don't copy adjacent duplicates (f defines "duplicate").
replaee(b,e,v,v2)
Replace elements "q in jb :e) for which °q==v with v2.
replaee(b,e,f,v2)
Replace elements 0q in Ib:e) for which f(·q) with v2.
p=replace_eopy(b,e,out,v,v2)
Copy Ib :e) to [o ul :p), replacing elements "q in [b:e) for which "q=v with v2.
B.5
ALGORIT HM S
111 5
Modifying sequence algorithms (continued ) p=re place_copy(b.e.out.f.v2)
Copy Ib :e) to lo ut :p), replacing clements *q in Ib:e) fOf which Wq) with v2.
p=re move(b,e.v)
Move elemenls *q in Ib :e) so Ihal lb :p) becomes the elements (Of" which W q==v).
p=re move(b,e.v,f)
Move elements *q in Ib :e) so that Ib :p) becomes the elements (Of" which !W q).
p=re move_copy{b,e.out,v)
Copy elements from Ib:e) for which !(Oq==v) to 10ut :pJ.
p=re move_copy_if( b,e,out,O
Copy elements from Ib :eJ for which !f(*q,v) to lout :p).
reverse(b,e)
Reverse the order of elements in [b :eJ.
p=reverse_copy(b,e,out)
Copy Ib :e) into lout: p) in reverse order.
rotate(b,m,e)
Rotate elements: treatlb :e) as a ci rcle with the first element right after the last. Move °b to om and in general move "(b+i) to "« b+(i+(e- m))%(e- b)) .
p=rotate_copy(b,m,e,out)
Copy (b :e) into a rotated sequence lo ul :p).
random_shuffle(b,e)
Shuffle elements of lb :e) into a distribution using the default uniform random number generator.
random_shuffle(b.e,O
Shuffle elements of [b :c) into a distribution using f as a random number generatOf".
A shu me algorithm shumes its sequence lUuch in the way we would shume a pack of cards; that is, after a shume, the elements are in a random o rder, where «random" is defi ned by the d istribution produced by the random number generator. Please note that these algorithms do not k.now if their argument sequence is a container, so they do not have the ability to add or remove clements. TIlliS, an algoritiuu such as re move cannot shorten its input sequence by deleting (eras ing) clements; instead , it (re)moves the clements it k.eeps to the front of lhe sequence:
typcdef vecto r : :ite rator VIi i void p rin ,-d igits(co nst string& 5, VII b, VII e) {
cout « Sj while (b! =e) {cout « °b j ++b;} cout « '\n';
APPENDIX B • STANDARD liBRARY SUMMARY
111 6
void ffO {
int aU = { 1,1,1, 2,2, 3, 4,4,4, 3,3,3, 5,5,5,5, 1,1,1 }; vector v(a,a+sizeof{a)/sizeof(in I»; print_digits("all : ",v.beginO, v.e nd{»; vector : :iterator pp = unique(v.begin (),v.end{»; prinCdigits(" head : ,v.beginO, pp) ; prinCdigits(" tail : ",pp,v.end()); II
Pl>= remove(v. begin (), pl>,4); prin C digits(" head: II ,v.beginO, pp); I>rin C digits{" tail: ",pp, v. e ndO); )
TIle resulting output is all:
1112234443335555111 head : 1234351 tail : 443335555111 head : 123351 tail : 1443335555111
B.S.3 Utility algorithms Technically, these utility algOli!.hms are also modifying sequence algorithms, but. we thought it a good idea to list them separately, lcst they get overlooked. Utility algorithms swap()(,y)
Swap )( and y.
iter_swal>(p,q)
Swap .p and . q.
swap_,anges(b,e,b2)
Swap Ihe elements of Ib :e) and [b2:b2+(e-b».
fill (b,e,v)
Assign v to every element of [b:e).
fiICn (b,n,v)
Assign v to every element of [b : b+n).
generate(b,e,f)
Assign fO to every element of [b :e).
generate_n(b, n,f)
Assign fO to every element of [b:b+n).
uninitialized_fill (b,e,v)
Initialize all elements in [b:e) with v.
uninitialized_copy(b,e,out)
Initialize all elements of loul :out+(e-b)) with the corresponding element from Ib :e).
(l .S
ALGORIT HM S
111 7
Note that uninitialized sequences should occur only at the lowest level of programming, usually inside the implementation of containers. Elements that are targets of uninitialized_fill or uninitialized_copy must be of built-in type or uninitialil.ed.
B.5.4 Sorting and searching Sorting and searching are fundamental and the needs of programmers arc quite varied. Comparison is by default done using the < operator and equivalence of a pair of values a and b is detennined by !(a(matchti,ll ll l Inlfleld3 . (rOlu_l lrlnsclnl>( nlIlIChcI13J)1 /I , , ,
syntax or rcgular cxpressions is based on characters with special meaning (Chaptcr 23):
rnlC
Regular expression special characters any single character (a uwildcard") character class count begin grouping end grouping
I
next character has a special meaning
•
zero or more
•
one or more
1134
AP PENDIX B • STANOARD LIBRARY SUMMARY
Regular expression special characters (continued ) l
optional (zero or one) ahernative (or)
start of line; negation
$
end of line
Repetition (n )
exactly n times
( n, )
n or more times
( n ,m)
at least n and al most m times zero Of more, that is,
to,}
+
one or more, that is, {I ,}
l
optional (zero or one), that is (O, l )
Character classes
alnurn
any alphanumeric character or the underscore
alpha
any alphabetic character
blank
any whitespace character thaI is not a line separator
cntrl
any control character
d
any decimal digit
digit
any decimal digit
graph
any graphical character
lower
any lowercase character
print
any printable character
pund
any punctuation character
,
any whilespace c haracter
space
any whitespace character
upper
any uppercase character
w
any word character (alphanumeric characters)
"digit
any hexadecimal digit character
0 .9
NUMERI CS
1135
Several character classes are supported by shorthand notation : Charader class a bbrevialions
III
a decimal digit
~
a lowercase character
lI,dlglllll II I lowtirt 11
"
a space (space, lab, elc.)
Ul8paftli U
Iu
an uppercase character
Ifl1lfJpa t ill
Iw III 11
a letter, a decimal digit,
IS IU IW
0(
an underscore Cl
II hlll1l1m lll
not \d
1' 111/1811 '11
not \I
[AlllowClfllI
not \!!
1"(u pltc:tHII
not \u
IAlluPPCirtlJ
nol \w
l"IHtlnllm lll
B.9 Numerics "n e c++ standard librmy provides the most basic building blocks for mathemat· ical (sciemific, engincering, elc.) calculations.
B.9.1 Numcricailimiis Each C++ implementation spccifies properties of the built·in types, so that pro· grammers C'1n usc those properties to cl1eck against limiLS, set sentincls, etc. From , we get 1111nlerl cJlmili for each built-in o r library type T. In addition, a programmer can define num eric Ilmll i for a user·d efm ed nu· meric type X. For example: cia:,. nume,' J".. Ilhic floal> { I)ublici ' IMlc con i l booll j_i pl.lclalll{!d • "U{!J
, Ialic (on lll Itll rAdii, . 2; If b.1M.! o( CKlxJftcnt (hI thl ~ t t.l M.', blllJry) . lililc cOl1 j l Inl dlghi • 24 ; If nUfni:lcr or t.ltll>: dll!1t~ In nhllltlu.1 j Ulllc onllllni dlglli10 . 6, If numher or b.l§c· 10 d igi ts 111 rtll1tlllss,1 j lililc con81 booll!l_i lg"tld • lruell italic eM 81 bfu.lII!lJ nltgt f . (A l u~, 8liulc con81 bool1 8~l! lIIe l • (ali e,
1136
APP ENDIX B • STANOARD LIBRARY SU MMARY
static float minO { return 1.17549435E-38F; } static float maxO { return 3.40282347E+38F; }
/I example value
"example value
static float epsilonO { relurn 1.19209290E-07F; } 'I example value II example value static float round_crrorO { return O.5F ; } static float slatic float static float sialic float
inrinit yO { return , - some value -I; } quieCNaN (} { return ,- some value -I; } signaling.,NaN(} { return , - some value -I; } denorm_min(} { return minO; }
static consl int static consl int static consl int slatic const inl
min_exponent = -125; min_exponent10 = -37; max_exponent = +128; max_exponenltO = +38;
/I example /I example /I example /I example
value value value value
stati c const bool hasj nfinity = true; slatic const bool has_quieCNaN = true ; static const bool has_signaling.,NaN = true ; static co nsl floa Cdenorm_style has_d enorm = d enorm_absent ; static consl bool has_d enorm_loss = false ; static const bool isjec559 = true; /I conforms to IEC·559 stati c co nsl bool is_bounded = true ; static co nsl bool is_modulo = false; slatic consl boo llraps = Iruc; static const bool tinyness_bcfore = tru e;
);
From and dloat.h>, we gel macros specify ing key properties of inte' gers and floating·point numbers, including: limit macros CHAR_8IT
number of bits in a char (usually 8)
CHAR_MIN
minimum char value
CHAR_MAX
maximum char va lue (usually 127 if char is signed and 255 if char is unsigned) smallest int value largest int value
8.9
NUMERICS
1137
Limit macros (continued ) LONG_MIN
smallest int value
LONG_MAX
largest int va lue
FLY_M I N
smallest positive float value (e.g., 1.175494351 e-38F)
FLY_M AX
largest float value (e.g., 3.402823466e+38F)
FLY_DIG
number of decimal digits of precision (e.g., 6)
FLT_MAX_10_EXP
largest decimal exponent (e.g., 38)
D8L_MIN
smallest d o uble value
DOL_MAX
largest double value (e.g., 1.7976931348623158e+308)
DBL_EPSILON
smalleslsuch IhaI 1.0+D8L_EPSILO N! = 1.0
B.9.2 Standard mathematical functions '111C standard library provides the most common mathematical fun ctions (defined in and =
fl oor(x)
largest integer and the allocation rUllctions in . See also §27.5.2.
8.10.5 Date and time In , yOli can find several types and runctions related to date and time. Date and lime Iypes an arithmetic type for holding short ti me intervals (maybe just intervals of a few minutes) IImtU
an arithmetic type for holding long time intervals (maybe centuries)
1m
a , Iru el for holding date and time (since year t 900)
1147
APPENDIX B • STAN OARO LIBR A RY SU MMAR Y
1148
slruct 1m is defined like this: slruct 1m { int 1m_sec; 1/ second of minute [0:61 I; 60 and 61 represent leap seconds int 1m_min i /I minute of hour [0,591 int 1m_hour; 1/ hour of day 10,231 int Im_mda y; 1/ day o f month 11,3 1 J int Im_mon ; /I month of year (0, 111; 0 means January (note: not [1 : 121 ) int 1m_year; 1/ year si nce 1900; 0 means year 1900, and 102 means 2002 int tm_wdaYi 1/ days since Sunday 10,6]; a means Sunday int Im_yday; /I days since Ja nuary 1 [0,3651; 0 means January , int tmjsdsl j /I hours of Daylight Savings Time
J; Date and time functions : II number of clock ticks since the start of the program
cloc k_1 doc kO;
lime_t time(time_t - pi); 1/ CUffent calendar time d o uble diiftimeU ime_t 12, time _t 11 ); 1112- 11 in seconds
1m· locaUime(consl time _l - pI); II loca l time for the ·pt Im * gmtime (consl lime_I· pt); II Greenwich Mean Time (GMn tm for 'Pt, or 0 lime_t mktime (tm * ptm); cha r · as ctime(const tm · plm); II C-style string representation for ·ptm cha r · clime(consl time_l - I) ( relurn asclime (iocallime(t)); )
An example o r the result o r a call o r asclime() is "Su n Sep 16 01 :03:52 1973\0" . H ere is a n exa mple o r how clo ck can be u sed to tim e a runction (do_something()) : int main(int a rgc, char- a rgv[]) {
inl n = a lo i(argv[l l);
=
clock_I t1 clockO; /I start time if (tl == cloc k_t{- l )) ( II clock_t(- I ) means "clockO didn't work" cerr « "sorr y, no doc k\n"; exit(1) ;
B.IO
C STANDARD LIBRARY FUNCTIONS
1149
for (int i = 0; i Microsoft Visual Studio 2005 > Microsoft VISUal Studio 2005. Open the File menu , point to New, and click Project. Under Project Types, select Visual C++. In the Templates section, select Wm32 Console Application. In the Name text box type the name of your project, for example, Hello,World!. C hoose a directory for your project. The default, C :\Documents and Scttings\Your Name\My Documents\Visual Studio 2005 Projects, is usually a good choice. Click OK. TIle WI N32 Application Wizard should appear. Select Application Settings on the left side of the dialog box. Under Additional Options select Empty Project. Click Fmish. All compiler settings should now be initialized for your console project.
C.3.2 USC the stdJ lb_lacltitie .h hc~dcr file For your fIrst programs, we strongly suggest that you use the custom header file iilet IIb_'acllllle" h from WW\'1.stroustrup.com/progranuninglstd_libJacilities. h.
1153
1154
APPENDIX C • GETTING STARTED WITH VISUAL STU DIO
Place a copy of it in the directory you chose in §C.3. 1, step 6. (Note: Save as text, IlOt HTML.) To usc il, you need the line
#include " . .I.Jstd_lib_faci lilies. h" in your program. The " .J..r tells the compiler that you placed the header in C:\Documents and Settings\Your Name\My Documents\Visual Studio 2005 Projects where it can be used by all of your projects, rather than right next to your source file in a project where you would have to copy it for each project.
C.3 .3 Add a
c++ source file to the project
You need at least one source fLle in your program (and often many):
I. Click the Add New Item icon on the menu bar (usually the second icoll from the left). ' nmt will open the Add New Item dialog box. Select Code under the VISUal C++ category. 2. Scicct the C++ HIe (.cpp) icon in the template window. Type the name of your program file (HeUo,World!) in the Name text box and click Add. YOli have created an empty source code file. You arc now ready to type your source code program.
C3.4 Enter your source code At this poim you can either enter the source code by typing it directly into the IDE, or you can copy and paste it from another source.
C3.5 Build an executable program W hen you believe you have properly entered the source code for your program, go to the Build menu and select Build Solution or hit the triangular icon pointing to the right on lhe list of icons near the top of the IDE window. 11\e IDE will try to compile and link your program. If it is successful, the message Build : 1 su cceeded, 0 fai led, 0 up·lo-dale, 0 skipped should appear in the Output window. Otherwise a number of error messages will appear. Debug the program to correct the errors and Build Solution again. If you used the triangular icon, the program will automatically start rtmning (executing) if there were no errors. If you used the Build Solution menu item, you have to explicitly start the program, as described in §C.3.6.
C.4
LATER
C.3.6 Execute the program Once al[ errors have been eliminated, execute the program by going to the Debug menu and selecting Start Wtthout Debugging.
C.3.? Save the program Under the File menu , dick Save All.lfyo Li forget and try to dose the IDE, the IDE will remind you .
C.4 later TIle IDE has an apparent infinity of features and options. Don't worry about those early on - or you'll get completely lost. If you manage to mess up a project so that it "behaves odd[y," ask an experienced friend for help or build a new project from scratch. Over time, slowly experimem with new features and options.
11 55
\t
.r
0
Installing FLTK "If the code and the comments disagree, then both are probably wrong." -Norm Schryer
T
his appendix describes how 10 download. i", ..ll. and link to the FL1' K gl'ilphicl ond CU I toolkit.
1157
APPENDIX 0
11 58
• IN STALLING FLTK
0.1 Introduction
0.2 Downloading FLTK D.) Installing FLTK 0.4 Using FLTK in Visual Studio
0.5 Testing if it all worke d
D.1 Introduction We chose FLTK, the Fast Light Tool Kit (pronounced "full lick"), as the base for our presentation of graphics and CU I issues because it is portable, relatively simple, relatively conventional , and relatively casy to instalL We explain how to install FLTK under Microsoft Visual Studio because that's what most of our students use and because it is the hardest. U you usc some mher system (as some of our students also do), juSt look in the main folder (directory) of the downloaded ftlcs (§D.3) for directions for yOllr favorite system. 'Whenever YOli lise a library mat is nal pan of the ISO C++ slalldard, you (or someone else) have to download it, install it, and correctly use it from your own code. 111at's rarely completely trivial, and installing FLTK is probably a good exercise - because downloading and installing even the best library can be quite fru strdting when you haven't tried before. Don't be tOO reluctan t to ask advice from people who have tried before, but don't just let them do it for you: learn from tl1em. Note that there might be slight differences in files and procedures from what we describe here. For example, there may be a new version of FLTK or you may be using a d ifferent version of Visual Studio from what we describe in §D.4 or a completely different C++ implementation.
D.2 Downloading FLTK Before doing anything, first see if FLTK is already installed on your machine; sec §D.5. If it is not there, the first thing to do is to get the files onto your computer: 1. Go to http://ntk.org. (In an emergency, instead download a copy from
our book support website: www.stroustrup.comiProgramminglFLTK.) 2. C lick Download in the navigation menu. 3. Choose FLTK l.l.x in the drop-down and dick Show D ownload Location s. 4. Choose a download location and download the .zip file . The file you gel will be in .zip formal. -nlat is a compressed format suitable for transnuuing lots of files across the net. You' ll need a program on your mach ine to "unzip" it into normal files ; on Windows, WinZip and 7-Zip are examples of sllch programs.
0.4
US IN G FlTK IN VI SUAL ST U DIO
0.3 Installing FLTK Your main problem in following our insouctions is likely to be one of two: somethiJlg has changed since we wrote and tested them (it happens), or the tenmnology is alien to you (we can't help with that ; sorry). In the latter case, find a friend to translate. I. Unzip the downloaded file and open the main folder, fllk -l.l. ? In a
Visual C++ folder (e.g. , vc2005 or venet), open fltk.dsw. If asked abOllt updating old project files, choose Yes to All . 2. From the Build menu, choose Build Solution. "nlis may take a few minutes. TIle source code is being compiled into static link libraries so that you do not have to recompile the FL'rK source code any time you make a new project. When the process has finished , close Visual Studio. 3. From the main FLTK directory open the lib fold er. Copy (not just move/drag) all the .lib files except README.lib (there should be scven) into C:\Prograrn Files\Microsoft Visual Studio\Vc\lib. 4. Go back to the FLTK main directory and copy the FL folder into C:\Program Files\Microsoft Visual Studio\Vc\include. Expens will tell you that there arc better ways to install than copying into C:\Program Files\Microsoft Visual Studio\Vc\lib and C:\Program Files\Microsoft Visual Studio\Ve\include. TIley arc right, but we are nOt trying to make you VS experts. If the experts insist, let lhem be responsible for showing you the better alternative.
0.4 Using FLTK in Visual Studio I. Create a new project in Visual Studio with one change to the usual procedure: creale a "\Vin32 project" instead of a "console application" when choosing your project type. Be sure to create an "empty project"; otherwise, some "software wizard" will add a lot of stuff to your project that you arc unlikely lO need or understand . 2. In Visual Studio, clloose Project from the main (top) menu, and from the drop-down menu choose Properties. 3. In lhe Properties dialog box, in the left menu, click the Linker folder. This expands a sub-menu. In this sub-menu, click Input. In the Additional Dependencies text field on the right, enter the following text : fltkd.1ib ws0ck32.Ub comctl32.lib fltkjpegd.lib fltkimagesd.lib [The foll owing step may be lIImecessary because il is now the default.] In the Ignore Specific Library text field , enter the following text: libcd.lib
1159
1164)
APPEND I X D • I NSTAL LI NG FLT K
4. [Ths step may be unnecessary because IMDd is now the default.] In the left menu of the same Properties window, dick C/C++ to c.xpand a different sub-menu. Click the Code Generation sub-menu item. In the right menu , change the Runtime Library drop-down to Multi-threaded Debug DLL (/ MDd ). Click OK lO d ose the Properties window.
D.S Testing if it all worked C reate a single new .cpp file in your newly created project and enter the following code. It should compile without problems. #include #include #include int main O (
FI_Window window(200, 200, "Window title"); FeRo" box(O,O,200,200, "Hey, I mean, He llo, World! "l;
window.showO; return FI: : run O;
If it did not work : "Compiler error stating a .lib fil e could not be found ": Your problem is most likely in the installation section. Pay attention to step 3. which involves putting the link libraries (.lib) fi les where your compiler can easily fin d them. "C ompiler error stating a.h file could not be opened": Your problem is most likely in the installation section. Pay attention to step 4, which involves putting the header (.h) flies where your compiler can easily find lhem. "Linker error involving unresolved external symbols": Your problem is most likely in the project section. If that didn't help, fmd a friend to ask.
CUI Implementation "When you finally understand what you are doing, things will go right." -Bill Fa irbank
T
his appendix presents implementatio n details of callbacks,
Window, Widget, and Vector_ref. In Chapter 16, we
couldn 't assume the knowledge of pointers and casts needed ror a more complete explanation , so we banished that explanation to tltis appendix.
1161
APPENDIX E • G U I IMPLEMENTAT ION
1162
E.1 Callback implementation E.2 Wldjl@1 implementation E.3 Window implementation E.4 Vector_' ll' E.5 An example : manipulating Wld8l!ls
E.l Callback implementation We implemcnted callbacks like this: \lo ld
Sl mpl l!~wlndow ll c b_n Ci'. t(Addr c u .
II LLlll
~ltfi l)lc_w l m luw :: IICX I () (Of IIII.'
Addre" addr) wln(tuw IOC,IIl'd ,II pw
Once you have understood C hapter 17, it is pretty obvious that an AdtlrC! j must he a void · . And, of cou rse, rctCl HHlecu ocSlniplc_wllldoW>('lthlr) must somehow create a reference to a Slml)lc window from the void· called add, . However, un· less you had previous programming experience, there was nothing "pretty obvi· ous" or ;'of course" about that before you read C hapter 17, so let's look at the use of addresses in detail. As described in §A. 17, C++ offers a way of giving a name to a type. For example:
TIlis means that the name AddrClIi can now be used instead of \lold · . Here, we used Addrc" to emphasize that an add ress was passed, and also to hide the fact that void · is the name of the type o f pointer to an object for which we don' t kllOW the type. So cb_neJlfO receives a vo id · called iultlr as an argument and - somehow promptly convens it to a SltnIJl ll_wlndow& :
rThe rClll rlll\CtU O is a templatc function (§A. 13): IllnllJlalll W& tc ' crenCc_IO(AddrcU pw) II Ire,1t ,lt1 .ltldrl'~!.u.! ,dl'll'nLl' 10 .1 W
E.2
WIDGET IMP LEMENTATI ON
1163
{
return 'stalic castl howOI ) vlrtunl void iUHICh(Wlridow&) . 0, /I c,llh Wltl»cl dcflt'l'~ .11 k"I~ 1 /1 (Jill! .KIIU!1 (ur ,I wlnduw
POlnllo(a Ittl width , Inl holShl ' ! lrlns lablllJ Cillibiltk doJt / prOICC:I\lt! 1 Window· own , ill_Wldget - (JWI )
,
IlllVt'ty Wld!}!.'1 bdu"~~ 10 .1 Wlnduw //.1 Widget "knuw!" It! FI_Wltlgcl
Note that our Widsci keeps track of its FLTK widget and the Window with which it is associated. Note that we need pointers for that because a Wid SCI can be associated with different Windows during its life. A reference or a named object wouldn't suffice. (Why not?) It has a location (Ioc), a rectangular shape (Width and heIShl), and a 13blll . Where it gets interesting is that it also has a callback fu nction (do II) - it connects a WldSClI's image on the screen to a piece of our code. TIle meaning of the operations (nlOv~O , ii howO, hld.,O, and "lIithO) should be obvious. Wldgel has a "half-fin ished " look to it. It was designed as an impicillcillation class that users should not have to see very often. It is a good candidatc for a redesign. We are suspicious about all of those public data membcrs, and "obvious" operations typically need to be reexamined for unplanned subtlcties. Wldscl has virtual function and can be used as a base class, so it has a vlrlual destructor (§ 17.5.2).
E.3 Window implementation When do we usc pointers and when do we use references instead? We examine that gencral question in §8.5.6. Here, we'll just observe that somc programmers like pointers and tllal we need pointers whcn \...·c want to point to diffcrent objects at different timcs in a program. So far, we have not shown one of the central classes in our graphics and G U I library, Window. The most significant reasons are lhat it uses a pointer and that
E.3
WINDOW IM PLEMEN TATION
1165
its implementation using FLTK requires free store. As found in Wlndow.h, here It IS:
Window I public ill Whldow { I)ublle: Illct the !y~tl'm plLk the IUL.ltIOI1: Wlndow(hH w, Int Ii, ( Onl l llltlng& IltltI) , IIlupldt LOlller In xy: WlndowWolnl ky, It" WI Inl hi ( 0". 1111,1118& tlllel)1
cl lI.5!I
VI,IUill ...Wlndown { ) Inl lumur: () eonl l ( ret urn W) ) Inl y_,tlil Jl O eunllt ( nHum h / )
vuld IllHu:h( h"pe& I) {l hilIH,!II, ,-iJ ii h_bn k(&I») ) vuld iHMeh(Wldget&)1
vuld dtltaeh(S hll (ltl& 8)1 void dela h(Wldge l& w);
II f'ernUW w (ruin sh,lpe5 Illemuve w (rum whu.luw II (tle.1Ulv,ltcS Lolllb,lt k:s)
void IJUI on IUI)(Shapc& I)) II put p Ul11UP of til her ~11tI 1)c' ptUt tletcd : void drawn) 1"lvale : vCClorcS hilpc·> 8hll pClIi II slMpe5 .JII.1elled It) Wlilduw Inl w,h, II wlmluw ~Ile vultl lnltO;
So, when we atMehO a ShlllHl we store a pointer in II hiiJlti8 so that the Wind ow can draw it. Since we can later detac:ho that shape, we need a poimer. Basically, all .,1111 hOed shape is still owned by our code; we just give the Winduw a reference to it. Window : tluln chO converts its argumem to a poimer so that it can store it. As shown above, l'I lIaehO is trivial ; dtltllchO is slightly less sim ple. looking in Wlndow,cl)I), we find:
" 66
APPENDIX E • CUI IM PLEMENTATION
void Window: :detach(Shape& s) /I guess that the last anached will be first released {
for (unsigned int i = shapes.sil-eO; (kij -- i) if (shapes[i-l l==&s) sha pes.erase(&shapes[i- l U;
T he eraseO member function removes ("crases") a value fro m a vector, decreasing the vector's size by one (§20.7. 1). Window is meant to be used as a base class, so it has a virtual destructor (§17.5.2).
E.4 Vector_ref Basically, Vectocref simu lates erences or wilh pointers:
II
vector of references. You c.m initialize it with ref·
If an object is passed to Vector_ref as a reference, it is assumed to be owned by the ca.llcr who is responsible for its life time (e.g. , the object is a scoped variable). If a n object is passed to Vector_ref as a pointer, it is assumed to be alloc.1.ted by new and it is Vector_ref's rcsponsibility to delete it. An clement is stored as a pointer - not as a copy or the object - into the Vector_ref and has rererence semantics. For example, YOll c.1.1l put a Ci rcle into a Vector_rekShape> without suffering slicing. te mplate class Vector_ref { vector v; vectorhld e(); alUtclW. dpl) ;
There are four callbacks. Each makes it appear that the buuon you press disap· pears and a new o ne appears. However, this is achieved in four different ways: void W1: :.hO
II hide .1 butlutl, ~huw .1nUll1ef
(
If (.hJcft) ( 1,'I->hldtlO; pl->!! hOw();
E.5
AN EXAMPLE : MAN IPULATING WIDG ET S
else ( pl->s hOWOj p2->hide(); }
shJeft = !shJeft ; }
void W7:: mvO
II move the button
{
if (mv_lefO ( m vp ->move(l oo,O); }
else { mvp ->move(- loo,O); }
mv_left = !mvJeft j }
void W7: :cd O
/I de lete the button and create a new one
{
cdp- >hide(); d ele te cdp j string la b = "create " j inl x = 100; if (cdJ eft) ( la b = "delete "; x = 200; cdp = ne w Butto n(Point(x,JOO), SO, 20, la b, cb_cd )j attach(-cdp)j cdJeft = !cdJeft ; }
void W7 : :ad O /I detach the button from the window and attach its replacement {
if (ad_left) ( d etach (-adp1); attach(·adp2); }
else ( detach(*adp2); attach (*adp1 )j }
1169
APPEN DI X E • CUI IMPLEMENTATION
11 70
ad lell - lldJelll
Inl maln O i W7 w(400,800, lI mu lell);
rei urn gul_ntaln OJ 111is program dcmonstrales the fundamental ways of adding and subtracting widgcLS lolfrom a window - or just appearing to.
Glossary "Often, a few well-chosen words ar worth a thousand pictures." -Anonymous
A glOJJdry is a brief explanation of words used in a text. TIlls is a rather shon glossary of the tenns we thought most essential, especially in lhe earlier stages of lcaming programming. The index and lhe "Terms" sections of the chapters might also help. A morc extensive glossary, relating specifically to C++, can be found at wv....v.rescarch.atl.com/ -bs/glossary.html, and there is an incredible variety of specialized glossaries (of greatly valying quality) available o n the web . Please nme that a term can have several related meanings (so we occasionally list some) and that most terms we list have (oflen weakly) rdated meanings in other
contexts; for example, we don't define abJtracl as it relates to modern paiming, legal practice, or philosophy. abstract class a class that camlot be directly used to create objects; often used to defin e an interface to derived classes. A class is made abstract by having a pure virtual funClion or a protected constructOr. abstraction a description of something that selectively and deliberately ignores ~lides) details (e.g. , implementation details); selective ignorance. addttss a value that allows us to find an object in a computer's memory. algorithm a procedure or fonnula for solving a problem ; a finite series of com· putalional steps to produce a result. alias an alternative way of referring to an object; o flen a name, pointer, or refer· ence. 1171
1172
GLOSSARY
application a program or a collection of program s that is considered an emily by its users. approximation something (e.g., a value or a design) that is d ose to the perfecl or ideal (val ue or design). Often an approximation is a resuit of trade-offs among ideals. argument a value passed to a function or a template, in which it is accessed through a parameter. an'3.y a homogeneous sequence of clements, usually numbered , e.g., (O:max). assertion a statement inserted into a program to state (assert) that something must always be true at lhis point in the program. base class a class used as the base of a class hierarchy. Typically a base class has one or morc virtual func tions. bit the basic unit of infonnation in a computer. A bit can have the value 0 or the value I. bug an error in a program. byte the basic unit of addressing in most compu ters. Typically, a byte holds 8 bits. class a user-defined type lhat may conlajn data members, function members, and member lypes. code a program or a part of a program; ambiguously used for both sou rce code and object code. compiler a program thatlums source code imo object code. complexity a hard-to-preciscly-define notion or measure of the difficulty of constructing a solution to a problem or o f the solution itsclf. Sometimes c07llpkxiJy is used to (simply) mean an estimate o f the number of operations needed to ex· ecute an algorithm . computation the execution of some code, usually taking some input and producing some output. concrete class class for which objects can be created. constant a value that cannot be changed (in a given scope); not mutable. constructor an operation that initializes ("constructs") an object. Typica.lly a construCLOr establishes an invariam and often acquires resources needed for an object LO be used (which arc then typically released by a destructor). container an object that holds elelllents (other objects). correctness a program or a piece of a program is correct if it meets its specification. Unfortunately, a specification can be incomplete or inconsistent, or can fai l to meet users' reasonable expectations. TItuS, to produce acceptable code, we sometimes have to do more than just foll ow the fomlal specification. cost the expense (e.g. , in programmer time, run time, or space) of producing a program or of executing it. Ideally, cost should be a function of complexity. data values lIsed in a compmation. debugging the act of searching for and removing errors from a program ; usually far less systematic than testing.
GLOSSARY
declaratio n the specification of a name with its type in a program. d efinition a declaration of an emity that supplies all infomlation necessary to complete a program using the emilY. Simplified definition: a declaration that allocates memory. d erived class a class derived from one or more base classes. d esign an overall description of how a piece of software should operate to meet its specification. d estructor an operation th at is implicitly invoked (called) when an object is destroyed (e.g. , at the end of a scope). Often, it releases resources. error a mismatch between reasonable expectations of program behavior (oft en expressed as a requirement or a users' guide) and what a program actually does . executable a program ready to be run (executed) on a computer. feature creep a tendency to add excess fUllctionality to a program "just in case." file a container of pellllanelU information ill a computer. n oating-point number a computer's approximation of a real number. such as 7.93 and 10.78e- 3. function a named unit of code that C.·1 1. l be invoked (called) from different parts of a program; a logical unit of computation. generic p rogramming a style of progranuning focused 011 the dcsign and efficient implementatioll o f algoritluns. A generic algorilhm will work for all arb'llment types that meet its requirements. In C++, generic programming typically uses templates. head er a file containing declarations used to share interfa ces bet\veen parts of a program. hiding the act o f preveming a piece of information from being directly seen o r accessed. For example, a name from a nested (inner) scope can prevem that same name from an outer (enclosing) scope from being directly used . ideal the perfect vers ion of something we arc striving for. Usually we have to make trade-oITs and settle fo r an approximation. implem entation (1) tile act of writing and testing code; (2) tile code that implements a program. infinite loop a loop where the termination cond ition never becomes true. Sec iteration. infinite recursion a recursion that doesn't end until the machine runs Out of memory to hold the calls. In reality, such recursion is never infinite but is terminated by some hardware error. information hiding the act or separating interface and implementation, thus hiding implementation details not mealll ror the user's attention and providing an abstraction. initia lize giving an object its first (initial) value. input values used by a computation (e.g., fun ction arguments and characters typed on a keyboard).
11 73
1174
GLOS SARY
integer a whole number, such as 42 and - 99. interface a declaration or a set of declarations specifying how a piece of code (such as a function or a class) can be called. invariant something that must be always tn le at a given point (or points) of a program; typically used to describe the state (SC I of values) of an object or t.he state of a loop before entry into the repeated statement. ileration the act of repeatedly executing a piece of code; sec recursion. iterator an objcct that identifies an clemcnt of a sequence. library a collection of types, functions, classes, etc. implementing a set of fa cilities (absuactions) meant to be potentially used as prut of more that one program . lifetime the time from the initialization of an object umil it becomes unusable (goes out of scope, is deleted, or the program tenninatcs). linker a program that combines object code files and libraries into an executable program. literal a notation that directly specifies a value, such as 12 specifying lhe integer value "twelve ." loop a piece of code executed repeatedly; in C ++, typically a for-statement or a while-statement. mutable changeable; the opposite of immutable, constant, and variable. object (I) an initialized region of memory of a kllown type which holds a vallie of tim type ; (2) a region of memory. object code output from a compiler intended as input for a linker (for the linker to produce e.....ecutable code). object file a me containing object code. object-oriented programming a slyle of programming focused on the design and use of classes and class hierarchies. operation something that can perform some action. such as a function and an operator. output values produced by a computation (e.g., a fun ction resuit or lincs of characters written on a screen). overflow producing a value that calUlot be stored in its intended target. overload definin g two functions or operators with the same name blll dilTerelll argumelll (opela nd) types. override defining a runction in a derived class with the same name and argumcnt types as a virtual fun ction in the base class, thus making the function callable through the interface defined by the base class. paradigm a somewhat pretentious term for design or programming style; oft en used with the (erroneous) implication that there exists a paradigm that is supe· rior to all others. parameter a declaration of an explicit input to a fun ction or a template. When called, a fun ction can access lhe arguments passed through the nallles of its parameters.
GLOSSARY
pointer (I) a value used to identify a typed object in memory ; (2) a variable holding such a value. post-condition a condition that must hold upon exit from a piece of codc, such as a function or a loop. pre-condition a condilion that must hold upon elllry into a piece of codc, such as a function or a loop. program code (possibly with associatcd data) that is sufficiently complcte to be executed by a computer. programming the art of expressing solutions to problems as code. programming language a language for expressing programs. pseudo code a description of a computation written in an infomlal nalation rather than a programming language. pure virtual function a virtual function that must be overridden in a derived class. RAIl ("Resource Acquisition Is Initialization n) a basic tcdmique for resource management based on scopes. range a scqucnce of values that can be described by a start point and an end point. For cxample, (0:5) means the values 0, 1, 2,3 , and 4. regular expression a notation for pattcOls in character strings. recursion the act of a function calling itself; see also iteration. reference (I) a value dcscribing the location of a typed value in memory; (2) a variable holding SUell a valuc. requirement (I) a description of the desired behavior of a program or part of a program ; (2) a desoiption of the assumptions a function or tcmplate makes of its arguments. resource something that is acquircd and must later be released, such as a file handle, a lock, or memory. rounding conversion of a value to the mathematically nearest value of a less precise type. scope the region of program text (source code) in whiell a name can be referred to .
sequence clcments that can bc visited in a linear order. software a collection of pieces of code and associated data; often used interchangeably with program. source code code as produced by a programmer and (in principle) readable by other programmers. source me a file containing source code. specification a description of what a piece of code should do. standard an officially agreed upon definition of something, such as a programming language. state a set of values. string a sequence of characters.
1175
1176
GLOSSARY
style a set of techniques for programming leading to a consistent use of language features; sometimes used in a very restricted sense to refer just to low-level rules for naming and appearance of code. subtype derived type; a type that has alIlhe propenies of a type and possibly more. supertype base type ; a type t.hat has a subset of the propertics o f a type. system (I) a progrnm or a set of programs for performing a task on a computer; (2) a shorthand for "operating system;' that is, the fundamclllal execution enviromllCnt and tools for a computer. template a class or a function parameterized by one or more types or (compiletime) values ; the basic C++ language construct supponing generic programming. testing a systematic search for errors in a progrnm. trade-off the result of balancing several design and implementation criteria. truncation loss of information in a conversion from a type into another that cannot exactly represent the value to be converted. type something that defines a set of possible values and a set o f operations fo r an object uninitialized the (undefin ed) state of an object before it is initialized . unit (I) a standard measure that gives mcaning to a value (e.g. , km for a distance); (2) a distinguished (e.g. , named) part of a larger whole. use case a specific (typically simple) lise of a program meaIll LO test its functionality and demonstrate its purpose. value a set of bits in memory interpreted according to a type. variable a named object of a given type; contains a value unless uninitialized. virtual function a member function that can be overridden in a derived class. word a basic unit of memory in a computer, usually the unit used to hold an integer.
Bibliography
Aho, Alfred v., Monica S. Lam, Ravi Sethi, and J effrey D. Ullman. Compilers: P'll1cip/~J, 7'edllllf/UCS, {/lui roots, Second £Iilioll (usually called "TIle Dragon Book") . Addison-\Vcs]cy, 2007. ISBN 032 1547985. Andrews, Mike, and Jruncs A. Whittaker. How to Brmfl. Siftware: Fundional mul Srom"ty Testingo/"mh Applim/iQ1/J IIl1d fffb Servias. Addison-Wesley, 2006. ISBN 0321369440. Austcrn, MatthelV H . Genmc Programming mui 1M STL: Using allll Exleuding lhe C++ Standmzl 7!:mplate [ibmry. Addison-V.'Cslcy, 1999. ISBN 0201309564. Austcrn, Matt, cd. Dr41 7(chnim/ Rep0l1 011 C++ Siandard Library £r/msiolls. ISOIlEC PDTR 19768. W\vw.opcn-std.orgljtc1 /sc22/w'(21/docsfpapcrs/2005/n 183 6.pdf. Bergin, Thomas ]., and Richard C. Gibson, cds. History rfProgramming Languages - Volume 2. Addison-vVcslcy, 1996. ISBN 0201895021. Blanchctlc, J asmin, and Mark Summcrfield. C++ CUI Programmillg with QL 4. Prentice Hall, 2006. ISBN 0 13 1872493. Boost.org. ~A Rcpository for Libraries Meant 10 Wo rk V.'elI wilh the C++ Standard Library." www.boost.org. Cox, Russ. ~ RcguI ar Expression Malching Can Be Simple and Fast (but Is Slow inJava, Perl, PHP, PYlhon, Ruby, ...J." http ://swtch.com/ -rsdregexp/regexpl.html. dmoz.org. http://dmoz.orgiComputersl ProgramminglLanguages. Freeman, T L. , and CJllis Phillips. RlTa1le1 Numerical Algonihllls. Premice Hall, 1992. ISBN 0136515975. Gamma, Erich, Richard Helm, Ralph J ohnson, and J ohn M. Vlissides. Jk.sigll Pattems: Ek///C1It.s o/"Rrmtlblr Olij"ecl-Oriell/ed Srf"twarr. Addison-Wesley, 1994. ISBN 0201633612. Goldthwaite, Lois, cd. 71xhllical Repor/ QII C++ lbfonllmu:e. ISOIIEC PDTR 18015. www.rescarch.all .cOlnl-bs/pcrformanecTR.pdf. Gullberg, Jan. Ma/hell/(I/iCJ - From IIle Birth 0/" Jol/lmbers. W. W. Nonon, 1996. ISBN 039304002X. Hailpcm, Brcnt, and B.1l"bara G. Ryder, eds. Ftrxeetiuw rj/lze 77tinl ACM SIGPLANCmgeretlU OIl /lze HUJOI)' if"Programming Lmq;uage.s (HOPL-J!l). San Diego, CA, 2007. http://portal.acm.orgl loc.cfm?id=1238844.
1177
1178
81BlIOGRAPHY
Hcnricson, Mats. and Erik Nyquist. huiustnal Sirmgth C++: Ruffs oml &rommnuulhans. Prentice Hall, 1996. ISBN 0 13 1209655. ISO/ lEG 9899: 1999. ProgrammuJg ulI/guagtJ - C. -nlc C standard. ISOIIEC 14 882:2003. Programming IAI'guogc; - C++. ll1c C++ standard. Kernighan, Brian W.. and DClUlis M. Ritchie. 'rnc C Programming Lallgtlagt. Premiec Hall. first edition, 1978; second edition, 1988. ISBN 013 1103628. Knuth, Donald E. 1k Arl f/"Computer Programming, fIi"lII~ 2: Semllll/mmmi Algrmihms, 77u'rd Edition. Addison·Wesley, 1998. ISBN 020 1896842. Koc::nig, Alldrcw. cd. 1M C++ SlamumJ. ISOfl EC 14 882:2002. Wiley, 2003. ISBN 0470846747.
Koenig, Andrew, and Barbara E. Moo. Acctin-oled C++: Itacl/wl Programmillg by Examp/e. Addison-Wesley, 2000. ISBN 020170353X. Langer. Angdika. and Klaus Kreft. SlmU/(IIri C++ IOSITtalllS (lnd Ux(/ltS: At/w I/ad Programmtr; Guide (II/(I Rijtrel/a. Addison-Wesley, 2000. ISBN 020 11 8395 1. Lippman, Stanley B., j osce Lajoie, and Barbara E. Moo. '{k C++ Primtr. Addison·\o'l'eslcy. 2005. ISBN 020 1721481. (Usc only the 4th edition.) Lock.heed Martin Corporation. ':Joint Strike Fighter Air Vehicle Coding Standards ror the System Development and Demonstration Program .~ Document N umber 2RD UooOO I Rev C. December 2005. Colloquially k.nown as "J SF++." www.rt:search.al.l.com/- bsi j SF·AV·mles.pdr. Lohr, Steve. Go 70: 1M Slory rflht Mnlh Mf!iqrs, 8ridgt Pfa)m, ~11tm, Chm WiUlnu, Maumck &in/lisls (lnd Irotux:!iI.lls - 7'ht Programmrrs Who Crtaltd Iht Siflwart RroolllllfJ/!. Basic Books, 2002. ISBN 9780465042265. Maddoc. j . boost::rt:gcxp documentatio n. www.boosLorg and www. boost.orgldodlibs! 1_36_0Ilibslrt:gexldodh tm llindex.htmi. Meyers. ScOtt. El1utilx S ri: 50 Sjxcjfo. Way'J 10 lmprout lollr Use 0/ lilt Slml(uml 7ellll)lalt Li· bmry. Addison·Wesley, 2001. ISBN 020 1749629. Meyers, ScOtt. Iijf«tif~ C++: 55 Sjxcffic Wl)'s to Improut Yollr F'rogmllls alld Dt-figm, 7'hird &Iitim,. Addison·' Vesley, 2005. ISBN 0321334876. M usser, David R., eillmer J. Derge, and Atul Saini. S7L 'lillorial t/1111 Rijrrt7ll:t Gllitk: C++ Progrmlllning wilh Iht Slal/(umi 'ft,np/ale Libral)" S((ol/(I £ililioll. Addison·\Vesley, 2001. ISBN 020 1379236. Programming Research. Higll-inlegrily C++ Oxling Sla//(umi Mallllal Vmion 2.4. www.pro· grammingresearc h.com. Richards, Martin. BCPL - 'nit IAngl/agt and lis Compiltr. Cambridge U niversity Press. 1980. ISBN 0521 2 19655. Ritchie, Dennis. M-nle Development of lhe C Programming Language." /trx:«r/ing'f f!!lht ACM HiJlory 0/ Programmillg IAnguagr.s CoI!forrna (110PL·2). ACM S IGPLAN .NiJlim, Vol. 28 No.3, 1993. Salus, Peter. A ccifier, 11 42 Ox. set l~rtx ,378. 3 80
INDEX
1183
A append ftle mode, 11 40 \ a alen, charnclcr lilcral. 1043 aOOrl(), 11 49 ab$(), absolUiC valuc, 879, 1137 complex. 88 1, 11 39 AbslrnCI classes. 487. 11 71 class hiernrchies, 503 creating. 487. 503- 50'1, 1080- 1081 Shape example, 487-488 Abstracl·fir.it approadl to progranuning,
ii ,
10 Abstraclion, 92-93. 11 71 level, ideals, 778-779 Access cOlllrol. 302, '196. 50 1- 502 base classes. 501 - 502 encapsulation. 496 members. 484- 485 private, 496, 50 1- 502 private by default, 302- 303 private us. public, 302- 304 privale: label. 302 protcctcd. 496, 502 prolectc ,593. Sc.-e also M ember access. [I , 116- 11 7. &t(llso$ubscripting. Derivation, classes, 496
1195
INDEX
Deri ved classes, 496. 1173 access conlfOL 501-502 base classes, 1078- 1079 inhelilll.nce, 1078- 1079 multiple inheritance, 1079 object layo ut, '~97-499 overview, 496-497, 1078-1079 private bases and members, 50 1502 protected bases and members, 502 public bases and members, 502 specifying, 499 virtual functions , 1079- 1080 Design , 35. 174, 177, 1173 Design for testing, 978- 979 Destructors, 586-588, 1077, 1173 See abo Constructors. containers, 1108-1109 debugging, 622-624 default, 1081 esscntial operations, 620-624 execptions. 675-677 and frec store, 589- 590 freeing resources, 3 18, 675- 677 generated. 588- 589 RAI l, 675-677 virtual, 589-590 where needed, 621 Device drivers. 340 Dictionary examples, 121 - 123, 756 differeneeO, 1103 difference_type. 1108 digi t, character class, 842 , 1134 Digit, word origin, 1041 Dijkstra, Edsger, 792-793, 952 D imensions, matrices, 862-865 Direct c."pressioll of ideas, ideals, 777778 Dispatch, 496 Display model, 409- 410 Divide I, 66,105 1 Divide lind assign 1=, 67, 1053 Divide and conquer, 93 Divide-by-zero error, 199- 200 dividesO , 1123 Domain knowledge, 896
Dot product. Set inner_producIO. double floating-point type, 63, 66-67, 78, 1062 Doubly-linked lists, 598, 698. Set auo list. drawO example fill color, 492 line visibility, 492 Shape, 491-494 draw_linesO example Set auo drawO example_ Closed_polyline, 452 Marked_polyline, 469 Open_polyline, 451 Polygon, 454-455 Rectangle, 459 Shape, 491 - 494 Dynamic dispatch, 496_ Set auo Virtual functions_ Dynamic memol)'_ Set Free store. dynamiccast, type conversion, 1058 exceptions, 1099 predictability, 894
E Efficiency ideals, 92 -9'~ , 775- 776 vector range checki.ng, 670 Einstein , Albert, 780 Elements Set also vector. numbering, 627 pointers to, 628- 63 1 variable number of, 628 Ellipse example, 466-468 m. Circle, 467 else, in if-statements, 102- 103 Email example, 820-830 Embedded systems coding standards, 935- 937, 943 concurrency, 894 containers, 912-9 16 correctness, 891 - 892 delete operator, 894 domain knowledge, 896
,,%
INDEX
Embedded systems (wlllillued) dynamiccasl, 894 error handling, 895-897 examples of. 888-890 exceptions, 894
fault tolerance, 892 fragmentation , 898, 899 free-store, 898-902 hard real time, 893 ideals, 894- 895 maintenance, 891 mcmOly management, 902- 904 new operator, 894 predictability, 893, 894 real-time constraints, 893 real-time response, 890
reliability, 890 resource leaks, 893 resource limitations, 890 soft real time, 893 special concerns, 890- 891
Ellipsis ." argume nts (unchecked), 1068-
1069 catch all exceptions, 150
Empty empl yO, is comainer empty?, 11 11 lists. 702 sequences, 702 statements, 100 Encapsulation, 496 Enciphering (Encryption), example,
930-935 endO itcrator. 1109 Siring, 815, 1132
vector, 695 End of line $ (in regular expressions), 837, 1134 End of file eorO, 349. 11 27 me streams, 360 lIO error. 349 stri ngstrea m, 390- 391 Ending programs. See Terminating. programs.
endl manipulator, 1130 ends manipulator, 1130 English grammar us. programming grammar, 19 1- 192 cnum, 314-317, 1008. See alsQEnumerations. Enumerations, 314-317. 1070 enum, 3 14-3 17, 1008 enumerators. 3 14-317, 1070- 1071 EOF macro. 10 19- 1020 cofO stream state, 349, 1127 cqualO, 729, 1113 Equal ==, 67, 1052 Equality operators, expressions, 1052 cqualJ angcO, 728, 763- 764 cquaUoO, 1122 e raseO list, 713-715, 1110 list operations, 600- 602 string, 815. 11 32 vector, 715- 718 crrno, error indicator, 880, 1138 crrorO example, 140- 141 passing multiple strings, 150 ~ ullca ught c.... ception" elTor, 151 E rror diagnostics, templates, 661 Error handling See alsQErrors; Exceptions. % for floaring-point numbers, 228-231 catching exceptions, 238- 240 fLies fail to open, 385 GU ls.563 hardware replication, 896 liD errors. See 110 errors. liD streams, 1127 mathematical elTQrs, 880 modular systems. 896- 897 monitoring subsystems, 897 negative numbe rs, 227- 228 positioning in files , 389 predictable en-ors, 895 recovering from errors, 238- 240 regular expressions, 842- 844 resource leaks, 896 self-checking, 896
INDEX
SllJ (St:Uldard Template Library), 1098- 1100 tcsting for errors, 224-227 transiclll errors, 895-896 vector resource exceptions, 677 Error messages Sa a/.w I.'rroro ; Reponing errors; runtime_error. exceptions, printing, 148- 149 templates, 661 writing your OWI\, 140 Errors, 1173 oS« al.w Dccifications, 134 rcco\'ering from , 238-240. Set also Exceptions. sources of, 134 syntax, 135-136 translation units, 137- 138 type mismatch, 136-137 undcclared identifier. 256 unexpected argulllents, 134 unexpected input, 134 unexpected state, 134 Errors, nm-time, 132. 138-140 See also Exceptions. callee responsibility, 141-143 caller responsibility, 14 0- 141 hardware violations. 139 reasons for, 142- 143 reponing, 143-144 Estimating development resources, 175 Estimating results. 155- 156 Examples age distribution. 527- 528 calculator. Sa C1.Iculator example. Dale. Stt Date example.
1197
deciphering, 930-935 deleting repeated words, 71-73 dictionary, 12 1- 123, 756 Dow J oncs tracking, 750-753 email analysis, 820-830 embedded systems, 888- 890 enciphering (encryption), 930-
935 exponential function, 5 17-5 18 finding largest elemcnt, 687-690, 696--697 fruits, 747-750 Gaussian climination, 874-876 graphics. 410-414, 432 graphing data, 527-528 graphing functions, 517-518 GUI (graphical user interface), 552-556, 560-56 1,563-564 Hello, World !, 45-46 intrusive containers, 1025- 103 1 lines_window, 552-556, 560-56 1, 563-564 link, 598--607 list (doubly linked), 598-607 map container, 747-753 Matrix. 872-877 palindromcs, 637-641 Pool allocator, 902-903 Punccstream, 397-401 reading a single value, 353-357 reading a Structurcd me. 361 -370 regular expressions, 844-849 school table. 844-849 searching, 828-836 sequences, 696--698 Stack allocator, 903- 904 TEA ('Iiny Encryption Algorithm), 930-935 tcxt editor, 704-7 11 vector. Sa vector example. Widget manipulation. 552- 556, 1167- 1170 windows, 552-556 word frequency, 745-477 writing a program. Sa Calculator example.
INDEX
11 98
Examples (continual) writing rues, 346-348 Z I P code detection, 828-836 c c)(ception>, 1097 Exceptions, 144- 148, 1086 Sa abc Error handling: Errors. bounds error, 147
C++ and C, 992 c.. tch, 145,238-240, 1087 cerr, 14 9 cout, 149 d CSlniClors,
1088
embedded systems, 894 error messages, printing, 148-149 exception, 150, 1099- 11 00 failure to catch, 15 1
GUIs,563 input, 148-151 narrow_casl example. 151 olT·by~nc
error, 147
ouc oCrange, 147
overview, 144-145 RAJ I (Resource Acquisition ls Initialization), 1087 range errors, 146-148 fe-throwing, 677, 1087 runtime_erro r, 14 0, 149. 15 1 Slack unwinding, 1088 standard library exceptions. 10991100 tcnni nating a program. 140 throw, 145. 1086 tru ncation. 15 1 type conversion, 151 uncaught exceptio n, 151 ust:r-dcrUlcd types. 1087 \'('clor range checking, 668-669
vecto r resources. Sa veclor. E.,xecuta ble code, 48. 1173 Executing a program . II . 11 54 ellitO. terminating a program. 1149 ellplicit constructor. 62 1- 622. 1003 Expression, 94-95. 1049-1054 coding smlldards, 940-9;11 consta nt expressions. 1056-1057
conversiolU. 1054-1056 debugging, 159 grouping 0 , 95, 83 1, 837. 840 lvaiue, 94-95, 1054 magic constants, 96, 14 1, 231-233,
697 memory management. 1057- 1058 mixing types. 98-99 non'obvious literals, 96 0l>crmor p!'(:cedellce, 95 opc.rators,97, 1049- 1059 order of opc.r.uiolls. 179 p!'(:cedellce, 1054 preserving values, 1054-1055 promotio ns, 98-99, 1054- 1055 rvalue, 9'~-95, 1054 scol>C !'(:solutio n, 1049 I)'IX couversion, 98-99, 10581059 usual arithmctic conversions. 1056 E;'(pression stateme nt. 99 Empty state ment. 1001 elliern. 257, 999 Exlr.lCling text from files, 820-825.
828- 830
F f/f sufflX , 1042 fai l() stream state, 349, ) 127 Falling through end of fu nctions. 2i2 faiSt', 1003-1004 Fault tolerance, 892 fclosc(), 10 19- 1020, 1140 Feature ottp. 186, 199, 11 73 Feedback. programming, 36 l-icJds, fonnauing. 383-384 FILE, 10 19-1020 E le 110, 343-344 binary 110. 387 convening represcntations. 368-
370 c!oscO. 3 46 closingfiles, 346, 1140- 1141 modes, 11 40-1141
IN DEX
open(), 346 opening flies. Su Opening files. positioning in flies, 389 reading. Su Reading fIIcs. writing. Sa Writing flies. Eles, 11 73 &ealJo Etc 110 . C++ and C, 1019-1020 opening and closing, C·sty[c lIO, 11 40-1 14 1 fi llO, 1116 Ell color cxamplc, 456-459, 492 fil CnO, 111 6 find O, 728-731 associativc containcr ol>cr,lIions, 1111 finding links, 600~602 generic usc, 731~732 non modifying sequencc alga· rithms, 11 13 string operations, 815, 1132 find~end O , 1113 find_firsCof() , 111 3 find jf(), 728, 732-734 Finding Set abo Matching; Scarching. associative container operations, 11 11 clcmcnts, 728 links, 600-602 pattcrns, 828- 830, 833-836 strin b'S, 815, 11 32 fi xed format , 383 fi xed manipulator, 38 1, 1130 f10il l t)1>C, 1062 , 858, 1136 Floating']>oint, 63, 855, 11 73 % remainder (modulo), 199 assigning integers to, 856-857 assigning to intcgcrs, 857 collvcrsions, 1055 fi xed fonnat, 383 generill format, 383 input, 180, 199- 200 intCb.....JI convcrsions, 1055
1199
litcrals, 180, 1042- 1043 mantissa, 857 OUtput, formatting, 380- 38 1 prccision, 382-383 and fCill numbcrs, 855 rounding, 382-383 scientific format , 383 trullcation, 857 vector example, 11 9- 121 000rO, 879, 11 37 FLT_DlG limit mllCro, 11 37 FLTK (Fast Light "Ioolkit), 4 14, 11 58 code ]>ortability, 414 color, 447, 459-461 current style, obtaining, 492 downloading, 1158 fill,459 in graphics code, 432 installing, 11 59 lines, drawing, 449, 452-453 outlines, 459 rectangles, drawing, 459 tesling, 11 60 in VISUal Studio, 11 59- 11 60 waiting for user actio n, 547- 548, 556-557 FLT_MAX limit macro, 11 37 FLT_MAX~ 1 0_EX P limit macro, 1137 FLT_MIN limit macro, 11 37 flush manipulator, 11 30 Hushing a buITer, 239-240 FOnlS for Graphics example, 463-464 fopenO, 1019-1020, 1140 for·stalement, 11 0-112 Ford, Henry, 772 for_each(), 1113 Formal arguments. Su Parameters. Fonnatting SaalJolIO strcams, 11 28- 11 29. SaalJoC-style 110, 1016-10 19. Saa/so Manipulators, 1129- 11 30. case, 393-394 fields, 383-384 precisioll, 382-383 whitcspace, 393
1200
INDEX
Fortran language, 786-788 array indexing, 863 complel, 882 subscripting, 863 Forward declarations, 259 For-vard ilcrawrs, 722-723, 1103 fprintf() , 1017, 1141 Fragmclll.1Iion, embedded systems,
898, 899 free(), deallocate, 1009-1010, 1147 Free store (heap slOrage) allocltion, 578-579 C++ and C, 1009- 10 II deallocation, 584--586 delete, 584-586, 586-590 and dCSlruCIOf'S. Sa destructors. embedded systems, 898-902 garbage collection, 585 leaks, 58.1- 586, 586-590 new, 578- 579 object lifetime, 1048 Freeing memory. Sa Dcallocating memory. friend , 1003, 1073-1074 from_slring() example, 817-818 fronl O, first clement, 1109 fronl_inserter(), 1122 fslream{) , 1126 ds tream>, 1096 fst ream type, 344-346 Fully qualified names, 29 1-293 function example, 439, 5 15-518 FUllction, 47, 112- 114 Sa abo Member functions. acccssingclass members, 1073- 1074 argu ments. &e Function arguments. in base classes, 496 body, 47, 11 3 C++ and C , 994- 998 callback, CUls, 544-546 calling, 1066 cleaning up, 233- 234 coding standards, 940-94 1 common style, 482-483 debugging, 158
declarations, 115-116, 1066 ddinition, 11 2, 269,1 173 in derived classes, 493, 496 falling through, 2n fom)al argu men ts. See Function parameters. fri end declaration, 1073-1074 generic code, 483 global variables, modifying, 267 graphing. Sa FunClion example. inline. 3 12, 992 link.a~ specifications, 1069 naming. Sa Namespaces. nesting, 267 organizing. Set Namespaces. ovcrload resolution, 1067- 1068 overloading, 3 16-318, 516, 992 parameter, 11 3. Sa abo Function parameters. poimer to, 1000- 1002 posHonditions, 163-164 prc-= comp.1rison, 1132 Gstyle strings, 1012 le.icographica Lcomparc(), 1121 Libraries, 51, 1174 &to alw Standa rd library. role in debugging, 158
Limit macros, 11 36- 1137
Limits, 858 , 858, 1096, 11 35 , 1095 Lists containers, 111 0 doubly linked. 598, 698 empty, 702 erasing clements, 713-715 examples, 598-600, 704-7 11 lindillg links, 600-602 getting the nth clemem, 600-602 inserting clements, 600-602, 71371 5 iteration, 70 1- 703, 708-71 1 link manipulation, 600-602 links, examples, 598-600. 606-607, 699 operations, 699-700 removing elements, 600-602 singly linked, 598, 698 this pointer, 603-605 Literals, 62, 104 1, 1174 character, 159, 1043-1044 decimal integer, 1041 in expressions, 96 f/ F suffix, 1042 Ooating-point, 1042- 1043 hexadecimal integcr. 1041 integer, 1041 Il L suffix, 1041 magic constants, 96, 14 J, 23 I -233, 697 non-obvious, 96 null poimer, 0, 1044-1045 numbcr systems, 1041- 1042 octal integer, 1041 special characters, 1043- 1044 string, 159, 1044 tellllinalion, debugging, 159 for types, 63 u/u suffix, 1041 unsigned, 104 1
1209
Local (automatic) o bjects, lifetime, 1048 Local classes, nesting, 268 Local functions, nesting, 268 Local scope, 265- 266, 1046 Local variables, army pointers, 636-637 Locale, 402 , 1097 logO, 879, 11 37 log100 , 879, 1137 Logic errors. Set Errors, logic. Logical and &&, 1052 , 1057 Logical operations, 1057 Logical or II , 1053, 1057 10gical_andO. 1122 logical_notO, 1122 logical_orO, 1122 Logs, graphing, 517-518 lo ng imegcr, 917, 1062 LONG_MAX limit macro, 1137 LONG_MIN limit macro, 1137 Look-ahead problem, 202-207 Loop, 109, 111 , 1174 examples, parser, 198 inlinite, 196, 1173 testing, 965-966 variable, 109, III Lovelace, Augusta Ada, 797 lower, 842, 1134 10wer_boundO, 764 , 111 2, 1117 Lower case. See Case. Ll,celll Bell Labs, 803 Lvalue, 94-95, 1054
M Machine code. Set Executable code. Macro substitution, 1090-1091 Macros, 1021-1022 conditional compilation, 10241025 t define, 1022-1024, 1090-1091 function·like , 1022-1023 .::'ifdef, 1024-1025 .::'ifndef, 1025 ti nclude, 1024, 1090 include guard, 1025
INDEX
1210 Macros (continI/ell) naming conventions, 102 1 syntax, 1023-1024 uses for, 1021 Maddoc.J o hn, 830 Magic constan ts, 96, 141 ,23 1-233, 697 Magical appro.leh 10 programming. 10 mainO, 46-47 arguments to, 1040 glo bal objects, 1040 return values. 47, 1039-1040 starling a program , 1039- 1040 Mailllainability, sofnvare, 34, 775 Maintenance. 891 make_heapO. 11 19 ma ke_pairO, 751 , 1124 nla ke_vecO, 677 maliocO, 1009, 1147 Ma nipukllors, 378, 1129- 113 1 complete list of, 11 29-1130 dec, 11 30 e ndl, 11 30 fi xed, 1130 hex. 1130 noskipws, 1129 oel, 11 30 resetiosilags{), 11 30 scientific, 11 30 setiosflags(), 11 30 setprecisio n(}, 11 30 skipws. 11 29 Ma ntissa, 857 ma p, associative array. 744- 750 Sa (1iJO set; unorde red_map. I I, subscripting, 745, 1111 b..llanced trees, 748- 750 bina ry search lI'ees, 747 case sensitivity, N03 ase example, 762- 763 counting wo rds example. 745- 747 Dow J ones example, 750- 753 em:!il example, 820-836 eraseO, 749, 1110 finding clements in. 745. 749, 1111 - 111 2
fruits example. 747- 750 inserlO, 750, 751. II 10 iterators, I 105 key storage, 745 make_pairO, 751 N03 ase example, 750, 762-763 Node example. 747- 750 red·black trees, 747 14. set. 756 standa rd libralY, 1107- 111 2 tree structure, 747-750 witho ut values. Sa sci. , 744 , 1095 mappefU yfX!, 1108 Margi nal ale rts, 3 M= greater than or equal. \052 » shirl right, 105 1. Su (Usc islream. »= shift right and assign, 1053 f: conditional expression (arith· metic if) , \053 [I subscript, \050 " bitwise exclusive or, \052, 1057 "= xor and assign, 1053 I bitwise or. 1052, \057 I = or and assign, \053 II logic.11 or. \053, \057 ~ complement. 1050 additive operators, 105 1 cons,-c.asl, \050, 1058 delete, 1051. \057- 1058
1215
delelell, 105 1, 1057- 1058 derererence. Set ComenlS or. dynamic_cast, 1050, \058 expressions, 1049- 1059 new, 1050, 105 1, 1057-1058 reinlerpre,-casl, 1050, 1058 si~ COnability, I I lJJ.
C++, 1039 FLIT, 414 , 11 58 l>Ositioning in files, 389 Post-conditions, 163- 164 , 96 1-962, 1175. Set abo Lwanants. l>Ost-deeremelll - - , 1050, 1064 Post-incremcnt ++, 1050, 1064 l>Ostfix expressions, 1050 Pre-conditions, 161 - 163, 96 1-962, 1175. See abo Invariants. Pre-dcerelllelll -- , 1050, 1064 Prc-ineremc.1ll ++, 1050. 1064 Precedence, in expressions, 1054 Precision, numeric, 382-383, 854-858 Predicates, 733 on class members, 737-738 function objects, 1122-1123 passing. Set FunClion objects. searching, 733-734 Predictability, 893 error handling, 895 features to avoid, 894 memory allocation, 898, 902 Preprocessing, 263
INDEX
1218
Preprocessor din.:ctivcs : define, macro substitution, 1090109 1 :ifdef, 1024 :ifndef, 1025 tinclude, including headers, 10901091 Pn::: proccsso r, 1090 coding standa rds, 939 prev_permutation(), 11 20 Princeton U niversity, 803 print, chamcter class, 842, 1134 Pri ntable chamcters, idemifying. 393 printfO family % , conversion spc:cific.ation, 1141 conversion spc:cificatlons, 11 4 11143 gelsO, 10 18, 1144-1145 output fon nalS, uscr-defined types. 1144 padding, 1143 printfO, 1016- 1017, 1141 scanfO, 1017- 1019, 1144-1145 slderr, 11 44 sldin, 1144 stdio. 11 44- 1145 stdout, 1144 synchronizing with 110 streams, 1016-10 17 truncation, 1143 Printing error messages, 14 8- 149 variable valucs, 246 priority_queue comainer adaptor, 1106 Private, 308 base classes, 502 implcmcmation details, 208, 302304, 308-309 members, 484-485, 496, 50 1- 502 private: label, 302 , 1003 Problelll analysis, 173 de"clopment stages, 174 estimating resources, 175 problem statement, 174- 175 prototyping, 176 strategy, 174- 176
Problem st.1tement, 174-175 Procedural progr.lmming languages, 781 Programmers Sa (dso Programming. commun.icmion skills, 22 computation ideals, 92-94 skills n:::quin.:ments, 22-23 stereotypes of, 2 1-22 worldwide numbers of, 807 Progranu n ing, xxiii, 11 75 Sa al.w Computation ; Software. abstract-first approadl, 10 analysis stage, 35 author's philosophy, 6-9 boltom-up approach, 9 C fi rst approach, 9 concept-baM:d appro.-tch, 6 concrete-first approach, 6 depth·first approach, 6 design stage, 35 environmenlS, 52 fcedb.1ck, 36 generic, 1173 implementation, 35 magical approacll, 10 object-oriented, 10, 1174 programming stage, 35 softwan.: engineering principles first appro.1ch, 10 stages of, 35 testing stage, 35 top-down approach, 10 writing a program. Sa Calculator example. Progranuning languages, 783- 784 , 786, 807 Ada, 796- 798 Algol family, 791 - 798 AlgoI60,792- 794 asM:mblers, 785 auto codes, 785 BC P L.803 C , 8OO- 804 Ct, 796 C++,804-806
1219
INDE X
COBOL, 788-790 Common Lisp, 790 Delphi. 796 Fo rtran, 786- 788 Lisp. 790-791 Pascal, 794-796 Scheme, 790 Simula. 798-800 Turbo Pascal. 796 Programming philosophy, 772- 773, 1175. Set aLso C++ programs; Programming idcals; Programming languages. Programming ideals abstraClion level, 778- 779 aims_ 772- 774 bOllom-up approach, 776-777 code structure, 776 consistency, 780 correct approaches, 776- 777 correctncss, 775 data abstraction, 78 1 desirable propenies, 773 direct expression of ideas, 777-778 efficiency, 775-776 gencric programming, 782 KISS, 780 maintainability, 775 minimalism, 780 modularity. 779-780 multi-paradigm, 783 object-oriellied programming, 781 783 olHimc delivery, 776 ovel>'icw, 774-775 paradigms, 78 1- 783 pcrfonnancc, 775-776 philosophies, 772-774 procedural. 78 1 styles, 781 -783 top·down approach, 776-777 Programming, history. 783-784 Sa aLso Programming languages. BN F (B.,ckus-Nau r) Fo rnl, 788, 793 classes, 799
CODASYL committee, 789 early languages, 784-786 first documented bug. 790 first modern s tored program, 784-
786 first progmnuning book, 785 function calls, 785 functional programming, 788 inheritance, 799 K&R, 802 lim, 801 object-oriemed design, 798- 799 STL (Standard "Ie mplate Library).
805-806 virtual functions. 799 Programs, 44. 1175 Sa abo Computation; Software. audiences for, 46 compiling. Sa Compilation. computing values. S« Expressio ns. confornling, 1039 experimental. S« Prototyping. flow, u-acing, 72 implementation defmed, 1039 legal, 1039 linki.ng, 5 1 not-confonning constructs. 1039 run. Sa VISUal Studio; Command line. startingc.'lccution, 46-47, 1039- 1040 slOred on a com pUler, 108 subdividing, 175-176 terminating, 206-207, 1039-1040 text of. S« Source codc. translation units, 51 troubleshooting. S« Debugging. unspecified constructs, 1039 valid, 1039 writing, example. S« CaiUllator example. ,mung your first , 45-47 Program organization Sa abo Progranuning ideals. abstraction, 92-93 divide and conquer, 93 Projects, Visual Studio, 11 53-1154
INDEX
1220
Promotions, 98-99, 1054-1055 Prompting ror input, 6 1 >, input prompt, 221 calculator example, 177 sample code, 220-223 Proofs, testing, 952 protected, 484-485, 496, 502, 1003 Prototyping, 176 Pseudo code, 177, 1175 Public, 302, 1003 base class, 500-501 interface, 208, 488-49 1 member, 302 public by default, shuet, 303 public: label, 302 punct, punctuation character elass, 842, 1134 Punet_strea m example, 397-401 Pure virtual functions, 487, 1175 push_baclcrations, II 10 membcr tYl>Cs, I 108 opcr..uions o\'efview. I 107 qucue operations. 11 10 sequence, 1105 5;1.e. 111O- 111 1 st;!ck operations, 1110 swapping, 1111 Sl"L function objects. 1122- 11 23 adaptors, 11 23
arithmctic opera tions, 1123 inserters, 1121-1 122 prcdicates. 738-738, 1122- 11 23 STL iterators. 1100- 1105 basic OI>Cntlions, 695 categories, 1103- 1105 definition, 694, 11 00-110 1 description, 695-696 cmpty lists, 702 example. 708-7 11 operations, 1102- 1103 Uf. pointers, 110 I sequence of clemcnts, 11 01- 1102 Storage class, 1047- 1048 automatic storage, 1047 frec storc (heap), 104 7 slatic storage, 1047 Storing data. Sa Containers. slrO. Siring extractor, 390-391 SlrcalO, 101 2- 10 13, 1146 slrchrO, 1014 , 114 6 slrcmpO, 1012- 1013, 11 46 slrcpyO, 101 2-10 13, 1015, 11 '~ 6 Stn::am buffers, 1125 iterators, 758-76 1 modes, 1126 states, 349 t}1>Cs, 1126 slreambuf, 402 , 11 25 , 1096 , 1096, 11 28 String literal, 62, 1044 siring, 66, 815, 11 75
Sa aI.w l ex!. + concatcnation, 68-69, 815. 11 32 +'" ap pend, 8 15
< lexicographical comp;uison, 8 15 « Output. 815 '" assign, 815 == equal, 8 15 » input, 8 15 II subscri pting, 815 almost container, 1106 appendO,8 15 basicstring. 8 16
INDEX
1228
string (amtinutd) C++ to C Slyle conversion, 815 c_slrO. C++ to Cstylc COllversion. 345, S15 eraseO, removing characters, SIS exceptions, 1099 findO . SIS from_slringO, S17-S18 getlineO. SIS input temlinator (whitesp.lce), 65 InserlO, adding characters, SIS lenglhO, number of characters, SIS lexicaCcast example, S I9 literals, debugging, 159 operations, SIS, 11 32 operators, 66- 67, 6S palindromes. example, 637- 638 pattelll matching. Set Regular exprcsslons. properties, 712- 713 size, 78 sizeO, number of characters, SIS standard library, S I6 siring to value conversion, 817- 818 slringslream, 816- S1S subscripting il, SIS lo_stringO example, 8 16- S18 values to string conversion, 8 16 V.i . vector, 715 whitespace, 8 1S-S 19 slringslream. 390- 391 , S I6-S18, 11 26 SlrlenO, 1012, 1146 SlrncalO, 1012-1013, 1146 slrncmpO, 1012-10 13, 1146 slrncpyO, 1012-10 13, 114 6 Strong guarantee, 677 Stroustrup, Bjallle advisor, 785 biography, 14- 15 Bell L.lbs colleagues. 80 1- S04, 989 education on invariants, 793 inventor of C++, 804-S06 Kristen Nygaard. 799 slrpbrlcO. 11 46 slrrchrO. 11 46 slrslr(). 11 46
strtod(), 1146 5Irtol(), 1146 5lrloul0 , 1146 slruct, 303- 304. Sat/Iso Data stnJclUrcs. SlruCI tag namespaee, 1002- 1003 Structure of data. Set Data stntctures. o f programs, 213- 2 14 Structured liles, 361- 370 Style, definition. 1176 Sub· patterns, 83 1, S34 Subclasses, 496, 1116. Sa also Derived classes. Subdividing programs, 175- 176 Subscripting, 116-11 7 o Fortran style, 863 II C Sty lc, 669, 863 arrays, 628. S63 atO, eheckcd subscripting. 669, 11 09 Malr;)( exam pic. 863-865, S69 po inters, 1064 string, 815. 11 32 veclor, 579-580, 592-593. 625626 Substrings. S27 Subtract and assign - =, 67, 1053. 1103 Subtraction - (minus) comple.. , S8 1, 11 38 definitio n, 1051 integers. 1064 iterato rs, 1104 pointers, 1064 Subtype, definition, 11 76 Summing valucs. Set accumulateO. Superclasses, 496, 1176. Sa also Base classes. swapO. 279, 1111 , 1116 Swapping columns, 870 containers, 1I11 ranges. 1116 rows, 870, S76 swapJ"nses{). 1116 switeh-statelllclllS break, case tc rmination, 104- 107
IND EX
1229
nse labels, 104-107 most comlllon error, 107 Uf. string·based selection, 105 Symbol tables, 246 Symbolic COnStantS 5« also Enumcrations. clcaning up, 23 1- 233 defining, wiLh slatic consl, 32 1 Symbolic names, tokens, 232 S),mbolic rcpresentations, read ing, 368- 370 Syntax analyzers, 188 Syntax checking, 48-50 Syntax errors examples, 48-50 overview, 135-136 repo ning. 135-136 Syntax macros, 1023- 1024 systcmO, 11 49 Systcm, definition, 1176 System tests, 969-973
T \I tab character, 108, 1043 lanO, torlS, retention period, 953 calculator example, 223-227 classes, 973-976 code coverage, 968 debugging, 979 dependencies, 962-963 designing for, 978- 979 faul ty assu mptions, 976-978 Iiles. after opening, 346 FL"I"K, 11 60 inputs, 961 loops, 965- 966 non·algorithms, 96 I-968 outputs, 961 pcrrom13llce, 979-983 pre· and post-conditions, 961 - 962 proofs, 952 RAI l, 964- 965
I NDEX
'23{)
Testing (conhium:l) ~grcss ion tests, 953 rcsoura: management, 964-965 reso urces, 962 stage of programming, 35 Slate, 96 1 system tests, 969- 973 tCSt cases, definition, 164 leSt harness, 957-959 liming, 98 1-983 white box, 952-953 l ating units fomlai specification, 954-955 random sequences, 959-96 1 stra tegy for, 955- 957 systematic tcsting, 954- 955 test harness, 957-959 Text character stri ngs. See siring: C -stylc strings. email example. 820-825, 828-830 extracting text (rom fdes, 820-825. 828- 830 find ing patterns, 828-830, 833836 in graphics. Set Text. implementation details, 826-828 inputloutput, GU Is, 550-551 maps. Su map. storage. 577 substrings, 827 vector example, 12 1- 123 words frequency example, 745-
7'17 Text example, 427- 429, 462-464 Text editor example. 708- 711 111ela, 88 1 this pointer, 603-605, 654- 655 Tnompson, Ken, 80 1-803 -!luee-wa), comp.1rison, 101 2 lluowing exceptions, 145, 1086 110 strea m, 1127 fe -throwing. 677 standard library. 1099- 11 00 throw, 145. 1053. 1086- 1088 \lector, 672-673
Time date and ti me, 1147- 11 49 measuring, 981 -983 1i mekccping. computer usc, 26 time_I, 1147 T Ul), Encryption Algorithm (ll~A), 785, 930-935 1m, 11 47 Token example, 181 - 184 Token_strt'am example, 204-2 12 tolowerO, 394.113 1 Top·down approach, 10, 776- 777 to_slringO example. 8 16-8 18 loupJJC!r{), 394 , 11 3 1 Tracing code execution, 160- 16 1 T rade-off, defini tio n, 1176 transform O. 1114 Transient errors, handling, 895- 896 Translation units, 51. 137- 138 TransparcnC)', '~ 47. 457 Tree smlClurc, map container, 747-750 true. 1003, 1004 trunc mode, 385. 11 26 Truncation, 82, 1176 C·stylc 110, 11 43 c.xceplions, 15 1 floating·point numbers, 857 try-catch. 144-150, 668- 669, 1003 Tu rbo Pascal language. 796 Two·dimensional m,uriccs, 868-870 1\\"0'5 complcmetlt, 922 1}'}>C convcrsiOIl casting, 594- 595 consLcast, casting awa), eonst, 594-595 exceptions, 151 explicit, 594 in expressions, 98- 99 fu nction arguments, 28 1- 282 implicit, 621-622 int to pointer. 576 opcratOI'S, 1058- 1059 poimers, 576, 594-595 reinlerpreLcasl,594 safety, 79- 83 static_cast, 594
INDEX
1231
siring to valuc, 817-818 tnlllcation, 82 valuc to string, 816 -rypc conversion, implicit, 621-622 bool, 1055 compiler warnings, 1055- 1056 fioating-poilll and illlcgral, 1055 illlegral promotion, 1054-1055 pointcr and refcrcncc, 1055 preserving values, 1054- 1055 prolllOlions, 1054- 1055 user-dcfincd, 1056 usual arithmetic, 1056 "lyPc safety, 78- 79 implicit convcrsions, 80-83 narrowing convcrsions, 80-83 poimers, 580- 583, 634-637 range error, 146-148.580- 582 safc conversions, 79-80 unsafc conversions, 80- 83 typedef, 703 Iypeid, 1003, 1050, 1099 , 1097 Iypename, 1003, 1086 Type, 60, 77, 1176 aliases, 703 buill-in. &e Built-in types. chccking, C++ and C , 998- 999 generators, 658- 659 graphics classes, 480-482 mislJ},l(eh errors, 136-137 mixing ill expressions, 98- 99 naming. &e Namcspaces. objccts. 77- 78 operations, 30 I organizing. &e Namespaces. paramcterized, 659- 661. Su aiJo "Ie mplatcs. as parameters. &e Tcmplates. poimers. &e Poimer. promotion, 98- 99 represe ntation of objcct, 304, 497-
499 safety, 78- 79, 82 subtype, 1176 supcrtype, 1176
tmncm.ion, 82 use r-defincd. &e UDTs_ uses fo r, 300 values, 77 variables. Set Variables, types.
u ufu suffIX. lO,n \U , "not uppercase," regex, 838, 1135 \ u, "uppercase character," regex, 837, 1135 UDT (User-defined type). SetClass; Enumeration. U nary expressions, 1050-1051 "Uncaught exception" crror, 15 1 U nehccked conversions, 905 "Undeclared idcntifier" error, 256 Undcfulcd ordcr of cvaluation, 261 ungel(), 349- 352 ungelcO, 1145 Uninitia1ized variables, 322-325, 11 76 uninilialized_copyO, 1116- 111 7 uninilialized_fiIl O, 1116- 111 7 union, 1082- 1083 uniqueO, 1114 unique_copyO, 728, 757, 760- 761 , 1114 UnittesLS formal spccificluion, 954- 955 random sequences, 959-961 strategy for, 955-957 systematic testing, 954-955 test harness, 957-959 Unnamed objecLS, 459-461 , 744, 1096 unordered_map, 744 See also map. finding ciemenlli, 753- 755 hash tables, 753 hash values, 753 hashing, 753 itcrators, I 105 unordered_mullimap, 744 , 1105 unordered_mullisel, 744 , 1105