Download C++ 1: Introduction to C++ - O`Reilly School of Technology
Transcript
C++ 1: Introduction to C++ (PDF) Lesson 1: Introduction Learning C++ Hist ory of C++ About Eclipse Perspect ives and t he Red Leaf Icon Writ ing Your First Program What Does It All Mean? Adding t o Our Program What Goes On Under t he Hood Finishing t he Program T he User Manual T he T est Plan A Few More Not es Lesson 2: Expressions Mat hemat ical Expressions Creat ing t he Project and File Edit ing and Running Your Program T ypes of Numbers Float ing-Point vs. Int eger Division Dividing by Zero Limit s on Numbers Common Problems Lesson 3: Variables Basic Programs Variables Variable Def init ions Variable T ypes: Int eger Variable T ypes: Float ing Point Variable T ypes: Charact ers Escape Charact ers Wide Charact ers Boolean Mixing T ypes Lesson 4 : Arrays and For Loops Using Arrays T he const Modif ier Our f irst array f or loops Array Saf et y Lesson 5: C++ Strings St rings in C++ Charact ers in st rings Ot her Funct ions Lesson 6: C-Style Strings What is a C-St yle St ring? Concat enat ion of C-St yle St rings Comparing St rings T ips Convert ing C++ St rings t o C-St yle St rings Unsaf e St ring Funct ions T he f ut ure of st rcpy() and st rcat () Comparisons t o ot her t ypes C St rings vs. Arrays of Charact ers C-St yle vs. C++ St yle Lesson 7: Reading Data and if Reading St rings Reading Int egers if St at ement s if Abuse Equalit y or Assignment ? Blocks Condit ional Short cut s Lesson 8: Shortcuts Operat ors For Loops For Loop Misuse Side Ef f ect s Lesson 9: While Loops while, break, and cont inue Fibonacci numbers Lesson 10: Scope What is Scope? Global Variables St orage Class f or Loop Scope Hidden Variables Lesson 11: Functions What is a Funct ion? Our First Funct ion Void Funct ions and Array Paramet ers Funct ion Overloading Def ault Paramet ers Lesson 12: Parameters and Return T ypes Passing Paramet ers Pass by Value Array Paramet ers Const Paramet ers Ref erences Const Ret urn Values Problems wit h Ref erence Ret urns Lesson 13: Final Project Put t ing It All T oget her Assignment Code Design Agile Development Coding Not es T est ing Revisions Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Introduction C++ 1: Introduction to C++ Lesson 1 Welco me to the O'Reilly Scho o l o f Techno lo gy's C++ co urse! We're glad yo u've decided to go o n this ride with us and learn C++ pro gramming. By the time yo u finish the co urse, we're co nfident that yo u'll have firm grasp o n this really practical pro gramming language. If yo u've already taken an O'Reilly Scho o l o f Techno lo gy (OST) co urse, yo u're familiar with the useractive appro ach to learning. It's an appro ach where yo u (the user) will be active! Yo u'll learn by do ing, building live pro grams, testing them, and then experimenting with them, hands-o n! Learning with O'Reilly School of T echnology Courses As with every O'Reilly Scho o l o f Techno lo gy co urse, we'll take the useractive appro ach to learning. This means that yo u (the user) will be active! Yo u'll learn by do ing, building live pro grams, testing them and experimenting with them— hands-o n! To learn a new skill o r techno lo gy, yo u have to experiment. The mo re yo u experiment, the mo re yo u learn. Our system is designed to maximize experimentatio n and help yo u learn to learn a new skill. We'll pro gram as much as po ssible to be sure that the principles sink in and stay with yo u. Each time we discuss a new co ncept, yo u'll put it into co de and see what YOU can do with it. On o ccasio n we'll even give yo u co de that do esn't wo rk, so yo u can see co mmo n mistakes and ho w to reco ver fro m them. Making mistakes is actually ano ther go o d way to learn. Here are so me tips fo r using O'Reilly Scho o l o r Techno lo gy co urses effectively: T ype t he co de . Resist the temptatio n to cut and paste the example co de we give yo u. Typing the co de actually gives yo u a feel fo r the pro gramming task. Then play aro und with the examples to find o ut what else yo u can make them do , and to check yo ur understanding. It's highly unlikely yo u'll break anything by experimentatio n. If yo u do break so mething, that's an indicatio n to us that we need to impro ve o ur system! T ake yo ur t im e . Learning takes time. Rushing can have negative effects o n yo ur pro gress. Slo w do wn and let yo ur brain abso rb the new info rmatio n tho ro ughly. Taking yo ur time helps to maintain a relaxed, po sitive appro ach. It also gives yo u the chance to try new things and learn mo re than yo u o therwise wo uld if yo u blew thro ugh all o f the co ursewo rk to o quickly. Expe rim e nt . Wander fro m the path o ften and explo re the po ssibilities. We can't anticipate all o f yo ur questio ns and ideas, so it's up to yo u to experiment and create o n yo ur o wn. Yo ur instructo r will help if yo u go co mpletely o ff the rails. Acce pt guidance , but do n't de pe nd o n it . Try to so lve pro blems o n yo ur o wn. Go ing fro m misunderstanding to understanding is the best way to acquire a new skill. Part o f what yo u're learning is pro blem so lving. Of co urse, yo u can always co ntact yo ur instructo r fo r hints when yo u need them. Use all available re so urce s! In real-life pro blem-so lving, yo u aren't bo und by false limitatio ns; in OST co urses, yo u are free to use any reso urces at yo ur dispo sal to so lve pro blems yo u enco unter: the Internet, reference bo o ks, and o nline help are all fair game. Have f un! Relax, keep practicing, and do n't be afraid to make mistakes! Yo ur instructo r will keep yo u at it until yo u've mastered the skill. We want yo u to get that satisfied, "I'm so co o l! I did it!" feeling. And yo u'll have so me pro jects to sho w o ff when yo u're do ne. Lesson Format We'll try o ut lo ts o f examples in each lesso n. We'll have yo u write co de, lo o k at co de, and edit existing co de. The co de will be presented in bo xes that will indicate what needs to be do ne to the co de inside. Whenever yo u see white bo xes like the o ne belo w, yo u'll type the co ntents into the edito r windo w to try the example yo urself. The CODE TO TYPE bar o n to p o f the white bo x co ntains directio ns fo r yo u to fo llo w: CODE TO TYPE: White boxes like this contain code for you to try out (type into a file to run). If you have already written some of the code, new code for you to add looks like this. If we want you to remove existing code, the code to remove will look like this. We may run pro grams and do so me o ther activities in a terminal sessio n in the o perating system o r o ther co mmandline enviro nment. These will be sho wn like this: INTERACTIVE SESSION: The plain black text that we present in these INTERACTIVE boxes is provided by the system (not for you to type). The commands we want you to type look lik e this. Co de and info rmatio n presented in a gray OBSERVE bo x is fo r yo u to inspect and absorb. This info rmatio n is o ften co lo r-co ded, and fo llo wed by text explaining the co de in detail: OBSERVE: Gray "Observe" boxes like this contain information (usually code specifics) for you to observe. The paragraph(s) that fo llo w may pro vide additio n details o n inf o rm at io n that was highlighted in the Observe bo x. We'll also set especially pertinent info rmatio n apart in "No te" bo xes: Note T ip No tes pro vide info rmatio n that is useful, but no t abso lutely necessary fo r perfo rming the tasks at hand. Tips pro vide info rmatio n that might help make the to o ls easier fo r yo u to use, such as sho rtcut keys. WARNING Warnings pro vide info rmatio n that can help prevent pro gram crashes and data lo ss. Learning C++ C++ is the wo rkho rse language o f the pro gramming wo rld. It's used fo r many different applicatio ns, fro m high-end graphics systems to embedded pro cessing. Chances are yo u already o wn two o r three co mputers running C++ pro grams, o nly they aren't called co mputers, they're called cell pho nes, GPS systems, cameras, o r DVD players. Our co urse is designed to teach yo u ho w to do real-wo rld, practical pro gramming. As such, it will teach no t o nly the best practices when it co mes to design and co ding, but also ho w to deal with the "wo rst practices" that seem to seep into many o f the pro grams o ut there in the real wo rld. Fo r this co urse, we will use the Advanced O'Reilly Learning Sandbo x. This system allo ws yo u no t o nly to read the lesso ns, but to interact with the examples. Yo u are enco uraged to experiment and try new things, all within the enviro nment o f yo ur O'Reilly Learning Sandbo x. Of co urse, in the real wo rld yo u'll make mistakes. Typing in a pro gram, finding that it's bro ken, and sweating o ver it until 2 o 'clo ck in the mo rning, o nly to find yo u've made a small mistake, is ano ther way o f learning. (We ho pe yo u will rarely need to use this metho d o f learning!) History of C++ C++ was bo rn in 19 70 when two pro grammers wanted a "high-level" language fo r a machine they were wo rking o n. They designed a language similar to an o ld language they had been using called B. In the pro gramming traditio n o f keeping things simple, they named their language C. C was a go o d language fo r its day. It ran o n very limited hardware (4mhz, 6 4K memo ry) and did a pretty go o d jo b. The language was also designed no t to get in the way o f the pro grammer. In o ther wo rds, if he wanted to do so mething stupid, it let him. C is a pro cedural language. The data and instructio ns are kept separate. Ten years after its inventio n, peo ple realized that they co uld make better pro grams if they co mbined data and the instructio ns that o perated o n the data into o ne thing called an o bject o r class. In 19 8 0 Bjarne Stro ustrup started wo rking o n a new language called "C with classes." The go al o f the language was to bring classes to C while no t breaking existing C co de (o r at least no t breaking it to o badly). This language wo uld beco me C++. About Eclipse We're using an Integrated Develo pment Enviro nment (IDE) called Eclipse. It's the pro gram filling up yo ur screen right no w. IDEs assist pro grammers by perfo rming many o f the tasks that need to be do ne repetitively. IDEs can also help to edit and debug co de, and o rganize pro jects. Perspectives and the Red Leaf Icon The Ellipse plug-in fo r Eclipse, develo ped by the O'Reilly Scho o l o f Techno lo gy, adds an ico n to the to o lbar in Eclipse. This ico n is yo ur "panic butto n." Eclipse is versatile and lets yo u mo ve things like views and to o lbars. If yo u ever get co nfused and want to return to the default perspective (windo w layo ut), the Red Leaf ico n is the mo st efficient way to do that. Yo u can also change perspectives by clicking the dro p-do wn arro w beside the ico n, and then clicking a series name (JAVA, PYTHON, C++, etc.). Mo st o f the perspectives lo o k similar, but subtle changes may be present "under the ho o d," so it's best to use the perspective designed specifically fo r each co urse. Fo r this co urse, select C++: Okay, no w that yo u understand the basic structure o f an OST co urse, yo u're ready to enter and run co de! Writing Your First Program We want yo u to see a wo rking C++ pro gram as so o n as po ssible, so we'll resist the urge to explain to o much fo r this first pro gram while yo u're creating and running it. Let's get go ing—we'll fill yo u in o n the details later! To start yo ur pro ject, select File | Ne w | C++ Pro je ct , as sho wn here: Note If C++ Pro je ct isn't o n the menu, then the perspective hasn't been set pro perly. Click the do wn arro w next to the Red Leaf ico n and then select C++ The C++ Pro ject type dialo g appears. Fo r Pro ject Name, enter he llo _wo rld. Note Due to limitatio ns in the GNU to o ls, all pro ject names and file names sho uld co nsist o f o nly letters, digits, and undersco res. Do no t use punctuatio n o r spaces in a name. It co nfuses the to o ls and causes things to break. Fo r "Pro ject Type," select Exe cut able | Em pt y Pro je ct . Under "To o lchains," select MiniGW GCC (the default). Then, click Finish: If yo u are pro mpted to o pen the C++ perspective, check the "Remember my decisio n" bo x and click No : New pro jects are added by default to the Other Pro jects wo rking set. To help keep yo ur pro jects o rganized, we'll mo ve them to the C++1_Lesso ns wo rking set. Find the he llo _wo rld pro ject in the Other Pro jects set, right-click it, and select Assign Wo rking Se t s.... In the dialo g bo x that appears, check the bo x fo r C++1_Le sso ns and click OK: No w we'll set up the pro ject's building behavio r. Right-click the he llo _wo rld pro ject again, and then select Pro pe rt ie s. Select C/C++ Build, then click the Be havio r tab. Check the Build o n re so urce save (Aut o build) bo x and click OK: Yo u will need to do this fo r every pro ject yo u create. If yo u do n't, when yo u try to run pro grams fro m the pro ject, yo u'll see this message: "Launch failed. Binary no t fo und." It isn't po ssible to set this flag as the default. But just in case yo u need to refresh yo ur memo ry o n o ccasio n, we've pro vided a checklist o f the steps yo u need to take in o rder to start a pro ject. Okay, we're ready to create o ur pro gram. Find the hello _wo rld pro ject in the C++1_Lesso ns wo rking set and select it, then select File | Ne w | So urce File : Enter the name he llo .cpp and click Finish: The new file he llo .cpp appears, with a sho rt header co ntaining the filename, the date, and yo ur name. In he llo .cpp, add co de as sho wn belo w: CODE TO TYPE: /* * hello.cpp * * Created on: Dec 15, 2009 * Author: smiller */ #include <iostream> int main() { std::cout << "Hello World!" << std::endl; return(0); } As yo u type, yo u'll no tice that the system auto matically co mpletes certain items. Fo r instance, when yo u type <, it adds a >. And after yo u enter the line that co ntains int m ain() {, Eclipse auto matically indents the next line by fo ur spaces and adds the clo sing bracket } o n the fo llo wing line. Eclipse is yo ur friend, and do es its best to help whenever it can! Select File | Save All to save yo ur file: Co ngratulatio ns, yo u've just written yo ur first C++ pro gram! No w let's run it. In the edito r windo w fo r yo ur he llo .cpp pro gram, right-click and select Run as | Lo cal C++ Applicat io n: Note To run a pro gram, yo u can also select it in the Package Explo rer and click the Run ico n ( ) in the to o lbar at the to p o f the screen. In the future, we'll use that ico n when we want to run the pro gram. A Co nso le windo w appears, co ntaining the o utput fro m yo ur pro gram: Excellent! Yo u've run yo ur first C++ pro gram! No w let's screw it up. We're do ing that o n purpo se no w, so we'll kno w what it lo o ks like and ho w to fix it when we screw up o ur pro grams later by accident. Mo dify he llo .cpp as sho wn belo w: CODE TO TYPE: #include <iostream> int main() { standard::cout << "Hello World!" << std::endl; return(0); } Note We o mit the header co mments fro m so me o f o ur examples in o rder to save space. In yo ur real pro grams, yo u sho uld always include descriptive co mments. Save yo ur file (File | Save all). A red ico n appears o n the left side o f the panel near the line yo u just changed. If yo u put the mo use po inter o n the ico n, yo u'll see this message: This tells yo u that so mething bad happened. In particular, the co mpiler can't figure o ut what the symbo l st andard means. Fix the pro blem by changing st andard back to st d, then save the file. The red ico n sho uld go away. No w let's create a new pro blem fo r o urselves. Mo dify he llo .cpp belo w as sho wn: CODE TO TYPE: #include <iostream> int main() { int std::cout << "Hello World!" << std::endl; return(0); } Save the file. Yo u'll see an x erro r ico n o n the the st d::co ut line: So what happened? Eclipse flags erro rs with an x erro r ico n. Ideally, it appears o n the line where yo u made the mistake, but so metimes (like no w), it do esn't. (Ho wever, in this case yo u do see a small yello w bo x co ntaining a questio n mark o n the int m ain line. Eclipse's internal parser detected an erro r o n this line and flagged it that way.) When Eclipse flags erro rs in yo ur pro gram, yo u still might need to do so me investigative wo rk to find and fix them— and it's a go o d idea to check the lines o f co de surro unding the flagged o nes as well. Fix the pro blem in he llo .cpp by remo ving the misplaced int , then save yo ur wo rk. What Does It All Mean? Let's take a clo ser lo o k at the pro gram to see ho w it wo rks: OBSERVE: hello .cpp #include <iostream> int main() { std::cout << "Hello World!" << std::endl; return(0); } The first line is # include <io st re am >. This #include line tells C++ "I'm go ing to use yo ur standard streaming I/O package (io stream)." The co mpiler brings in the definitio ns o f the items fo r this package. The next line, int m ain(), is the start o f the co de fo r yo ur pro gram. The m ain() functio n is special in C++; it is the first functio n that C++ executes. We'll get into functio n definitio ns later—fo r no w, yo u just need to kno w that this special line starts the pro gram. The curly brace { indicates the start o f the bo dy o f the co de. Co de enclo sed in braces is called a block. In this pro gram, we have o ne blo ck o f statements and they make up the bo dy o f the m ain() functio n. In later lesso ns we'll learn ho w to use multiple blo cks o f co de. The next line co ntains st d::co ut << " He llo Wo rld!" << st d::e ndl;, which is a C++ executable statement. It tells C++ to print a message. Yo u'll no tice that the line starts with fo ur spaces. C++ do esn't care ho w many spaces yo u use to start a line, but go o d pro gramming style dictates that yo u use o ne level o f indentatio n fo r each level o f lo gic. Here we indented fo ur spaces fo r each set o f braces we have nested. We cho se to indent fo ur spaces as a standard because it's easy to read and we needed a standard fo r this co urse. Let's break the st d::co ut statement do wn into co mpo nents. The first item, st d::co ut , is the name o f a predefined variable that is used by C++ to write to the standard o utput (the co nso le). (In the Eclipse pro gramming enviro nment, co nso le o utput sho ws up in a windo w at the bo tto m o f the screen.) The st d::co ut variable is o ne o f the items bro ught in by the # include <io st re am > statement. The o perato r << tells C++ to take what fo llo ws it and send it so mewhere else, in this case to the o utput (st d::co ut ). Next in o ur co de, we have the string " He llo Wo rld" . This is a literal string co ntaining the characters we want to display o n the co nso le. This is fo llo wed by << again (which sends whatever fo llo ws it to the o utput stream o n the left) and the symbo l st d::e ndl. The st d::e ndl symbo l tells C++ to o utput an end-o f-line character. The statement ends with a semico lo n. Next, we have the return line re t urn(0 );, which tells C++ to end the pro gram and return a status o f 0 to the o perating system. (Yo u'll learn mo re abo ut the return statement later, but fo r no w all yo u need to kno w is that inside main, it ends the pro gram.) A return co de o f 0 indicates a no rmal exit. Co des 1-255 typically indicate that the pro gram exited abno rmally—the bigger the number, the bigger the pro blem. Again, the statement ends with a semico lo n. At the very end we have a clo sing brace } . This ends the blo ck o f co de that started at the brace just after the m ain() line. Adding to Our Program No w let's say we want to o utput ano ther line o f text. To do that, we can add ano ther line to o utput an additio nal message. Edit yo ur pro gram as sho wn (using yo ur o wn name instead o f "Steve"): CODE TO TYPE: /* #include <iostream> int main() { std::cout << "Hello World!" << std::endl; std::cout << "My name is Steve!" << std::endl; return(0); } Save yo ur file, then run it by right-clicking in he llo .cpp in the edito r windo w and cho o sing Run as | Lo cal C++ Applicat io n (alternatively yo u co uld click the Run ico n in the to o lbar). Yo u'll see this o utput: OBSERVE: Hello World! My name is Steve! Our o utput appears o n two lines because we used st d::e ndl. Ano ther way to make the o utput appear o n two lines is to use the special escaped character \n. Mo dify he llo .cpp as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "Hello World!" << "\n"; std::cout << "My name is Steve!" << "\n"; return(0); } Save yo ur pro gram, and run it. The o utput lo o ks identical to the last run: OBSERVE: Hello World! My name is Steve! \n is called an escape character. The backslash (\) "escapes" fro m the regular interpretatio n o f keybo ard characters to begin a special multi-character sequence, indicating a special character. In this case, it's a "newline," o r end o f line, the equivalent o f pressing the Enter key. Fo r mo re info rmatio n, see the glo ssary's descriptio n o f the escape character. But the escape character is the o ld-fashio ned way to print a newline. The mo re mo dern practice is to use the special symbo l st d::e ndl. There is a subtle difference between \n and st d::e ndl; the st d::e ndl symbo l causes a buffer flush, which makes sure the o utput appears immediately. The \n is no t required to flush the buffer (altho ugh o n mo st systems it do es). We co ver buffering and flushing in mo re detail in later C++ co urses. What Goes On Under the Hood Eclipse is a type o f to o l called an IDE o r Integrated Development Environment. This so rt o f to o l is a wrapper aro und many o ther to o ls. The idea o f the IDE is to hide the o ther to o ls and give yo u a single system in which to wo rk. But as a pro fessio nal, yo u'll need to kno w what go es o n "under the ho o d" to make the mo st effective use o f all the to o ls available. When yo ur pro ject is built, Eclipse figures o ut what needs to be do ne to make yo ur pro grams executable, auto matically. This co mes in handy fo r many types o f pro grams, including o ur small "hello wo rld" pro ject. To o ls like Visual Studio wo rk much the same way. So me pro grams use o ther builder to o ls to make them auto matically executable—in the C/C++ wo rld, a pro gram called make is a co mmo n to o l fo r that. In java, Ant is a po pular to o l fo r that task. Bo th o f tho se to o ls require pro grammers to specify a set o f "rules" o r "targets" that describe ho w a pro gram will be built. To co nvert yo ur co de into co mputer instructio ns, Eclipse uses the GNU g++ co mpiler. This pro gram takes yo ur so urce co de (.cpp file) and turns it into an executable. To do this, it needs to run a series o f pro grams. The first is the actual C++ co mpiler. Its jo b is to take the human-readable so urce co de and turn it into an o bject file (.o file). Yo u can see the o bject file created by the co mpiler. Switch to the Package Explo rer tab, then expand the De bug fo lder. Inside that fo lder yo u'll see he llo .o (amo ng o ther things). If yo u try to o pen he llo .o , yo u wo n't find anything useful— this file co ntains co mputer co de. The o bject file is readable by the co mputer, but no t by humans. The o bject file co ntains only the co de fo r executing the task that yo u wro te. In the case o f hello _wo rld, that co de uses st d::co ut to write o ut a message. The definitio n o f st d::co ut is no t in yo ur o bject file; instead it is part o f a standard library. This library co ntains generally useful definitio ns like std::co ut and lo ts o f o ther things. The library itself is just a bunch o f o bject files packaged to gether into o ne file (so mething like a zip file, but different). The linker takes yo ur o bject file and the o bject files in the library and pro duces an executable pro gram. Here's a graphical representatio n o f what it do es: With so me co mpilers, yo u may no t see o bject files, because they delete o bject files after the link step. With the GNU co mpiler, the co mpilatio n pro cess is actually acco mplished by multiple pro grams. The first thing g++ do es to yo ur pro gram is pass it thro ugh a pro gram called the pre-pro cesso r. This pro gram takes care o f things like the # include directive. (We co ver lo ts mo re abo ut this pro gram in the next C++ co urse.) The next stage turns the high-level C++ co de into lo w-level assembly co de. In high-level co de, o ne statement can result in many machine instructio ns being created to pro cess that statement. In assembly language, there's o ne statement per instructio n. Also , high-level languages are machine-independent (o r they are suppo sed to be.) Assembly co de is machine-dependent. In o ther wo rds, the assembly language fo r an Intel x8 6 -co mpatible pro cesso r (such as the Intel Co re 2 Duo o r Intel Pentium) is entirely different fro m the assembly co de fo r the iPho ne's ARM pro cesso r. Fo rtunately, all this co mplexity is hidden fro m yo u and yo u can igno re it mo st o f the time. But so metimes yo u may need to take a peek under the ho o d to deal with any bugs yo u enco unter alo ng the way. Finishing the Program Our pro gram, altho ugh syntactically and lo gically co rrect, is no t co mplete because it only contains the default comments produced by Eclipse. A co mment is text in the pro gram that tells peo ple reading the pro gram what's go ing o n. Co mments are no t read by the co mputer and altho ugh it is po ssible to write a pro gram with no co mments in it, we will no t do so in this co urse. Pro fessio nal pro gramming means creating pro fessio nal-quality pro grams with co mments— even if that pro gram is "Hello Wo rld." All o f yo ur pro grams sho uld begin with a co mment blo ck that co ntains these sectio ns: The lesso n and pro ject number (so the instructo r kno ws which questio n yo u're answering). A descriptio n sectio n that describes what the pro gram is suppo sed to do . A usage sectio n. Co mments begin with /* and end with */. Co mments can also begin with // and go to the end o f the line. Our pro gram needs a set o f co mments. Mo dify he llo .cpp as sho wn: CODE TO TYPE: /* * Lesson 1, Example 1 (Or Assignment 1 for programs you turn in) * * Description: The classic "Hello World" program. Prints * out the message and that's all. * * Usage: Run it and get the message. */ // This is another way to comment a single line. #include <iostream> int main() { std::cout << "Hello World!" << std::endl; return(0); } Save and run it to verify that it still wo rks as expected. T he User Manual Are we finished? No t yet—a pro gram isn't any go o d if no o ne kno ws ho w to use it, so we'll write a user manual fo r every pro gram. Yo u may wo nder ho w to go abo ut writing a manual fo r such a sho rt pro gram. Fo r a sho rt pro gram, we just write a sho rt manual. To create yo ur manual, select the hello _wo rld pro ject and then select File | Ne w | Ot he r. In the New File Wizard, select Ge ne ral | File . Name yo ur file manual.txt. No w write the manual: CODE TO TYPE: Run the program. See the message. T he T est Plan Finally, the pro gram needs a test plan. Our test plan sho uld have these attributes: It sho uld test as much o f the pro gram as is feasible. It must list a precise set o f steps to fo llo w (ambiguo us instructio ns lead to results that canno t be repro duced). Its results must be o bservable. It must lead to a clearly o bservable pass/fail result. Fo r example, a test plan that says, "Play aro und with the so ftware and see if yo u can break it," is a vague and therefo re pretty bad test plan. First, the term "Play aro und" is no t precise. Different peo ple co uld "play aro und" in different ways. Seco nd, what happens if so meo ne breaks the so ftware? Can he do it again? Often, the answer to this questio n is no . Third, the term "break" is no t defined. If the system crashes, that certainly is a break. But what if it merely draws so mething that lo o ks o dd? Is that "o dd" drawing a feature o r a bug? No w we'll write o ur clear, brief, and excellent test plan. Create a file called test.txt, then type in the co de as sho wn: CODE TO TYPE: 1. Run the program. 2. Observe the message "Hello World!" (Yes -- Pass, No -- Fail) A Few More Notes We reco mmend that yo u use the Save All menu o ptio n to save yo ur wo rk; this will save everything yo u have o pened, and it can prevent pro blems when running yo ur pro grams while yo u're wo rking o n them. Do not put spaces o r o ther special characters in file names. Limit yo urself to a co mbinatio n o f letters, digits, undersco res (_), and dashes (-) This helps to avo id pro blems with the to o l set being used. When yo u create a new so urce file, it always co ntains the standard header, including the file name, date, and yo ur name. Yo u sho uld replace tho se elements with mo re detailed and specific info rmatio n abo ut yo ur pro gram. Remember, when using the O'Reilly sandbo x system, that Red Leaf ico n is yo ur emergency butto n. It will resto re yo ur screen to the o riginal layo ut: Co ngratulatio ns! Yo u have created yo ur first C++ pro gram and co mpleted lesso n 1 o f the co urse! In the next lesso n, we'll investigate expressio ns. See yo u there! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Expressions C++ 1: Introduction to C++ Lesson 2 Glad to see yo u're back! In this lesso n we'll learn to use mathematical expressio ns in C++. Mathematical Expressions C++ understands these o peratio ns: + Additio n - Subtractio n * Multiplicatio n / Divisio n % Mo dulus (remainder after divisio n) We can co mbine these o peratio ns with numbers into an expressio n to do useful lo ts o f really useful wo rk. Let's get go ing and try an example to see ho w these o perato rs wo rk. Start a new pro ject and name it e xpe xpre ssio n. Assign it to the C++1_Le sso ns wo rking set. Then create a new so urce file in the new e xp-e xpre ssio n pro ject and name it e xp-e xpre ssio n.cpp. No w create the pro ject and so urce file. Yo u can see a graphical representatio n o f this pro cedure in the next sectio n. But if yo u feel co mfo rtable with the pro cess so far, go ahead and skip to the fo llo wing sectio n. Creating the Project and File Select File | Ne w | C++ Pro je ct , enter the info rmatio n, and click Finish, as sho wn: If yo u are pro mpted to change the perspective, check the Re m e m be r m y de cisio n bo x and click No : Assign the C++1_Le sso ns wo rking set to the e xp-e xpre ssio n pro ject; right-click the pro ject, select Assign Wo rking Se t s..., and assign the wo rking set as sho wn: In the Package Explo rer, right-click the e xp-e xpre ssio n pro ject, select Pro pe rt ie s, and set the Build pro perties as sho wn: No w, in the e xp-e xpre ssio n pro ject, select File | Ne w | So urce File , and enter info rmatio n as sho wn: Editing and Running Your Program Open yo ur e xp-e xpre ssio n.cpp file and enter the fo llo wing co de (we'll o mit the auto matic co mments fro m no w o n to save space): CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is " << (1 + 2) * 4 << std::endl; return (0); } Save yo ur so urce file, then in the edito r windo w fo r e xp-e xpre ssio n.cpp, right-click and select Run as | Lo cal C++ Applicat io n (o r select e xp-e xpre ssio n.cpp in the Package Explo rer and click the the to o lbar). Yo u'll see this o utput: ico n in OBSERVE: The answer is 12 The co mputer evaluated, o r calculated, the answer to the expressio n (1 + 2) * 4 (which is 12) and sho wed yo u the results. So , ho w did the parentheses affect the answer? I'm glad yo u asked! Let's remo ve them and see what happens—edit yo ur co de as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is " << (1 + 2) * 4 << std::endl; return (0); } Save and run yo ur pro gram. This time the answer is different: OBSERVE: The answer is 9 The co mputer reads the expressio n 1 + 2 * 4 fro m left to right, but it also fo llo ws the Order o f Operatio ns: 1. expo nents and ro o ts 2. multiplicatio n and divisio n 3. additio n and subtractio n Multiplicatio n o ccurs befo re additio n, so the co mputer actually do es this: 2*4=8 1+8 =9 Yo u can change the Order o f Operatio ns by using parentheses ( ). In the first example, we used parentheses to fo rce additio n to o ccur befo re multiplicatio n. T ypes of Numbers There are two majo r types o f numbers in C++: integers and floating point. (Yo u might also hear abo ut a complex type, but that type isn't actually built into the language.) Integers, also kno wn as whole numbers have no fractio nal value. Fo r example, these are all integers: OBSERVE: 1 324290 42 -999 37 Flo ating-po int numbers co ntain a fractio nal part. Fo r example: OBSERVE: 1.2 3.5 14.8 37.0 The last number presents a key co ncept: 37 .0 is a flo ating-po int number. Even tho ugh the fractio nal part is 0 , its presence after the decimal po int makes 37 .0 a flo ating-po int number. The number 37 is an integer. Note When writing flo ating-po int numbers, always include a decimal po int. It tells anyo ne reading yo ur co de that yo u intend the value to be flo ating po int. So 1.0 is go o d, and 1 is bad. 0 .0 is go o d; 0 is bad. Flo ating-po int numbers can also co ntain an o ptio nal expo nent. Fo r example: OBSERVE: 13.33E+5 This tells C++ that the value o f the number is 13.33 x 10 5 . Floating-Point vs. Integer Division Edit e xp-e xpre ssio n.cpp to co mpute (and print) the value o f the expressio n 1/3 as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is " << 1 / 3 << std::endl; return (0); } Save and run it, then read the o utput: OBSERVE: The answer is 0 When C++ do es integer divisio n, the result is an integer—it truncates any fractio nal part o f the result. No w, edit e xp-e xpre ssio n.cpp again, as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is " << 1.0 / 3.0 << std::endl; return (0); } Save and run it and lo o k o ver the o utput: OBSERVE: The answer is 0.333333 When C++ sees that the arguments are flo ating-po int numbers, it perfo rms flo ating-po int divisio n and gives flo ating-po int results. But what if o ne number is flo ating po int and the o ther is an integer? Let's give that a try. Mo dify e xpe xpre ssio n.cpp as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is " << 1.0 / 3 << std::endl; return (0); } Save and run it and read o ver yo ur results. Try 1 / 3.0 as well. No w that yo u've seen ho w mixed-mo de arithmetic will affect yo ur pro grams, avo id using it if at all po ssible. Fo r no w, that may be difficult, but later we'll learn abo ut casing, which will let us explicitly tell the co mpiler which types o f numbers (and therefo re o peratio ns) to use. Dividing by Zero We canno t divide anything by zero —that o peratio n isn't defined and the expressio n has no meaning. So what happens if we tell the co mputer to divide by zero ? Mo dify yo ur pro gram to co mpute a new expressio n that divides by zero as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "Divide " << (1/0) << std::endl; return (0); } Save yo ur pro gram, and igno re the warning message. message: Run it and o bserve that it terminates with this The co mputer can't handle this type o f math, so the pro gram sto ps with a warning. Click OK to end the pro gram. But what happens when yo u divide by zero with a flo ating-po int number? Try it and find o ut; edit yo ur pro gram belo w as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "Divide " << (1.0/0) << std::endl; return (0); } Save and run it. Yo u'll see o utput like: OBSERVE: Divide inf The flo ating-po int fo rmat used by basic Intel-co mpatible pro cesso rs has special "numbers" defined fo r erro r co nditio ns such as inf , -inf , and NaN (no t a number). This is pro cesso r-dependent and altho ugh almo st all mo dern pro cesso rs no w use this standard fo rmat, so me do n't. Results o n tho se co mputers co uld be different. So no w yo u may be wo ndering why integer divisio n by zero crashes yo ur pro gram, while flo ating po int divisio n by zero do es no t. This is by design—Intel-co mpatible pro cesso rs have been used fo r decades, and at first co uld o nly perfo rm integer arithmetic. Flo ating-po int arithmetic was handled separately, and thus it co ntinues to generate different erro rs. Instead o f wo rrying abo ut the differences in erro r handling, it is better no t to generate the erro r in the first place. In future lesso ns we'll learn ho w to make sure o ur pro grams wo rk co rrectly. Stay tuned! Limits on Numbers Suppo se yo u have an o ld eight-digit calculato r. Yo u type in the number 9 9 ,9 9 9 ,9 9 9 and then add 1 to it. The result is a nine-digit number, which the calculato r can't display. So the calculato r displays ERROR. There are similar limits to the numbers in C++. Unfo rtunately, these are no t hard limits. They can vary depending o n the pro cesso r type, co mpiler, and o perating system. C++ has a file (named climits) that defines the limits o n its basic types. We'll # include this file, and then add so me co de to use it. Edit yo ur e xp-e xpre ssio n.cpp pro gram as sho wn: CODE TO TYPE: #include <iostream> #include <climits> int main() { std::cout << "INT_MAX " << INT_MAX << std::endl; return (0); } Save and run it. Yo u'll see this: OBSERVE: INT_MAX 2147483647 Note This example uses the C-style constant fo r the integer limit. The pure C++ way o f do ing this is to include the header file <limits>. Then yo u can get the maximum integer with the expressio n st d::num e ric_lim it s<int >::m ax(). We used the C metho d because it's sho rter. Also , to understand the expressio n st d::num e ric_lim it s<int >::m ax(), yo u need to understand classes, static member functio ns, templates and template specializatio n—all co ncepts we will co ver in a future co urse. Let's see what happens when we go past the limit. Change the pro gram as sho wn: CODE TO TYPE: #include <iostream> #include <climits> int main() { std::cout << "INT_MAX+1 " << INT_MAX+1 << std::endl; return (0); } Based o n the last executio n o f the pro gram, we might expect to see the number 214748 36 48 . Instead we see: Run it. OBSERVE: INT_MAX+1 -2147483648 This is called overflow. It o ccurs when a number beco mes to o big o r to o small to fit into its type (in this case, integer). C++ do es no t check fo r o verflo w and will no t warn yo u when it o ccurs. Yo u wo n't enco unter this pro blem to o o ften, but if yo u do , no w yo u'll be able to reco gnize and co rrect it. Okay, no w let's see what happens when we have a flo ating-po int o verflo w. Because o f the way flo ating-po int numbers are sto red and co mputed, it's hard to specify an exact maximum number. But the expressio n belo w will definitely give yo u an o verflo w, so go ahead and add it to yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> #include <climits> int main() { std::cout << "Float " << (9E399 * 9E399) << std::endl; return (0); } Run it. Yo u'll see the special flo ating-po int number inf ; the flo ating system gives yo u so me indicatio n that an o verflo w o ccurred. Common Problems There are so me co mmo n warnings and erro rs that yo u may enco unter when wo rking with C++. We'll experiment with so me o f them by making a few mistakes o n purpo se. Change yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> #include <climits> int main() { std::cout << "The answer is" << (1 + 2) * 4; return (0); } C++ flags this line with an erro r message because it do esn't reco gnize st d::co ut . The st d::co ut functio nality is defined in io st re am , so in o rder to use st d::co ut , we have to include io st re am in o ur pro gram. Edit the pro gram as sho wn: CODE TO TYPE: #include <iostream> #include <climits> int main() { (1 + 2) * 4; return (0); } When yo u co mpile the pro gram, yo u'll no tice a warning triangle next to the line that co ntains the expressio n. Lo o k in the Co nso le panel to see the text asso ciated with the warning: The warning reminds us that o ur expressio n do esn't really do anything—we do no t o utput its results o r save them anywhere. Save and run it. The o utput windo w co ntains abso lutely no thing. In particular, it do es no t co ntain the result o f the calculatio n. The line (1 + 2) * 4 tells C++ to co mpute the value o f the expressio n, but no thing mo re. It do esn't sto re the result anywhere, do esn't make a decisio n based o n the result, and do esn't o utput it. C++ just co mputes the answer and then thro ws it away. This is perfectly legal, but pretty strange—so strange that the co mpiler issues a warning when yo u build it. That's why yo u go t the "no effect" warning. Let's fix the pro gram by editing it as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is" << (1 + 2) * 4; return (0); } Save and run it. Yo u'll see this: OBSERVE: The answer is12 Do yo u see a pro blem in this co de? That's right—we need a space between "is" and the answer. Add the space as sho wn (we use an undersco re here to represent the space): CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is_" << (1 + 2) * 4; return (0); } Save and run it. Hmm. There's still a pro blem. See if yo u can spo t it. We'll add ano ther o utput statement (as sho wn in blue belo w) to help illuminate the pro blem: CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is " << (1 + 2) * 4; std::cout << "The answer still is " << (1 + 2) * 4; return (0); } Save and run it. The o utput lo o ks like this: OBSERVE: The answer is 12The answer still is 12 Any additio nal o utput statements will be appended to the end o f this o ne. Yo u need to add a newline at the end o f the o utput line. Edit the pro gram as sho wn: CODE TO TYPE: #include <iostream> int main() { std::cout << "The answer is " << (1 + 2) * 4 << std::endl; std::cout << "The answer still is " << (1 + 2) * 4 << std::endl; return (0); } Save and run it to make sure that the pro blem has been co rrected. We co vered a lo t in this lesso n! We went o ver expressio ns, integers, and flo ating po int numbers. No w yo u're ready to tackle the next lesso n, where we'll discuss pro gram structure and variables. See yo u there! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Variables C++ 1: Introduction to C++ Lesson 3 Basic Programs We have to walk befo re we can run, so we're go ing to learn to pro gram fo r no w in a subset o f the C++ language. Our basic pro gram structure is: OBSERVE: /* File heading comments */ #include directives int main() { data declarations executable statements return (0); } Note In so me bo o ks and co de examples, the dat a de clarat io ns are placed befo re the int m ain line. In these lesso ns, they co me after it. At this stage, fo r the types o f pro grams we can currently write, either o rder will wo rk. (We'll learn the difference between the two types o f declaratio ns later.) It is easier to use Eclipse if yo u put the dat a de clarat io ns just after the first brace ({). The include dire ct ive s, dat a de clarat io ns, and e xe cut able st at e m e nt s sectio ns are o ptio nal, so the sho rtest po ssible C++ pro gram wo uld have all three sectio ns o mitted: OBSERVE: int main() { return(0); } Such a pro gram may appear to be useless, but it's actually a standard Linux/Unix co mmand, true. It's used in shell scripting as a co mmand that always returns a go o d status (0 ) to the currently running script. Variables A variable is a bit o f yo ur co mputer's memo ry, like a bo x, in which yo u can put a single item o f data. We must declare variables befo re we use them. In o rder to declare a variable, C++ needs two pieces o f info rmatio n: the name and the type (what the bo x is called, and what type o f bo x it is). In o rder to pass this co urse, yo u'll need to add a third piece o f info rmatio n: A co mment explaining what the variable is used fo r. A variable name begins with a letter (upper o r lo wer case) o r an undersco re (_), then co ntinues with any co mbinatio n o f letters, undersco res, o r digits. It canno t be the same as any C++ keywo rd. Fo r example, these are legal variable names: OBSERVE: box_width whatever point_count point3 These are no t legal variable names: today dataField OBSERVE: 3times // Begins with a digit box-top // Contains hyphen Variable names are usually lo wer case (size , f ull_size o r mo stly lo wer case (Size , FullSize , f ullSize . Co nstants are usually given upper-case-o nly names (PI, MAX_INT ). No thing in the language fo rces yo u to fo llo w this co nventio n, but if yo u cho o se to igno re it, do n't be surprised if a mo b o f angry maintenance pro grammers sho ws up o utside yo ur do o r with to rches and pitchfo rks. Style No te: There are two majo r ways o f co nstructing variable names. The first is separating wo rds with undersco res: OBSERVE: box_width point_count data_size The o ther is so mething called "CamelCase": OBSERVE: boxWidth pointCount dataSize In practice, there's no t a lo t o f difference in the readability o f the two styles, but there is a great benefit to picking one style and sticking to it. The style guide fo r this co urse requires yo u to use the undersco re style. Variable Definitions A variable definitio n co nsists o f three parts: OBSERVE: {type} {name}; // {Comment explaining the variable} The co m m e nt is not o ptio nal—at least no t in this co urse. The reaso n is that a pro gram is a set o f instructio ns to the co mputer that uses a unique (to that pro gram!) vo cabulary. I mean if yo u see a variable named ce nt e r_po int in co de, the first questio n yo u are go ing to ask yo urself is "Center o f what?" By co mmenting every variable declaratio n, yo u pro duce a mini-dictio nary describing every specialized wo rd (variable) yo u use in yo ur pro gram. It makes understanding the pro gram much easier. Variable T ypes: Integer The C++ keywo rd fo r the integer type is int (Glo ssary integer, int). A integer variable declaratio n lo o ks like this: OBSERVE: int x; // example variable The int declaratio n tells C++ to declare an integer variable using the o ptimal size o f an integer fo r the machine. On most machines, this allo ws numbers fro m 214748 36 47 to -214748 36 48 to be used. On so me o lder systems, this is just 3276 7 to -3276 8 and o n so me newer systems, it's −9 ,223,372,0 36 ,8 54,775,8 0 8 to +9 ,223,372,0 36 ,8 54,775,8 0 7. This is the difference between 32-bit, 16-bit, and 64-bit integers. Unless yo u are interested in the technical details regarding the physical sto rage o f integers within yo ur co mputer's pro cesso r, yo u do n't need to remember the difference between bit sizes and number ranges. Instead, remember there are different ways to sto re this data and remember to use the co nstants we saw earlier, such as INT _MAX. Think o f a variable as a bo x. Yo u can put a single integer in it and yo u can lo o k in it and see what's in it. Let's lo o k at this in actio n. Create a pro ject named assign-e xp in yo ur C++1_Le sso ns wo rking set, and a pro gram named assign-e xp.cpp that co ntains the fo llo wing co de: CODE TO TYPE: // Put in the regular heading comments #include <iostream> int main() { int play; // An integer to play around with play = 5; std::cout << "The value of play is " << play << std::endl; return(0); } Save and run it. This pro gram assigns the variable play a single value and then uses it in an o utput. Yo u'll see the results: OBSERVE: The value of play is 5 The pro gram sto res "5" in the variable named play and then displays that value to yo u. Variables can change values as pro grams execute, and play is no exceptio n. Let's see ho w the value o f play changes as the pro gram executes. Change yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> int main() { int play; // An integer to play around with std::cout << "At first, the value of play is " << play << std::endl; play = 5; std::cout << "The value of play is " << play << std::endl; play = -999; std::cout << "Finally, the value of play is " << play << std::endl; return(0); } Save and run it. Yo u sho uld see the fo llo wing o utput: OBSERVE: At first, the value of play is 0 The value of play is 5 Finally, the value of play is -999 If we stepped thro ugh the pro gram, we'd see the value o f play after each line is executed. We might see the fo llo wing: Line int play; value o f play undefined std::co ut << "At first, the value o f play is " << play << std::endl; undefined play = 5; 5 std::co ut << "The value o f play is " << play << std::endl; 5 play = -9 9 9 ; -9 9 9 std::co ut << "The value o f play is " << play << std::endl; -9 9 9 return(0 ); -9 9 9 BUT WAIT! This table sho ws that the initial value o f play is undefined, but the o utput sho ws that it was 0 ! Befo re we assign play a value fo r the first time—befo re the play = 5 line—its value is no t kno wn, and canno t be assumed to be anything. With this specific co mputer, co mpiler, and executio n, the value happened to be 0 . A different co mputer, co mpiler, o r executio n co uld pro duce any o ther result, such as 10 0 , 9 0 0 , o r -214748 36 48 ! The bo tto m line: don't assume your variable has a value before you give it a value! In C++, yo u can declare and initialize variables in o ne statement. Change assign-exp.cpp as sho wn: CODE TO TYPE: #include <iostream> int main() { int play = 2; // An integer to play around with std::cout << "At first, the value of play is " << play << std::endl; play = 5; std::cout << "The value of play is " << play << std::endl; play = -999; std::cout << "Finally, the value of play is " << play << std::endl; return(0); } Save and run it. Yo u sho uld see the fo llo wing o utput: OBSERVE: At first, the value of play is 2 The value of play is 5 Finally, the value of play is -999 Variable T ypes: Floating Point The int is just o ne o f C++'s built-in types. Ano ther majo r type is the flo ating-po int number. Here's an example o f a typical flo ating po int (f lo at ) declaratio n and use. Create a pro ject named f lo at -play, assign it to the C++1_Le sso ns wo rking set, and in it, create a f lo at -play.cpp pro gram as sho wn: CODE TO TYPE: #include <iostream> int main() { // Floating-point variable declaration... float area = 5.2 * 3.5; // Area of a rectangle std::cout << "The area is " << area << std::endl; return(0); } Save and run it. Yo u sho uld see the fo llo wing result: OBSERVE: The area is 18.2 Here we saved a step—we declared a variable named are a and assigned it the value o f the expressio n 5 .2 * 3.5 all in a single line o f co de. C++ do es the math—it evaluates the expressio n and assigns 18.2 to the are a variable. Variable T ypes: Characters The character (char) data type sto res a single character. To be mo re specific, it sto res a single character fro m the ASCII character set. This character set pro vides fo r the letters a-z (upper and lo wer case), the digits 0 -9 , a set o f punctuatio n characters, and special control characters. Glo ssary: ASCII Character Set. Co ntro l characters are no t printed, but instead co ntro l ho w the o utput appears o n the screen. Character co nstants are enclo sed in single quo tes: 'A', 'B', '?'. Create a char-play pro ject, assign it to the C++1_Le sso ns wo rking set, and in it, create char-play.cpp as sho wn: CODE TO TYPE: #include <iostream> int main() { char ch1; // First play character char ch2; // Second play character char ch3; // Third play character ch1 = 'A'; ch2 = 'B'; ch3 = 'C'; std::cout << "The characters are " << ch1 << ch2 << ch3 << std::endl; return(0); } Save and run it. Yo u sho uld see the fo llo wing: OBSERVE: The characters are ABC What happens if we try to sho ve mo re than o ne character into a variable? Try it! Change yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> int main() { char ch1; // First play character char ch2; // Second play character char ch3; // Third play character ch1 = 'A'; ch2 = 'B'; ch3 = 'CDEF'; std::cout << "The characters are " << ch1 << ch2 << ch3 << std::endl; return(0); } See the warning? This is the first indicatio n that so mething isn't quite co rrect. Try running the pro gram. Yo u'll see so mething like: OBSERVE: The characters are ABF Lo o ks like the co mputer wasn't happy with o ur 'CDEF' character, so it dro pped CDE witho ut telling us. Warnings exist fo r a reaso n—do n't igno re them! Escape Characters There is a special character, the backslash (\), which is used to specify characters that canno t be typed inside single quo tes easily, such as tab ('\t') and newline ('\n'). In these cases, the backslash "escapes" fro m no rmal rendering o f t and n, allo wing yo u to represent tabs and newlines in pro gram o utput. So me o f the escape characters are: \b Backspace Mo ve the curso r to the left o ne character. \f Fo rm feed Go to to p o f a new page. \n New line Go to the next line. \r Return Go to the beginning o f the current line. \t Tab Advance to the next tab sto p (eight-co lumn bo undary). \' Apo stro phe o r single quo tatio n mark The character ' . \" Do uble quo te The character ". \\ Backslash The character \. \nnn some character The character number nnn (o ctal). \xNN some character The character number NN (hexadecimal). Edit the pro gram belo w, replacing the value we assign to ch2 as sho wn: CODE TO TYPE: #include <iostream> int main() { char ch1; // First play character char ch2; // Second play character char ch3; // Third play character ch1 = 'A'; ch2 = '\n'; ch3 = 'C'; std::cout << "The characters are " << ch1 << ch2 << ch3 << std::endl; return(0); } Save and run it and o bserve the o utput: OBSERVE: The characters are A C No w let's try so mething a little different. Change the value o f ch2 to \b, the backspace, as sho wn belo w: CODE TO TYPE: #include <iostream> int main() { char ch1; // First play character char ch2; // Second play character char ch3; // Third play character ch1 = 'A'; ch2 = '\b'; ch3 = 'C'; std::cout << "The characters are " << ch1 << ch2 << ch3 << std::endl; return(0); } Save and run it and o bserve the o utput: OBSERVE: The characters are A☐C The display pro bably do esn't lo o k co rrect—depending o n ho w yo ur co mputer handles the backspace character, yo u might see anything fro m AC to A, so me funny character, and then C. Wide Characters The char type suffers fro m the fact that it canno t deal with internatio nal alphabets. To help so lve this pro blem, the wide character (wchar) type was created. While the char type defines 256 characters, wchar defines 6 5536 . Ho wever, there are languages (such as Chinese, Japanese, Farsi, Hebrew, and many o thers) that co ntain even mo re than 6 5536 characters. To display characters fro m tho se languages, a character enco ding system called Unicode was created. Suppo rt fo r wide and Unico de characters is dependent o n the co mpiler and o perating system that yo u are using. We'll discuss this in a future lesso n. Boolean The bo o lean type (bo o l) can have the value t rue (which is also o ne, o r 1) o r f alse (which is also zero , o r 0 ). Create a pro ject named play-bool, assign the C++1_Le sso ns wo rking set to it, and create the pro gram file playbo o l.cpp as sho wn: CODE TO TYPE: #include <iostream> int main() { bool flag; // Boolean to play around with flag = true; // Set it to true std::cout << "Flag is " << flag << std::endl; flag = false; // Set it to false std::cout << "Flag is " << flag << std::endl; flag = (1 == 1); // == is the test for equality operator (expression is true) std::cout << "Flag is " << flag << std::endl; return(0); } Save and run it. Yo u sho uld see the fo llo wing o utput: OBSERVE: Flag is 1 Flag is 0 Flag is 1 The co mputer printed the underlying values fo r flag as it was set to true, then false, then true. Originally, C did no t have a bo o lean type, so peo ple defined their o wn. As a result, yo u may see things like BOOL, BOOLEAN, Bo o l, T RUE, and FALSE in o lder bo o ks o r co de. Be aware that these are lo cal, no n-standard items. No w the questio n co mes up, "What sho uld I do abo ut legacy types in my co de?" The best answer is, if the co de wo rks, leave it alo ne. Yo u co uld waste a lo t o f time and effo rt trying to impro ve wo rking co de and bring it up to current standards, merely to make it do what it already do es. If yo u do have to go in and change so mething, and bringing the types up to date will not cause too much trouble, by all means do so . But do n't change anything just fo r the sake o f changing it. Mixing T ypes C++ is very flexible when it co mes to mixing types. If it can figure o ut a co nversio n, it will silently allo w yo u to assign a co nstant o f o ne type (such as bo o lean) to ano ther (such as integer). Here are the co nversio ns that o ccur when mixing types: Result type Expressio n Co nversio n type integer bo o lean 1 fo r true, 0 fo r false (no t guaranteed by the standard, but everyo ne I kno w o f implements it that way). flo at bo o lean Same as integer. char integer The character who se character number is the number being assigned. This depends o n the character set o n yo ur system. Fo r mo st systems, this is ASCII, so assigning ch = 6 5 makes ch an 'A' (ASCII character number 6 5). integer flo at Integer after truncatio n. No te: If the value o f the flo at is bigger than the maximum size the integer can handle, the integer will get the maximum value. integer char The numeric value o f the character in the current character set. flo at char The numeric value o f the character in the current character set. bo o lean Numeric If the number 0 (zero ), the bo o lean variable gets f alse . If no n-zero , the value t rue is assigned. Let's try this. Change yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> int main() { bool flag; // Boolean to play around with flag = true; // Set it to true float test = flag; // will this work? flag = false; std::cout << "Flag is " << flag << std::endl; std::cout << "Test is " << test << std::endl; return(0); } Save and run it. Yo ur pro gram happily sto res the bo o lean value 1 fro m f lag into t e st . Also no te that, even when the value o f f lag changes to false (0 ), t e st retains the value o riginally assigned to it: OBSERVE: Flag is 0 Test is 1 We learned a lo t abo ut variables and types in this lesso n! In the next lesso n, we'll learn ho w to sto re many values o f the same data type using arrays. See yo u then! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Arrays and For Loops C++ 1: Introduction to C++ Lesson 4 Using Arrays So far, we've o nly learned basic data types and every datum had a name. But suppo se we want to calculate the average grade fo r twenty students in a class. It's a lo t o f wo rk to define twenty different variables, o ne fo r each number: OBSERVE: int student1; int student2; int student3; // I'm not going ... int student20; // // // to A number we are going to average A number we are going to average A number we are going to average write out the whole thing. // A number we are going to average Arrays allo w us to define a set o f data—like a gro up o f mailbo xes at an apartment building. Co mpare this to a regular variable (o ne that isn't an array)—it is like a mailbo x o utside o f a single ho use. A regular (no n-array) variable is just a single part o f yo ur co mputer's memo ry, but an array is a chunk o f co ntinuo us memo ry lo catio ns. Here is ho w we'd declare an array to sto re the same set o f numbers: OBSERVE: int students[20]; // The numbers we are going to average The elements o f the array are st ude nt s[0 ] thro ugh st ude nt s[19 ]. Yo u might expect them to be 1 thro ugh 20 , but in C++, array element numbering starts at 0 . The numbers—0 , 1, o r 19 —are indexes to the array. T he const Modifier Our class might always have twenty students in it, but what if it changes, say, to 35? We wo uld have to go thro ugh o ur pro gram, find all o f the 20 values relating to o ur st ude nt s array, and change them manually to 35 . This pro cess is erro r-pro ne—after all, there may be o ccurrences o f 20 unrelated to the number o f students, that we do n't want to change! Go o d pro gramming practice dictates that we specify the size o f o ur class in o ne place, as a variable, and then use that variable rather than the literal number in o ur pro gram. Since o ur class size do esn't change very o ften, we can tell C++ that the variable is a constant. The co nst mo difier defines a "variable" (actually a co nstant) who se value canno t be changed by the pro gram when it's running. C/C++ style co nventio ns call fo r the names o f co nstants to be all upper case; fo r example, co nst int CLASS_SIZ E = 35 . Ho w do co nstants wo rk? Let's find o ut! Start a new pro ject named co nst ant s, assign it to the C++1_Le sso ns wo rking set, and in it, create a new so urce file named co nst ant s.cpp as sho wn: CODE TO TYPE: #include <iostream> int main() { const int CLASS_SIZE = 20; std::cout << "I have " << CLASS_SIZE << " students in my class." << std::end l; return(0); } Save and run it. If yo u typed everything co rrectly yo u will see the fo llo wing: OBSERVE: I have 20 students in my class. What happens if the pro gram tries to change the value o f CLASS_SIZ E? Try it: CODE TO TYPE: #include <iostream> int main() { const int CLASS_SIZE = 20; std::cout << "I have " << CLASS_SIZE << " students in my class." << std::end l; CLASS_SIZE = 35; std::cout << "Now I have "<< CLASS_SIZE << " students in my class." << std:: endl; return(0); } Save yo ur co de. This time yo ur pro gram wo n't co mpile, because yo u are trying to change a co nstant. If yo ur number is go ing to change in the middle o f a pro gram run like this, it sho uldn't be defined as a co nstant. To fix this pro blem, yo u'd need to remo ve the wo rd co nst fro m the variable declaratio n and change the variable name to an appro priate style, fo r example, class-size . Yo u sho uld use named co nstants to specify the dimensio ns o f arrays; fo r example, int st ude nt s[CLASS_SIZ E]. Go o d pro gramming style dictates that yo u sho uld always use named co nstants in this way. In o ther wo rds, the dimensio n specificatio n o f an array sho uld never be just a number like 20 . Our first array No w let's lo o k at arrays in actio n. Create a new pro ject named ave rage , assign it to the C++1_Le sso ns wo rking set, and in it, create ave rage .cpp as sho wn: CODE TO TYPE: #include <iostream> int main() { const int CLASS_SIZE = 5; float average = 0.0; // average of the items float total = 0.0; // the total of the data items float students[CLASS_SIZE]; // data to average and total students[0] students[1] students[2] students[3] students[4] = = = = = 34.0; 27.0; 46.5; 82.0; 22.0; total = students[0] + students[1] + students[2] + students[3] + students[4]; average = total / CLASS_SIZE; std::cout << "Total " << total << " Average " << average << std::endl; return (0); } Save and run it. Yo u sho uld see the fo llo wing result: OBSERVE: Total 211.5 Average 42.3 Remember ho w we co uld declare a variable and set its value at the same time? Yo u can also do that fo r arrays, using {braces}. Change yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> int main() { const int CLASS_SIZE = 5; float float float erage and average = 0.0; // average of the items total = 0.0; // the total of the data items students[CLASS_SIZE] = { 34.0, 27.0, 46.5, 82.0, 22 }; total students[0] students[1] students[2] students[3] students[4] = = = = = // data to av 34.0; 27.0; 46.5; 82.0; 22.0; total = students[0] + students[1] + students[2] + students[3] + students[4]; average = total / CLASS_SIZE; std::cout << "Total " << total << " Average " << average << std::endl; return (0); } Save and run it. Yo u sho uld see the same results as befo re. Our co de so far lo o ks go o d, but o ur to tal calculatio n is a bit unwieldy because we'll have to change the fo rmula each time we change the CLASS_SIZ E. Let's see ho w we can fix that! for loops We can have the co mputer calculate the to tal fo r us—after all, it kno ws ho w big CLASS_SIZE is! To do this, we can use a for loop—which executes a blo ck o f co de a specified number o f times. Change yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> int main() { const int CLASS_SIZE = 5; int x; float average = 0.0; // average of the items float total = 0.0; // the total of the data items float students[CLASS_SIZE] = { 34.0, 27.0, 46.5, 82.0, 22 }; nd total // data to average a total = students[0] + students[1] + students[2] + students[3] + students[4]; for (x = 0 ; x < CLASS_SIZE ; x = x + 1) { total = total + students[x]; } average = total / CLASS_SIZE; std::cout << "Total " << total << " Average " << average << std::endl; return (0); } Save and run it. Yo u sho uld see the same o utput as befo re: OBSERVE: Total 211.5 Average 42.3 So ... ho w do es the f o r lo o p wo rk? Take a lo o k at the co de: OBSERVE: for (x = 0 ; x < CLASS_SIZE ; x = x + 1) { total = total + students[x]; } In English, this lo o p might be written this way: "fo r x st art ing at ze ro , while x is le ss t han CLASS_SIZ E, x is incre m e nt e d by o ne after we add e ach st ude nt value t o t he t o t al. Since x starts at zero and o ur CLASS_SIZE is 5, the co de t o t al = t o t al + st ude nt s[x] will run five times—with x having the values 0 , 1, 2, 3, and 4. A fo r lo o p typically has these parts: OBSERVE: for (/* Initialization */ ; /* Test */ ; /* Increment */) { /* body of loop */ } In o ur lo o p: x = 0 is the init ializat io n co de . Arrays start at zero , so x must start at zero as well. x < CLASS_SIZ E is the t e st co de . Our array o nly has the number o f elements (5) specified by CLASS_SIZE, but the indexes start at 0 so the last index will be 4; therefo re, we want to sto p lo o ping befo re x is equal to CLASS_SIZE. x = x + 1 is the incre m e nt co de. x will increase by o ne after each iteratio n. t o t al = t o t al + st ude nt s[x] is the bo dy o f lo o p co de, which updates the to tal. To really see what the fo r lo o p is do ing, let's add so me co de to sho w the values o f x and t o t al inside the lo o p while it's running: CODE TO TYPE: #include <iostream> int main() { const int CLASS_SIZE = 5; int x; float average = 0.0; // average of the items float total = 0.0; // the total of the data items float students[CLASS_SIZE] = { 34.0, 27.0, 46.5, 82.0, 22 }; nd total // data to average a for (x = 0 ; x < CLASS_SIZE ; x = x + 1) { total = total + students[x]; std::cout << "Students[x = " << x << "]: " << students[x] << "; total: " tal << std::endl; } << to average = total / CLASS_SIZE; std::cout << "Total " << total << " Average " << average << std::endl; return (0); } Save and run it and o bserve the o utput: OBSERVE: Students[x = 0]: 34; total: 34 Students[x = 1]: 27; total: 61 Students[x = 2]: 46.5; total: 107.5 Students[x = 3]: 82; total: 189.5 Students[x = 4]: 22; total: 211.5 Total 211.5 Average 42.3 A fo r lo o p can really make sho rt wo rk o f a big list! Suppo se o ur class size gro ws to ten. We can quickly update o ur pro gram to handle this, simply by updating CLASS_SIZ E and entering values fo r the additio nal students. Update yo ur pro gram as sho wn. Remember, arrays are zero -based, so we are adding students 5 thro ugh 9 . CODE TO TYPE: #include <iostream> int main() { const int CLASS_SIZE = 10; int x = 0; float average = 0.0; // average of the items float total = 0.0; // the total of the data items float students[CLASS_SIZE] = { 34.0, 27.0, 46.5, 82.0, 22, 72.3, 55.9, 91.2, 90.0, 43.8 }; ge and total // data to avera for (x = 0 ; x < CLASS_SIZE ; x = x + 1) { total = total + students[x]; std::cout << "Students[x = " << x << "]: " << students[x] << "; total: " tal << std::endl; } << to average = total / CLASS_SIZE; std::cout << "Total " << total << " Average " << average << std::endl; return (0); } Save and run it. See ho w we didn't have to change the rest o f the pro gram—it just wo rked! Yo ur o utput sho uld lo o k like this: OBSERVE: Students[x = 0]: 34; total: 34 Students[x = 1]: 27; total: 61 Students[x = 2]: 46.5; total: 107.5 Students[x = 3]: 82; total: 189.5 Students[x = 4]: 22; total: 211.5 Students[x = 5]: 72.3; total: 283.8 Students[x = 6]: 55.9; total: 339.7 Students[x = 7]: 91.2; total: 430.9 Students[x = 8]: 90; total: 520.9 Students[x = 9]: 43.8; total: 564.7 Total 564.7 Average 56.47 Array Safety C++ makes it easy to sto re a lo t o f info rmatio n in an array. What happens if yo u make a mistake—like accidentally lo o p o ver to o many array elements? Edit the pro gram as sho wn: CODE TO TYPE: //******************************************** //*** WARNING: In order to see what happens when we violate the rules, this program del iberately overflows an array. //******************************************** #include <iostream> int main() { const int CLASS_SIZE = 10; int x = 0; float average = 0.0; // average of the items float total = 0.0; // the total of the data items float students[CLASS_SIZE] = { 34.0, 27.0, 46.5, 82.0, 22 72,3, 55.9, 91.2, 90.0, 43.8 }; e and total // data to averag for (x = 0 ; x < 15 ; x = x + 1) // OOPS!! { total = total + students[x]; std::cout << "Students[x = " << x << "]: " << students[x] << "; total: " tal << std::endl; } << to average = total / CLASS_SIZE; std::cout << "Total " << total << " Average " << average << std::endl; return (0); } Save the file. No erro r o r warnings will be generated, because the co mputer assumes yo u kno w what yo u are do ing, and has no t checked to make sure yo u are staying within the bo unds o f the st ude nt s array. What happens when yo u try to run the pro gram? Run it to find o ut! Yo ur pro gram may run, and it may crash. If it runs, yo u might see o utput like this: OBSERVE: Students[x = 0]: 34; total: 34 Students[x = 1]: 27; total: 61 Students[x = 2]: 46.5; total: 107.5 Students[x = 3]: 82; total: 189.5 Students[x = 4]: 22; total: 211.5 Students[x = 5]: 72.3; total: 283.8 Students[x = 6]: 55.9; total: 339.7 Students[x = 7]: 91.2; total: 430.9 Students[x = 8]: 90; total: 520.9 Students[x = 9]: 43.8; total: 564.7 Students[x = 10]: 3.21401e-039; total: 564.7 Students[x = 11]: 5.95261e-039; total: 564.7 Students[x = 12]: 1129.4; total: 1129.4 Students[x = 13]: 0; total: 1129.4 Students[x = 14]: 1.96182e-044; total: 1129.4 Total 211.5 Average 21.15 See the junk added at the end? Yo ur specific o utput may lo o k different. C++ didn't check to make sure yo u were staying within the bo unds o f yo ur array, and happily went o n with the pro gram. It is like trying to get mail o ut o f 15 mailbo xes, when o nly 10 physical mailbo xes exist in yo ur apartment building. What happens if we try to write to an array lo catio n o utside o f CLASS_SIZE? Try it: Co de to Edit: average.cpp //******************************************** //*** WARNING: In order to see what happens when we violate the rules, this program del iberately overflows an array. //******************************************** #include <iostream> int main() { const int CLASS_SIZE = 10; int x = 0; float average = 0.0; // average of the items float total = 0.0; // the total of the data items float students[CLASS_SIZE] = { 34.0, 27.0, 46.5, 82.0, 22 72,3, 55.9, 91.2, 90.0, 43.8 }; e and total // data to averag students[500] = 500.0; for (x = 0 ; x < 15 ; x = x + 1) // OOPS!! { total = total + students[x]; std::cout << "x: " << x << " students[x]: " << students[x] << " total: " tal << std::endl; } << to average = total / CLASS_SIZE; std::cout << "Total " << total << " Average " << average << std::endl; return (0); } Save the file. Once again, no erro r o r warnings are generated, because the co mputer assumes yo u kno w what yo u are do ing and has no t checked to make sure yo u are staying within the bo unds o f the st ude nt s array. What happens when yo u try to run the pro gram? Run it to find o ut! Yo ur pro gram will crash, and give an erro r like this: C++ did no t check to make sure yo ur array index o f 50 0 was valid. Instead, that line executed, and crashed yo ur pro gram. In C++, when yo u try to access o r write so mething yo u are no t suppo sed to access, any o f these things might happen: yo ur pro gram co uld crash. yo ur co mputer co uld crash, depending o n the o perating system. yo ur pro gram co uld run and calculate things inco rrectly. yo ur pro gram co uld run no rmally, o nly to crash later (perhaps waiting until it's shipped to 10 ,0 0 0 custo mers, when it suddenly decides to wipe o ut all their impo rtant data!). If yo u remember the go o d o ld days o f co mputers and o perating systems—MS-DOS, Windo ws 9 5, and MacOS 7, to name a few—yo u pro bably remember bugs in applicatio ns that co uld crash the entire co mputer. Tho se bugs were o ften array pro blems just like this! In so me o ther languages, yo u might no t need to wo rry so much abo ut checking yo ur array indices. In C++, yo u do . In a future co urse, we will discuss ways to do uble-check yo ur pro grams to make sure yo u are accessing arrays co rrectly. Note In the real wo rld, almo st no o ne checks the array indices befo re using them to access an array. Instead, they run witho ut checking and spend millio ns o f do llars later to debug the strange and hard-to -find bugs caused by bad index values. CHECK YOUR CODE! We co vered a lo t in this lesso n! We learned ho w to use arrays, and ho w to lo o p o ver arrays using fo r lo o ps. In the next lesso n we'll learn abo ut ano ther type o f variable: strings. See yo u then! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. C++ Strings C++ 1: Introduction to C++ Lesson 5 Strings in C++ Strings are sequences o f characters yo u can use in a co mputer pro gram. There are two basic ways to use strings—the newer C++ style strings (which we will learn abo ut in this lesso n), and o lder "C-Style" strings that we will review in the next lesso n. To use C++ strings, we need to # include <st ring> at the to p o f o ur pro grams. We can then declare a string with a statement like: OBSERVE: std::string variableName; // comment Let's see ho w this wo rks. Create a pro ject named st ring, assign it to the C++1_Le sso ns wo rking set, create a so urce file named st ring.cpp, and enter the fo llo wing co de: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; std::string last; // First name // Last name first = "Joyce"; last = "Kilmer"; std::cout << "My name is " << first << " " << last << std::endl; return(0); } Replace we'll use Jo yce Kilmer in the examples, but yo u sho uld replace Joyce and Kilmer with any names yo u like. As yo u can see, string co nstants are enclo sed in do uble quo tes ("). Remember that character co nstants are enclo sed in single quo tes ('). It might help to remember that o ne tick (') is fo r a single character and multiple ticks (") fo r multiple characters (strings). Save and run the pro gram. Yo u'll see so mething like: OBSERVE: My name is Joyce Kilmer Excellent! So far, strings wo rk exactly like any o ther variable such as an int o r f lo at . We learned ho w to add two numbers in a previo us lesso n. Yo u can perfo rm a similar o peratio n o n strings—using the plus o perato r (+), yo u can concatenate two strings. To see ho w this wo rks, change yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; std::string last; std::string full; // First name // Last name // The full name first = "your first name"; last = "your last name"; full = first + " " + last; std::cout << "My name is " << full << std::endl; return(0); } Save and run it. Yo u'll see the same o utput: OBSERVE: My name is Joyce Kilmer In this pro gram, we co ncatenated the two variables f irst and last (with the space " " in between). What if we tried to co ncatenate " J o yce " , a space, and " Kilm e r" directly? Change yo ur pro gram as sho wn: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; std::string last; std::string full; // First name // Last name // The full name first = "Joyce"; last = "Kilmer"; full = "Joyce" + " " + "Kilmer"; std::cout << "My name is " << full << std::endl; return(0); } Oo ps! Lo o ks like C++ isn't happy with us. It gives the fo llo wing erro r: This is because o f the way the co ncatenate (+) o perato r is defined. There must be a st d::st ring o n at least o ne side o f the +. Change yo ur pro gram to fix this pro blem: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; std::string last; std::string full; // First name // Last name // The full name first = "Joyce"; last = "Kilmer"; full = first + " " + "Kilmer"; std::cout << "My name is " << full << std::endl; return(0); } Save and run it; yo u'll see the same results as befo re. Characters in strings Yo u can access any character in the string using the subscript ([]) o perato r. Change st ring.cpp as sho wn: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; // First name std::string last; // Last name std::string full; // The full name char first_initial; // The first initial first = "Joyce"; last = "Kilmer"; full = first + " " + last; first_initial = first[0]; // Assigns first_initial the value 'J'. std::cout << "My first initial is " << first_initial << std::endl; return(0); } Save and run it, and o bserve the o utput: OBSERVE: My first initial is J This [] syntax might remind yo u o f an array. This is because a string is just like an array o f characters! There is a pro blem here—the index is no t checked in this o peratio n. So if the index is o ut o f range, the expressio n returns an undefined value. In o ther wo rds, this o peratio n is no t safe—and yo u kno w ho w we feel abo ut safety! Fo rtunately, there is ano ther way o f getting the character, the at () functio n. Change the pro gram as sho wn: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; std::string last; std::string full; char first_initial; // // // // First name Last name The full name The first initial first = "Joyce"; last = "Kilmer"; full = first + " " + last; first_initial = first.at(0); // Assigns first_initial the value 'J'. This is the safe way of doing this. std::cout << "My first initial is " << first_initial << std::endl; return(0); } Save and run it. Yo u'll see the same o utput as befo re: OBSERVE: My first initial is J No w just fo r fun, change the line that gets the first initial to attempt to grab character 9 9 (an illegal index), as sho wn belo w: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; // First name std::string last; // Last name std::string full; // The full name char first_initial; // The first initial first = "Joyce"; last = "Kilmer"; full = first + " " + last; first_initial = first.at(99); // Assigns first_initial the value 'J'. This i s the safe way of doing this std::cout << "My first initial is " << first_initial << std::endl; return(0); } Save and run it. Yo u'll see the fo llo wing o n the co nso le: OBSERVE: This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. The pro gram can't access the 9 9 th character in the string, so it threw in the to wel. This isn't quite a crash, but it isn't a go o d way to end yo ur pro gram. Other Functions One o f the mo re co mmo n things to do with a string is to extract a substring; fo r example, so me substrings o f the full name " J o yce Kilm e r" are "Jo yce," "e Ki," and "Kilmer." C++ strings let yo u take substrings using the subst r functio n. Let's try it! CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; // First name std::string last; // Last name std::string full; // The full name char first_initial; // The first initial first = "Joyce"; last = "Kilmer"; full = first + " " + last; first_initial = first.at(99); // Assigns first_initial the value 'S'. This i s the safe way of doing this std::cout << "My substring is " << full.substr(4, 5) << std::endl; return(0); } Save and run it. Yo u will see the fo llo wing o utput: OBSERVE: My substring is e Kil Let's take a lo o k at the substr co de: OBSERVE: full.substr(4, 5) The 4 is the po sitio n o f the starting character fo r the substring—in this case, the 'e' in Jo yce. The 5 is the length o f the substring—in this example, the pro gram returns the characters 'e,' space, 'K,' 'i,' and 'l.' If yo u o mit the seco nd number, a different substring is returned. Try it: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; std::string last; std::string full; // First name // Last name // The full name first = "Joyce"; last = "Kilmer"; full = first + " " + last; std::cout << "My substring is " << full.substr(4, 5) << std::endl; return(0); } Save and run it. This time yo u will see: OBSERVE: My substring is e Kilmer C++ also has a functio n to tell yo u ho w many characters are in a string. It's called le ngt h()—let's try it: CODE TO TYPE: #include <iostream> #include <string> int main() { std::string first; std::string last; std::string full; // First name // Last name // The full name first = "Joyce"; last = "Kilmer"; full = first + " " + last; std::cout << "My name has " << full.length() << " characters in it." <<std:: endl; return(0); } Save and run it. Sure eno ugh, it co unts the characters, including spaces! OBSERVE: My name has 12 characters in it. In the next lesso n we will learn mo re abo ut strings and discuss C-Strings. See yo u then! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. C-Style Strings C++ 1: Introduction to C++ Lesson 6 What is a C-Style String? In the last lesso n we learned abo ut C++ strings. There is an additio nal, different type o f string—the C-style string. C-style strings are the primary string type o f the C language. Since C++ is a superset o f C, it to o has use C-style strings. In previo us lesso ns we examined characters and arrays—a C-style string is essentially an array o f characters with the special character null ('\0 ') at the end. Since C-style strings are arrays, they have a fixed maximum length. "Dynamic" strings are po ssible, but they require the pro grammer to manually manage memo ry—a pro cess that is full o f pitfalls and go tchas. Many security pro blems and bugs refer to buffer o verflo ws—which are typically erro rs with C-style strings that result in memo ry co rruptio n. There are many who believe that yo u sho uld never have a C-style string in a C++ pro gram. Unfo rtunately "sho uld" and the "real wo rld" are two quite different things. There is still a lo t o f legacy co de o ut there that uses C-style strings. As a pro grammer in the real wo rld, yo u will see this type o f string and have to deal with it. So let's start with an experimental C-style string pro gram. Create a pro ject named c-st ring, assign it to yo ur C++1_Le sso ns wo rking set, and create a pro gram c-st ring.cpp co ntaining the fo llo wing: Co de to Type: c-string.cpp #include <iostream> int main() { char name[] = {'S', 'a', 'm', '\0'}; // The name for this example std::cout << "The name is " << name << std::endl; return(0); } This assigns the value "Sam" to a C string nam e , which can be o utput to st d::co ut . Save and run it, and o bserve the o utput: OBSERVE: The name is Sam No w what wo uld happen if yo u didn't end the string with '\0 '? Let's see. Change yo ur pro gram as sho wn: Co de to Edit: c-string.cpp #include <iostream> int main() { char name[] = {'S', 'a', 'm', '\0'}; // The name for this example char other[] = {'J', 'o', 'e'}; // Another name with an error std::cout << "The name is " << name << " and other is " << other return(0); } Save and run it, and o bserve the o utput: OBSERVE: The name is Sam and other is Joew << std::endl; Yo ur actual o utput might differ fro m this example—in fact, it might even lo o k no rmal. This is ano ther situatio n where the behavio r is undefined. If yo u do no t put an end-o f-string marker (\0 ) in yo ur C-style string, it is anybo dy's guess what will o ccur. Remember when we accidentally used an array element we weren't suppo sed to use? What happened? Because there was no end-o f-string marker, C++ did no t sto p at the end o f o t he r. It co ntinued to write o ut characters fro m rando m memo ry until it actually fo und an end-o f-string character. C++ allo ws fo r even mo re co mpact initializatio n, using do uble quo tes ("). Let's use it to fix the erro r: Co de to Edit: c-string.cpp #include <iostream> int main() { char name[] = {'S', 'a', 'm', '\0'}; // The name for this example char other[] = "Joe"; // Another name with an error std::cout << "The name is " << name << " and other is " << other return(0); << std::endl; } This fo rm o f initializatio n creates an array four characters lo ng and assigns it fo ur character values, the fo urth and last being the end-o f-string character. Save and run it, and o bserve the o utput: OBSERVE: The name is Sam and other is Joe Yo u canno t assign a value to an existing C-style string. This is because a C string is an array and yo u canno t change its value like yo u can with o ther variables. Try it: Co de to Edit: c-string.cpp #include <iostream> int main() { char name[] = "Sam"; // The name for this example char other[] = "Joe"; // Another name with an error name = "Joe"; // Will this work? std::cout << "The name is " << name << " and other is " << other return(0); } When yo u save this file yo u will see an erro r: << std::endl; This erro r is generated because C strings require the pro grammer to wo rry abo ut memo ry and do extra wo rk when co pying them. Think o f the mailbo x analo gy fro m the array lesso n—here we created a mailbo x with three slo ts, co ntaining the values "S," "a," and "m." Using nam e = " J o e " ; is like buying a new mailbo x with three slo ts and trying to sho ve the new mailbo x with slo ts "J", "o " and "e" where the o ld mailbo x is still hanging. Instead o f trying to smash o ne mailbo x in place o f ano ther, we must manually o pen each slo t and co py the co ntents fro m the new to the o ld. This is do ne using the st rncpy() functio n (see the reference info rmatio n at cplusplus.co m). No te this reference uses an o ld header file (st ring.h) instead o f the current o ne (cst ring). This functio n has three parameters: strncpy() Syntax std::strncpy( destination , source , size ); de st inat io n is where the data is to be put, so urce is the so urce o f the data, and size is the maximum number o f characters to put in the destinatio n. Befo re we can use st rncpy, we need to get o ut o ur tape measure—an o perato r named size o f (). sizeo f() returns the size o f so mething in "char" units. If we use it o n a C-style string, it will return the maximum number o f characters that can be sto red in the string. This is very impo rtant because o ur strings (mailbo xes) are fixed in size. If we try to co py to o many characters fro m o ur new mailbo x to the o ld, bad things co uld happen. Co pying to o many characters is yet ano ther way to o verflo w the buffer and po ssibly cause the pro gram to crash. Let's see an example. Edit c-st ring.cpp as sho wn: Co de to Edit: c-string.cpp #include <cstring> #include <iostream> int main() { char name[4];// Short name std::cout << "Size is " << sizeof(name) << std::endl; std::strncpy(name, "Joe", sizeof(name)); std::cout << "Name is now " << name << std::endl; return (0); } Save and run it. Yo u'll see: OBSERVE: Size is 4 Name is now Joe Yo u might be wo ndering why yo u see Size is 4 —after all, J o e is o nly three letters lo ng! The fo urth character is the end o f string ('\0 ') null character. Remember: this character is required, so yo u must take it into acco unt. What happens when we try to co py a larger string into a smaller variable? Let's try it: Co de to Edit: c-string.cpp #include <cstring> #include <iostream> int main() { char name[4]; // Short name std::cout << "Size is " << sizeof(name) << std::endl; std::strncpy(name, "Joe", sizeof(name)); std::cout << "Name is now " << name << std::endl; std::strncpy(name, "Steve", sizeof(name)); std::cout << "Name is now " << name << std::endl; return (0); } Save and run it. This time, yo u'll see so mething like this: OBSERVE: Size is 4 Name is now Joe Name is now Stev a" The o utput fro m yo ur pro gram may be slightly different, see ho w "Steve" wasn't co pied co rrectly, and the o utput co ntains extra characters? We used the size o f o perato r to co mpute the maximum number o f characters that can be sto red in the variable nam e . This included the null character. "Steve" is six characters—"Steve" plus the end-o f-string character. If the so urce string has fewer characters than the size o f the array, then st d::st rncpy() co pies the string and adds an end-o f-string ('\0 ') to the end. But since the so urce is bigger here, it co pies size's number o f characters and do es no t append the end-o f-string. So in o rder to make things wo rk, we must do so o urselves: Co de to Edit: c-string.cpp #include <cstring> #include <iostream> int main() { char name[4]; // Short name std::cout << "Size is " << sizeof(name) << std::endl; std::strncpy(name, "Joe", sizeof(name)); std::cout << "Name is now " << name << std::endl; std::strncpy(name, "Steve", sizeof(name)); name[sizeof(name)-1] = '\0'; std::cout << "Name is now " << name << std::endl; return (0); } Since size o f (nam e ) is 4 in o ur example, size o f (nam e )-1 will be 3. Remember arrays (and C-style strings, which are arrays o f characters) are zero -based, so 3 is the last mailbo x in the nam e string. Save and run it. This time yo u'll see: OBSERVE: Size is 4 Name is now Joe Name is now Ste We o nly see the first three characters o f "Steve" because nam e is o nly big eno ugh to co ntain fo ur characters—"Ste" plus the null character. Believe it o r no t, changing the size o f C-style strings is no t as straightfo rward as yo u might expect. That to pic will be co vered in a future co urse. Concatenation of C-Style Strings In the last lesso n, we co vered the le ngt h() functio n fo r C++-style strings. The functio n st d::st rle n() returns the length o f a C-style string. In o ther wo rds, it returns the number o f characters actually in the string, as o ppo sed to size o f (), which returns the capacity. The functio n to perfo rm co ncatenatio n o f C-style strings is st d::st rncat (). Unlike co ncatenatio n o f C++ strings, co ncatenatio n o f C-style strings requires so me planning to make sure yo u do n't o verflo w any buffers. The functio n takes three parameters: OBSERVE: std::strncat( destination , source, size ); Yo u must carefully calculate size in o rder to make sure yo u do n't o verflo w the de st inat io n. The easiest way to do this is to always use the fo llo wing co de: Co ncatenatio n Design Pattern std::strncat( destination , source, sizeof(dest) - std::strlen(dest) - 1 ); destination[sizeof(destination)-1] = '\0'; The calculatio n fo r the size parameter fo r st d::st rncat () wo rks like this: Co de sizeo f(destinatio n) De script io n Start with the size o f the destinatio n string in characters. - std::strlen(destinatio n) Subtract the number o f characters already in the string. -1 Subtract o ne mo re fo r the end-o f-string ('\0 ') character. Let's try an example! Edit c-st ring.cpp as sho wn: Co de to Edit: c-string.cpp #include <cstring> #include <iostream> int main() { char name[25]; // Short name with plenty of space std::cout << "Size is " << sizeof(name) << std::endl; std::strncpy(name, "Joe", sizeof(name)); std::cout << "Name is now " << name << std::endl; std::strncat(name, " Smith", sizeof(name) - std::strlen(name) - 1); name[sizeof(name)-1] = '\0'; std::cout << "Name is now " << name << std::endl; return (0); } Save and run it, and o bserve the o utput: OBSERVE: Size is 25 Name is now Joe Name is now Joe Smith Success! Comparing Strings The C-style string co mpariso n functio n is st d::st rcm p(). It takes two parameters: OBSERVE: std::strcmp( string1, string2) It returns: 0 if the strings are equal A po sitive value if the first character that do es no t match has a greater value in string1 than in string2 A negative value if the first character that do es no t match has a greater value in string2 than in string1 Let's see ho w it wo rks. Create a co m pare -c pro ject and assign it to yo ur C++1_Le sso ns wo rking set. Then, create a pro gram named co m pare -c.cpp as sho wn: Co de to Type: co mpare-c.cpp #include <cstring> #include <iostream> int main() { char str1[] = "Steve"; char str2[] = "Steven"; int result = std::strcmp(str1, str2); std::cout << "Result is " << result << std::endl; return (0); } Save and run it, and o bserve the o utput: OBSERVE: Result is -1 Yo u might be asking yo urself why we can't use the == equality o perato r to check to see if two strings are the same. Let's try it to see ho w it might wo rk: Co de to Edit: co mpare-c.cpp #include <cstring> #include <iostream> int main() { char str1[] = "Steve"; char str2[] = "Steve"; if (str1 == str2) { std::cout << "Same!" << std::endl; } else { std::cout << "Not the same!" << std::endl; } return (0); } Save and run it, and o bserve the o utput: OBSERVE: Not the same! Why is this? The two strings o bvio usly have the same value. Using o ur mailbo x metapho r, the == equality o perato r checks to see if the two mailbo xes are the same (like if they have the same serial number)—it do esn't check their co ntents. This fails because the mailbo xes are no t the same. T ips Converting C++ Strings to C-Style Strings Yo u can co nvert fro m C-style strings to C++ style strings, and vice versa. To get a C-style string fro m a C++style string, use the c_st r() functio n. Yo u can assign a C-style string to a C++-style string. Try it: Co de to Edit: c-string.cpp #include <iostream> int main() { char name[] = "Sam"; char other[] = "Joe"; char c_style[4]; // The name for this example // Another name // New variable to hold C++ string std::string cpp_style; cpp_style = name; // Assigning to a C++-style string std::strncpy(c_style, cpp_style.c_str(), 4); // Copy C-string to a variabl e std::cout << "The name is " << name << " and other is " << other << std::en dl; std::cout << "cpp_style as a C-style string is " << c_style << std::endl; return(0); } In this example we: 1. Co pied a C-style string to a C++ style string, using direct assignment: cpp_style = name 2. Co pied a C++ string to a C-style string, using c_str() and std::strncpy Save and run it, and o bserve the o utput. To us, the results lo o k the same: OBSERVE: The name is Sam and other is Joe cpp_style as a C-style string is Sam Unsafe String Functions Many peo ple do n't use the string co py design pattern we pro vided, and thus buffer o verflo w pro blems o ccur in many pro grams. Instead, they use the functio n std::strcpy(). The standard fo rm o f this functio n is: Unsafe Use o f strcpy() // Unsafe. Do not use. std::strcpy(destination, source); Where de st inat io n is where the data will be co pied into and so urce is the string to co py. Parano id pro grammers will ask themselves "What happens if the so urce is bigger that the destinatio n?" The st rcpy() functio n do es no t check length and if the so urce is to o big, it will happily write rando m memo ry, co rrupting yo ur pro gram. T ip Parano ia, in pro grammers, is actually a good quality. In the style guide, we reco mmend that yo u not use the st rcpy() functio n. In the real wo rld, yo u might enco unter legacy co de co ntaining st rcpy()—a lo t o f co de still uses this functio n. So , what sho uld yo u do when yo u see it? Ideally, to make the pro gram safe, replace all st rcpy() functio ns with st rncpy(), but any time yo u change a pro gram there is risk—fo r example, yo u may no t make the change co rrectly. If the co de is wo rking, even if it is messy, the best thing to do is to leave it alone. Unless there is a bug in the pro gram that fo rces yo u to rewrite the co de, leave working code alone. There are two times yo u wo uld want to upgrade st rcpy() to the C-string st rncpy() design pattern. The first is if yo u are changing the co de anyway. (Always leave co de better than when yo u fo und it.) The seco nd is when yo u are trying to track do wn a memo ry co rruptio n bug—in this case, the change might fix the bug. Ano ther unsafe functio n is std::strcat(). It perfo rms much the same functio n as st d::st rcpy(), except that it do es co ncatenatio n instead o f co pying. std::strcat (unsafe) // Unsafe. Do not use. std::strcat(destination, source); This functio n adds the so urce string to the end o f the de st inat io n with no regard for the size of the destination. T he future of strcpy() and strcat() Peo ple have do ne all so rts o f things to get aro und the limitatio ns o f st rcpy() and st rcat () fo r years. Currently, the OpenBSD fo lks have devised new functio ns, st rlcpy() and st rlcat (), designed to o verco me the safety pro blems with st rcpy() and st rcat (), respectively. Ho wever, their effo rt has no t made it into the standard yet. Fo r mo re info rmatio n, see strlco py in Wikipedia. Comparisons to other types C Strings vs. Arrays of Characters C-style strings and arrays o f characters are two different things. An array o f characters is o f fixed length and co ntains no markers o r o ther special characters. In o ther wo rds, char nam e [5 0 ] co ntains 50 characters o f any type, no mo re o r less. Note In a character array, the null character ('\0 ') need no t be present; it's just ano ther character, with no special meaning. A C-style string is built o n the character array type. It states that yo u have an array o f characters, with an endo f-string marker ('\0 ') to end it. So , null ('\0 ') canno t be part o f the string. So all C-style strings are arrays o f characters, but all arrays o f characters are no t C-style strings. Let's try an example. Edit yo ur co m pare -c.cpp pro gram as sho wn: Co de to Edit: co mpare-c.cpp #include <cstring> #include <iostream> int main() { char state[2] = {'C','A'}; std::cout << "This probably looks funny: " << std::endl; std::cout << state << std::endl; std::cout << "This looks better: " << std::endl; std::cout << state[0] << state[1] << std::endl; return (0); } Yo u might lo o k at the state declaratio n and think it is an erro r, that it sho uld be char st at e [3] in o rder to reserve o ne character fo r the end o f string. But this is no t a mistake. st at e is not a C-style string; it's a character array. It ho lds two characters. No mo re, no less (there are no o ne-character state name abbreviatio ns). Save and run it, and o bserve the o utput. Generally, yo u'll see so mething like: OBSERVE: This probably looks funny: CA ÿ" This looks better: CA When yo u use st d::co ut << st at e <<, C++ will assumes that state is a C-style string (it's no t). It will then lo o k fo r the end-o f-string marker (there is no ne) and write the state abbreviatio n fo llo wed by so me rando m garbage. Yo u must write a character array o ne character at a time: Writing a Character Array std::cout << state[0] << state[1] << std::endl; T he bo t t o m line : Yo u can write o ut a C-style string using << but no t a character array. C-Style vs. C++ Style There are advantages and disadvantages to using each type o f string. Size C++ strings can sto re any length string auto matically. Yo u must explicitly declare the Size maximum size o f C-style strings. Memo ry The memo ry used by C-style strings is precisely co ntro lled. They do no t gro w o r shrink depending o n what data yo u put into them. C++ style strings manage their o wn memo ry. They can gro w and shrink. They can also use memo ry in surprising ways if yo u are no t careful. Almo st all o f the o peratio ns yo u can use o n C++ style strings are safe. Almo st all o f the Operatio ns o peratio ns yo u can use o n C-style strings can be dangero us. Yo u must be very careful abo ut safety so yo u do no t cause any buffer o verflo ws. Efficiency C-style strings are mo re efficient that C++ style strings. Ho wever, as a practical matter, mo st pro grams are no t CPU limited so efficiency makes little difference in a pro gram. Safety do es, and that's where C++ style strings win. OS Interactio n If yo u are interacting directly with an o perating system like Windo ws o r Linux, yo u will find that many o f the lo wer-level o perating system functio ns (raw re ad and o thers) use C-style strings as arguments. This means that if yo u pass data fro m o ne part o f the OS to ano ther, C-style strings are mo re efficient. Have yo u had eno ugh o f strings yet? In o ur next lesso n we'll finally mo ve o n fro m o utput to input, and we'll start learning ho w to make decisio ns in o ur pro grams. See yo u there! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Reading Data and if C++ 1: Introduction to C++ Lesson 7 Reading Strings In earlier lesso ns we used st d::co ut to o utput data to the co nso le. If we want to read data in fro m the co nso le, we can use—surprise!—st d::cin. Let's lo o k at a sho rt pro gram that demo nstrates the use o f st d::cin. Create a pro ject named re ading, assign it to the C++1_Le sso ns wo rking set, then type a re ading.cpp pro gram in it as sho wn: Co de to Type: reading.cpp #include <iostream> int main() { std::string name; std::cout << "Enter your name: "; std::cin >> name; std::cout << "You typed " << name << std::endl; return (0); } Save and run it. Enter a first name, a space, and a last name (separated by a space) and press Ent e r. Yo u see so mething like: OBSERVE: Enter your name: Jimi Hendrix You typed Jimi The pro gram o nly reads the first name. Yo u pro bably kno w "Jimi" by his first name, but that wo n't wo rk fo r everyo ne! But all is no t lo st! The so lutio n is to use the standard functio n std::getline. The general fo rm o f this functio n is: getline syntax std::getline( input-stream , string ); The input-stream is the so urce o f the data—in o ur case, it's st d::cin. Change yo ur reading pro gram as sho wn: Co de to Edit: reading.cpp #include <iostream> int main() { std::string name; std::cout << "Enter your name: "; std::getline(std::cin, name); std::cout << "You typed " << name << std::endl; return (0); } Save and run it again. Enter the first and last name and press Ent e r. This time the result is much better: OBSERVE: Enter your name: Jimi Hendrix You typed Jimi Hendrix st d::ge t line reads a full line up to and including the end-o f-line character. The result (minus the end o f line) is sto red in the string. Reading Integers st d::cin and the >> o perato r wo rk fo r all so rts o f variables, including integers. Edit yo ur reading pro gram as sho wn: reading.cpp #include <iostream> int main() { int value = 0; // a value to double std::cout << "Enter a value: "; std::cin >> value; std::cout << "Twice " << value << " is " << value * 2 << std::endl; return (0); } Save and run it, then click in the co nso le windo w, type 123 and press Ent e r. Yo u will see: OBSERVE: Enter a value: 123 Twice 123 is 246 Let's lo o k at this co de mo re clo sely. Observe: reading.cpp #include <iostream> int main() { int value = 0; // a value to double std::cout << "Enter a value: "; std::cin >> value; std::cout << "Twice " << value << " is " << value * 2 << std::endl; return (0); } Back in the first lesso n, we learned that the << o perato r means to "put whatever's o n the right into whatever's o n the left." Since we are using st d:cin and want to get data fro m the co nso le, we use >> to go the o ther directio n and "get whatever's o n the right from whatever's o n the left." In o ur case, we get data fro m st d::cin and put it in the variable named value . Also , lo o k at the line st d::co ut << " Ent e r a value : " ;. No tice that there's no st d::e ndl at the end. We o mitted this deliberately to make this o utput line a pro mpt. In real-wo rld pro gramming, parano ia is part o f the jo b. So o ne questio n yo u need to ask at this po int is "What happens if I type so mething that isn't a number?" Let's try it! Run yo ur pro gram again, enter "Jimi Hendrix," and press Ent e r. This time yo u'll see the fo llo wing: OBSERVE: Enter a value: Jimi Hendrix Twice 0 is 0 When yo u try to assign an inappro priate type o f data to the value variable, it do esn't change. if Statements No w that we can read data, we are go ing to create a pro gram that reads a number and tells yo u if it's even. Create a pro ject named if , assign it to yo ur C++1_Le sso ns wo rking set. In that pro ject, create a pro gram named if .cpp as sho wn: Co de to Type: if.cpp /* * if Show the use of the if statement * * In this case the program will tell you if a number * is even or odd. * * Usage: * Run the program. * Type in a number when prompted. * Get the answer. * */ #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( (number % 2) == 0) { std::cout << number << " is even" << std::endl; } return(0); } Save and run the pro gram. Enter an even number like 8. Yo u will see the fo llo wing o utput: OBSERVE: Enter a number: 8 8 is even If yo u enter an o dd number like 7, yo u wo n't see any o utput at all. Ho w do es the if statement wo rk? The key line is: if Statement in Use if ((number % 2) == 0) This says to C++, "co mpute the value o f the expressio n num be r % 2." The % is the mo dulus o perato r—it calculates the remainder after divisio n. If the value is equal to (==) zero , the pro gram executes the statements in the fo llo wing blo ck (enclo sed in curly braces {}). if statements have the fo llo wing structure: OBSERVE: if ( conditional test ) { Code to execute when conditional test is true. } else { Code to execute when conditional test is false. You do not need to have an "else." } There are o ther co mpariso n o perato rs yo u can use (in if statements and elsewhere): == Equal to != No t equal to > Greater than < Less than >= Greater than o r equal to <= Less than o r equal to Let's try a different co mpariso n. Change yo ur pro gram as sho wn: Co de to Edit: if.cpp #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( number >= 100 ) { std::cout << number << " is big!" << std::endl; } else { std::cout << number << " is not so big." << std::endl; } return(0); } In this pro gram, we changed o ur co nditio nal test slightly and added an "else" clause. Save and run it. Enter 25 0 ; yo u will see: OBSERVE: Enter a number: 250 250 is big! If yo u enter a smaller number, like -250 , yo u'll see the o ther message instead: OBSERVE: Enter a number: -250 -250 is not so big. if Abuse if Abuse Equality or Assignment? In o ur first example o f the if statement, we used the == equality o perato r to see if a number was even o r no t. What wo uld happen if yo u used a single = instead? Try it: Co de to Edit: if.cpp #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( number = 100 ) { std::cout << number << " is one hundred!" << std::endl; } else { std::cout << number << " is not one hundred." << std::endl; } return(0); } Save and run it, and enter 25 . Yo u'll see: OBSERVE: Enter a number: 25 100 is big! Try it with o ther numbers: -0 , -25, 150 . No matter what yo u type, the co mputer thinks yo u entered 10 0 ! This is because we didn't use the e qualit y o pe rat o r—instead, we changed the value o f num be r. In o ther wo rds, this line: OBSERVE: if (number = 100) was essentially interpreted as: OBSERVE: number = 100; if (number != 0) { This so rt o f erro r can be tricky to spo t. An easy way to avo id this issue is to always place co nstants o n the left side o f the co mpariso n. Change yo ur co de to the fo llo wing: Co de to Edit: if.cpp #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( 100 = number ) { std::cout << number << " is one hundred!" << std::endl; } else { std::cout << number << " is not one hundred." << std::endl; } return(0); } Save yo ur pro gram. See ho w there is a new erro r: This erro r indicates yo u are trying to change the value o f "10 0 " to whatever is sto red in num be r, but "10 0 " isn't a variable, so yo u canno t do that so rt o f assignment. Fix the erro r by using the == equality o perato r: Co de to Edit: if.cpp #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( 100 == number ) { std::cout << number << " is one hundred!" << std::endl; } else { std::cout << number << " is not one hundred." << std::endl; } return(0); } Blocks C++ allo ws yo u to write if statements in a co mpact way. Change yo ur pro gram as sho wn: Co de to Edit: if.cpp #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( 100 == number ) { std::cout << number << " is one hundred!" << std::endl; } else { std::cout << number << " is not one hundred." << std::endl; } return(0); } Save and run yo ur pro gram a few times with different numbers. Yo u will see this pro gram wo rks just like the prio r versio n. The if statement do es no t require yo u to use braces {}—it executes the statement immediately fo llo wing the if o r e lse . OBSERVE: if ( conditional test ) Code to execute when conditional test is true. else (Optional) Code to execute when conditional test is false. You do not need t o have an "else." This can be very pro blematic, tho ugh. Change yo ur pro gram as sho wn (including spaces): Co de to Edit: if.cpp #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( 50 <= number ) // if #1 if ( 100 == number ) // if #2 std::cout << number << " is one hundred!" << std::endl; else // else #1 std::cout << number << " is not so big." << std::endl; else // else #2 std::cout << number << " is ??? " << std::endl; return(0); } Co nfused? Yo u sho uld be! Witho ut braces (and pro per indentatio n), it is very hard to figure o ut what exactly will happen in this pro gram. Which e lse go es with which if ? Po ssible answers include: if #1 go es with else #1 if #2 go es with else #1 if #1 go es with else #2 If yo u do n't write co de like this, yo u wo n't have to wo rry abo ut silly questio ns like this. The co rrect answer is number 4 ! Yo u need to kno w this so yo u can debug o ther peo ple's co de. Peo ple who value co mpact co de o ver readability, understandability, and safety. Ho wever, since we find readability, understandability, and safety valuable and we write go o d co de, we will never write co de like this. Note So me peo ple tell yo u to always use {} fo r the statements affected by an if . The Perl language requires it. We co nsidered this, but decided that, fo r the mo st part, letting the pro grammer decide whether {} o r a single statement is clearer. Conditional Shortcuts If statements also let yo u take sho rtcuts in the co ndit io nal t e st . In the C++ wo rld, 0 is false, and anything else is true. With this in mind, peo ple have devised sho rtcuts, such as the fo llo wing: Co de to Edit: if.cpp #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( ! number ) { std::cout << number << " is zero!" << std::endl; } else { std::cout << number << " is not zero." << std::endl; } return(0); } The ! is the lo gical negatio n o perato r—it adds a "no t" to the co nditio n. The co nditio nal statement in this pro gram might read like "if no t number"—which is pretty co nfusing. Save and run the pro gram. Enter 0 (zero ); yo u'll see this: OBSERVE: Enter a number: 0 0 is zero. If yo u enter a no n-zero number (even -25), yo u'll see the fo llo wing: OBSERVE: Enter a number: -25 -25 is not zero. This co de is no t go o d because it isn't clear exactly what is go ing o n. Instead, be explicit with yo ur if statements. Change yo ur pro gram as sho wn: Co de to Type: if.cpp #include <iostream> int main() { int number; // A number we are going to check std::cout << "Enter a number: "; std::cin >> number; if ( 0 != number ) { std::cout << number << " is not zero." << std::endl; } else { std::cout << number << " is zero." << std::endl; } return(0); } This pro gram is clearer—the co nditio n reads "if number is no t equal to zero ." Much better! Yo u made it! In the next lesso n we will shift gears and discuss so me sho rtcuts that are co mmo n in C++ pro grams. See yo u then! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Shortcuts C++ 1: Introduction to C++ Lesson 8 There are many different ways to acco mplish the same task in C++. So me co de patterns o ccur very o ften, so the develo pers o f C and C++ have included sho rtcuts that can make co de sho rter and easier to understand. Operators Co nsider the fo llo wing o peratio n: Incrementing a Variable's Value x = x + 5; This co de pattern o ccurs frequently in C++ (and o ther languages), so the makers o f C++ added a sho rtcut o perato r to the language: Incrementing with a Sho rtcut x += 5; Other sho rtcut o perato rs are: Lo nghand Sho rt cut a = a - b; a -= b; a = a * b; a *= b; a = a / b; a /= b; a = a % b; a %= b; a = a + 1; a++; a = a - 1; a--; Let's experiment with so me sho rtcut o perato rs. Start a new pro ject named sho rt cut , and assign it to yo ur C++_Le sso ns wo rking set. In the new pro ject, create a so urce file named sho rt cut .cpp. Co de to Type: sho rtcut.cpp #include <iostream> int main() { int x = 0; // to play std::cout << "x is " << x << std::endl; x += 5; std::cout << "x is " << x << std::endl; x++; std::cout << "x is " << x << std::endl; return(0); } Save and run yo ur pro gram. Yo u'll see the value o f x change: OBSERVE: x is 0 x is 5 x is 6 One o f the mo st co mmo n uses o f these sho rtcuts is in f o r lo o ps. Let's take a lo o k: Co de to Edit: sho rtcut.cpp #include <iostream> int main() { int x = 0; // to play for (x = 0 ; x < 25; x++ ) { std::cout << "x is " << x << std::endl; } return(0); } Save and run it. Yo u'll see: OBSERVE: x x x x x x x x x x x x x x x x x x x x x x x x x is is is is is is is is is is is is is is is is is is is is is is is is is 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 We can use += to have o ur lo o p skip by five instead: Co de to Edit: sho rtcut.cpp #include <iostream> int main() { int x = 0; // to play for (x = 0 ; x < 25; x += 5 ) { std::cout << "x is " << x << std::endl; } return(0); } Save and run it. See the difference: OBSERVE: x x x x x is is is is is 0 5 10 15 20 For Loops It turns o ut the fo r lo o p has a few mo re tricks. Suppo se we wanted to write a pro gram to add several numbers, but no mo re than ten. We do n't want to include any negative numbers, and if we enco unter a zero , we will kno w o ur list is do ne. We can make this happen with two sho rtcuts: co nt inue and bre ak. Clear yo ur pro gram and type the fo llo wing: Co de to Edit: sho rtcut.cpp #include <iostream> int main() { int total; int count; int number; // Total so far // Count of the numbers // A number to read total = 0; for (count = 0; count < 10; ++count) { std::cout << "Enter a number: "; std::cin >> number; // Skip all negative numbers if (number < 0) { std::cout << "Negative numbers don't count." << std::endl; continue; } if (number == 0) { std::cout << "I guess you want to end the list" << std::endl; break; } total += number; std::cout << "The new total is " << total << std::endl; } std::cout << "The grand total is " << total << std::endl; return(0); } Save and run it. Enter a few po sitive numbers, a negative number, and finally a zero . Yo u'll see so mething like this: OBSERVE: Enter a number: 1 The new total is 1 Enter a number: 1 The new total is 2 Enter a number: 1 The new total is 3 Enter a number: 1 The new total is 4 Enter a number: 1 The new total is 5 Enter a number: -5 Negative numbers don't count. Enter a number: 9 The new total is 14 Enter a number: 0 I guess you want to end the list The grand total is 14 When the pro gram enco unters a negative number, it o utputs a message and then runs co nt inue . This skips the rest o f the fo r lo o p, and go es o n to the next number. When yo u enter a zero , the pro gram o utputs a message and then runs bre ak, which co mpletely exits the fo r lo o p and o utputs the grand to tal. Instead o f using co nt inue and bre ak, yo u co uld have acco mplished similar results by using if statements and perhaps ano ther variable, but co ntinue and break make the lo o p much easier to understand. Suppo se yo u want to allo w users to enter as many numbers as they want—and o nly quit the pro gram when they enter a zero . Yo u can change yo ur fo r lo o p to acco mplish this as well: Co de to Edit: sho rtcut.cpp #include <iostream> int main() { int total; int count; int number; // Total so far // Count of the numbers // A number to read total = 0; for (;;) { std::cout << "Enter a number: "; std::cin >> number; // Skip all negative numbers if (number < 0) { std::cout << "Negative numbers don't count." << std::endl; continue; } if (number == 0) { std::cout << "I guess you want to end the list" << std::endl; break; } total += number; std::cout << "The new total is " << total << std::endl; } std::cout << "The grand total is " << total << std::endl; return(0); } Save and run it. It will co ntinue until yo u enter a zero . Earlier, we discussed the sectio ns o f a fo r lo o p: OBSERVE: for (/* Initialization */ ; /* Test */ ; /* Increment */) { /* body of loop */ } The initializatio n, test, and increment sectio ns are all o ptio nal. Only the semico lo ns (;) are required. WARNING This can create an infinite lo o p if yo u do n't have an appro priate bre ak in yo ur co de! For Loop Misuse The go al o f pro gramming is to be as clear and co rrect as po ssible. Ho wever, so me peo ple think it's to use as few characters as po ssible. I ho pe yo u never have to debug their co de. One o f the tricks they have is to put the co mma (,) o perato r into a f o r statement. Co ding Ho rro r for (twos = 0, threes = 0; twos < 100; twos +=2, threes += 3) The co mma (,) o perato r can be used to string two C++ statements to gether and have the co mpiler treat them as o ne. Do not use it! All it really do es is make it easy to write bad co de. In this case, we have two initializatio n statements: t wo s = 0 and t hre e s = 0 . Because o f the co mma o perato r, C++ do es no t o bject to them bo th being inside a f o r initializatio n. The same ho lds true fo r the increment sectio n. Two statements have been stuffed into a place where o nly o ne sho uld go . What this lo o p is suppo sed to do is to co unt up two variables, t wo s by 2 and t hre e s by 3, all in o ne lo o p. What it really do es is to cause go o d pro grammers to curse the peo ple who think they are being clever by writing such co de. Side Effects A side effect is an effect that o ccurs in additio n to the main effect o f a statement. C++ allo ws yo u to use the ++ and -o perato rs inside o ther expressio ns. Let's take a lo o k. Clear yo ur pro gram and enter the fo llo wing: Co de to Edit: sho rtcut.cpp #include <iostream> int main() { int total_size; // Total so far int current_size; // Count of the numbers total_size = 5; current_size = -3; current_size = ++total_size; std::cout << "current_size: " << current_size << std::endl; std::cout << "total_size: " << total_size << std::endl; return(0); } Do yo u kno w what the pro gram will do ? Save and run it. The results may surprise yo u: OBSERVE: current_size: 6 total_size: 6 This is bad co de! The line curre nt _size = ++t o t al_size ; do es two things (in this o rder): 1. Increments to tal_size. 2. Assigns the value o f to tal_size to current_size. This is bad pro gramming style because it makes the co de harder to read. Two sho rt o peratio ns are much easier to maintain and understand than o ne co mplex o ne. There is ano ther pro blem with side effects. Change yo ur pro gram as sho wn: Co de to Edit: sho rtcut.cpp #include <iostream> int main() { int total_size; // Total so far int current_size; // Count of the numbers total_size = 0; current_size = 1; total_size = (++current_size * 5) + (++current_size * 3); std::cout << "current_size: " << current_size << std::endl; std::cout << "total_size: " << total_size << std::endl; return(0); } Save and run it. Once again, the o utput may surprise yo u: OBSERVE: current_size: 3 total_size: 19 The co de total_size = (++current_size * 5) + (++current_size * 3) tells C++ to : 1. Increment current_size and multiply the result by 5 2. Increment current_size and multiply the result by 3 3. Add the results fro m steps 1 and 2 to gether. There is no rule that tells C++ which step (step 1 o r step 2) to execute first. Depending o n the co mpiler, the executio n o rder co uld: 1. Increment the FIRST current_size fro m 1 to 2 and multiply the result by 5 and get 10 . 2. Increment the SECOND current_size and multiply the result by 3 and get 9 . 3. Add the results fro m steps 1 and 2 to gether and get 19 . Or, it co uld: 1. Increment the SECOND current_size fro m 1 to 2 and multiply the result by 3 and get 6 . 2. Increment the FIRST current_size fro m 2 to 3 and multiply the result by 5and get 15. 3. Add the results fro m steps 1 and 2 to gether and get 21. So , which result is right? They bo th are! The C++ standard allo ws fo r this ambiguity. That's o ne o f the reaso ns the style guide pro hibits this type o f co ding. We want to make the co de safer and mo re reliable. Yo u sho uld never use the increment (++) and decrement (--) o perato rs inside ano ther expressio n, especially an assignment statement. But so me peo ple do , so it's impo rtant to kno w ho w they wo rk. The prefix increment (++x) o perato r increments the variable and returns the result af t e r incrementing. The po stfix increment (x++) o perato r increments the variable and returns the result be f o re incrementing. The mnemo nic I use is that if yo u see the ++ first, then C++ increments first, then returns the value. If yo u see the value first, C++ returns the value first, then increments it. No w let's rewrite o ur pro gram, so it do es o ne thing at a time, with no side effects. Co de to Edit: sho rtcut.cpp #include <iostream> int main() { int total_size; // Total so far int current_size; // Count of the numbers int first_term; // for first term int second_term; // for second term total_size = 0; current_size = 1; current_size += 1; first_term = current_size * 5; current_size += 1; second_term = current_size * 3; total_size = first_term + second_term; std::cout << "current_size: " << current_size << std::endl; std::cout << "total_size: " << total_size << std::endl; return(0); } This pro gram is a little lo nger than the last, but it is very clear what is happening. Save and run it. Yo u'll see: OBSERVE: current_size: 3 total_size: 19 We co vered a lo t in this lesso n! In the next we will examine ano ther lo o p we can use in o ur pro grams: while lo o ps. See yo u then! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. While Loops C++ 1: Introduction to C++ Lesson 9 while, break, and continue Welco me back! In the previo us lesso ns we have used fo r lo o ps to do so me repetitive wo rk. In this lesso n, we'll learn abo ut while lo o ps—ano ther way to do repetitive wo rk. The basic fo rm o f the while lo o p is: while Syntax while (condition) { statement; } In the last lesso n, we used an "empty" fo r lo o p that wo uld let us input as many numbers as we wanted, and give us the grand to tal after we entered a zero . We can do the same thing using a while lo o p instead. Start a new pro ject named while , and assign it to the C++1_Le sso ns wo rking set. In the new pro ject, create a new file named while .cpp as sho wn: Co de to Type: while.cpp #include <iostream> int main() { int total; int number; // Total so far // A number to read total = 0; while( true ) { std::cout << "Enter a number: "; std::cin >> number; // Skip all negative numbers if (number < 0) { std::cout << "Negative numbers don't count." << std::endl; continue; } if (number == 0) { std::cout << "I guess you want to end the list" << std::endl; break; } total += number; std::cout << "The new total is " << total << std::endl; } std::cout << "The grand total is " << total << std::endl; return(0); } Save and run yo ur pro gram. Yo u'll so o n no tice it runs exactly the same as the fo r lo o p we used befo re—right do wn to the co nt inue and bre ak statements. Suppo se we want o ur pro gram to run until we enter a zero OR o ur grand to tal is greater than 50 . We can alter the co ndit io n in o ur lo o p to acco mplish this: Co de to Edit: while.cpp #include <iostream> int main() { int total; int number; // Total so far // A number to read total = 0; while( total <= 50 ) { std::cout << "Enter a number: "; std::cin >> number; // Skip all negative numbers if (number < 0) { std::cout << "Negative numbers don't count." << std::endl; continue; } if (number == 0) { std::cout << "I guess you want to end the list" << std::endl; break; } total += number; std::cout << "The new total is " << total << std::endl; } std::cout << "The grand total is " << total << std::endl; return(0); } Save and run it. Enter the numbers 5, 10 , 15, 20 , and 1—yo u sho uld see yo ur pro gram sto p: OBSERVE: Enter a number: 5 The new total is 5 Enter a number: 10 The new total is 15 Enter a number: 15 The new total is 30 Enter a number: 20 The new total is 50 Enter a number: 1 The new total is 51 The grand total is 50 Fibonacci numbers The Fibo nacci numbers are numbers in a sequence starting with "0 1," where each subsequent number is the sum o f the previo us two : Fibo nacci Number Calculatio ns 0 + 1 = 1 1 + 1 = 2 1 + 2 = 3 2 + 3 = 5 3 + 5 = 8 5 + 8 = 13... and so on. Thus, the first Fibo nacci numbers are 0 , 1, 1, 2, 3, 5, 8 , and 13. (Yes, 1 is in there twice.) We can use a while lo o p to calculate the sequence o f Fibo nacci numbers less than 10 0 . Create a new pro ject named f ib and assign it to yo ur C++1_Le sso ns wo rking set, and in that pro ject, create a so urce file named f ib.cpp as sho wn: Co de to Type: fib.cpp #include <iostream> int main() { int old_number; // previous Fibonacci number int current_number; // current Fibonacci number int next_number; // next number in the series // start things out old_number = 0; current_number = 1; std::cout << "0 "; // Output first number while (current_number < 100) { std::cout << current_number << ' '; next_number = current_number + old_number; old_number = current_number; current_number = next_number; } std::cout << std::endl; return (0); } Save and run it. Yo u sho uld see the Fibo nacci sequence: OBSERVE: 0 1 1 2 3 5 8 13 21 34 55 89 Ho w did we do that? Let's lo o k at the pro gram mo re clo sely. fib.cpp #include <iostream> int main() { int old_number = 0; int current_number = 1; int next_number; // previous Fibonacci number // current Fibonacci number // next number in the series std::cout << old_number; // Output first number while (current_number < 100) { std::cout << current_number << ' '; next_number = current_number + old_number; old_number = current_number; current_number = next_number; } std::cout << std::endl; return (0); } Fro m the fo rmula fo r Fibo nacci numbers, we kno w the starting values and that the next number is the sum o f the previo us ("o ld") and current numbers, so we created variables fo r the o ld_num be r (set to 0 ), the curre nt _num be r (set to 1), and ne xt _num be r (which we'll set in o ur lo o p). The first Fibo nacci number is 0 —the initial value o f o ld_num be r—so we'll just o utput it befo re we start the lo o p. (But rather than print "0 ", we'll use the variable, so if we ever ant to change it, we o nly need to change it in o ne place in the pro gram.) We want to co ntinue lo o ping while the number is less than 10 0 , so we can add a while lo o p to o ur pro gram. Inside the while lo o p, we display t he curre nt num be r, then add t he o ld and curre nt num be rs t o ge t t he value o f t he ne xt num be r. No w, to mo ve the sequence alo ng, we shift the values: m o ve t he curre nt _num be r value t o o ld_num be r and t he ne xt _num be r value t o curre nt _num be r befo re the next calculatio n. Finally, we do a little ho usekeeping. Our pro gram o utputs everything o n a single line, so we add an e nd-o f -line charact e r after the lo o p finishes. Excellent! To get a better idea ho w Fibo nacci numbers, and while lo o ps wo rk, let's add so me co ut statements. Add the co lo rized co de: Co de to Edit: fib.cpp #include <iostream> #include <iomanip> int main() { int old_number = 0; // previous Fibonacci number int current_number = 1; // current Fibonacci number int next_number; // next number in the series int iteration_count = 1; std::cout << "Iteration old current next <100?" << std::endl; while (current_number < 100) { std::cout << std::setw(2) << iteration_count; std::cout << std::setw(12) << old_number; std::cout << std::setw(9) << current_number; next_number = current_number + old_number; old_number = current_number; current_number = next_number; std::cout << std::setw(5) << next_number; if (current_number < 100) { std::cout << " T"; } else { std::cout << " F"; } std::cout << std::endl; iteration_count = iteration_count + 1; } std::cout << std::endl; return (0); } We included io m anip—specifically the st d::se t w() functio n—to help fo rmat o ur o utput. This functio n sets the padded width o f the next item in the co ut chain. Fo r example, the fo llo wing co de ensures that it e rat io n_co de is o utput as exactly two characters: OBSERVE: std::cout << std::setw(2) << iteration_count; Save and run it. This time, yo u'll see a beautifully fo rmatted table: OBSERVE: Iteration 1 2 3 4 5 6 7 8 9 10 11 old 0 1 1 2 3 5 8 13 21 34 55 current next <100? 1 1 T 1 2 T 2 3 T 3 5 T 5 8 T 8 13 T 13 21 T 21 34 T 34 55 T 55 89 T 89 144 F The o utput sho ws ho w variables are saved fo r the next trip aro und the while lo o p. By the tenth iteratio n we have the first Fibo nacci number (sto red in curre nt _num be r) that is greater than o r equal to 10 0 , so the pro gram sto ps. Yo u've added so me extremely helpful to o ls to yo ur C++ to o l kit! In the next lesso n, we'll discuss the scope o f o ur variables. See yo u then! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Scope C++ 1: Introduction to C++ Lesson 10 What is Scope? Up to this po int, we've used very basic variable declaratio ns. We've declared variables at the to p o f o ur pro grams and used them thro ugho ut the entire pro gram. In o ther wo rds, all variables existed thro ugh the entire pro gram. In this lesso n, we'll see ho w to create variables that exist fo r o nly a po rtio n o f the pro gram. We'll start with a sho rt pro gram. Create a pro ject named var-e xp and assign it to yo ur C++1_Le sso ns wo rking set. In this new pro ject, create a pro gram named var-e xp.cpp as sho wn: Co de to Type: var-exp.cpp #include <iostream> int main() { std::string state = "Texas"; std::cout << "State is " << state << std::endl; return (0); } Save and run this pro gram. As yo u might expect, yo u will see the fo llo wing o utput: OBSERVE: State is Texas No w, edit the pro gram as sho wn: #include <io stream> int main() { std::string state = "Texas"; std::co ut << "State is " << state << std::endl; return (0 ); } Co de to Edit: var-exp.cpp #include <iostream> int main() { std::string state = "Texas"; std::cout << "State #1 is " << state << std::endl; { std::string city = "Austin"; std::cout << "City is " << city << std::endl; } return (0); } Save and run it. Yo u'll see: OBSERVE: State #1 is Texas City is Austin Edit the pro gram again as sho wn: Co de to Edit: var-exp.cpp #include <iostream> int main() { std::string state = "Texas"; std::cout << "State #1 is " << state << std::endl; { std::string city = "Austin"; std::cout << "City is " << city << std::endl; } std::cout << "City #2 is " << city << std::endl; return (0); } Save yo ur pro gram; this time yo u'll no tice an erro r: The co mpiler is telling us that cit y isn't defined—but we did define it... didn't we? No t quite. The variable cit y has a local scope. Sco pe is the po rtio n o f a pro gram in which the variable is kno wn. cit y o nly exists within the curly brace ({}) blo ck enclo sing it—no t o utside o f it. Co mpare this to the st at e variable. It also has a lo cal sco pe, but its enclo sing braces include the entire pro gram. Is the st at e variable accessible fro m the middle o f o ur pro gram? Let's see. Change yo ur pro gram: } Co de to Edit: var-exp.cpp #include <iostream> int main() { std::string state = "Texas"; std::cout << "State #1 is " << state << std::endl; { std::string city = "Austin"; std::cout << "City is " << city << std::endl; std::cout << "State #2 is " << state << std::endl; } std::cout << "City #2 is " << city << std::endl; return (0); } Save and run it. Yo u'll see: OBSERVE: State #1 is Texas City is Austin State #2 is Texas Tho ugh we added a blo ck in braces and a lo cal variable to o ur list o f variables, st at e is still within the sco pe o f the pro gram. No w, let's see if we can access st at e AFTER the blo ck in braces. Change yo ur pro gram: Co de to Edit: var-exp.cpp #include <iostream> int main() { std::string state = "Texas"; std::cout << "State #1 is " << state << std::endl; { std::string city = "Austin"; std::cout << "City is " << city << std::endl; std::cout << "State #2 is " << state << std::endl; } std::cout << "State #3 is " << state << std::endl; return (0); } Save and run it. Yo u'll see: OBSERVE: State #1 is Texas City is Austin State #2 is Texas State #3 is Texas Global Variables Like their geo graphical co unterparts, yo u're in the state when yo u're in the city, but yo u're no t (necessarily) in the city when yo u're in the state. In o ur example, the st at e variable is actually a lo cal variable. It exists o nly inside the curly braces that enclo se it (but it's still available within o ther braces nested in tho se braces). Right no w that happens to be o ur entire pro gram, but we will deal with mo re co mplex pro grams in the next few lesso ns. A variable that exists o utside o f m ain() and in fact exists everywhere is called a global variable. st d::co ut , fo r example, is a glo bal variable. It exists befo re m ain() starts and after it ends. Let's declare o ur o wn glo bal variable named co unt ry. Edit yo ur pro gram as sho wn: Co de to Edit: var-exp.cpp #include <iostream> std::string country = "USA"; // A global variable int main() { std::string state = "Texas"; std::cout << "State #1 is " << state << std::endl; std::cout << "Country #1 is " << country << std::endl; { std::string city = "Austin"; std::cout << "City is " << city << std::endl; std::cout << "State #2 is " << state << std::endl; std::cout << "Country #2 is " << country << std::endl; } std::cout << "State #3 is " << state << std::endl; std::cout << "Country #3 is " << country << std::endl; return (0); } Save and run it. Yo u'll see: OBSERVE: State #1 is Texas Country #1 is USA City is Austin State #2 is Texas Country #2 is USA State #3 is Texas Country #3 is USA In the city, yo u can "see" the state and the co untry. In the state, yo u can "see" the co untry but no t the city. In the co untry, yo u can't see the state o r city. It's an imperfect anao lo gy, but it's o kay fo r the purpo se o f illustratio n, right? Storage Class The sto rage class o f a variable can be permanent o r tempo rary. The lo cal variables we've defined are tempo rary. They are created when they are declared and disappear when their enclo sing blo ck ends. Glo bal variables are permanent. They are created (and initialized) when the pro gram starts, and are no t destro yed until the pro gram ends. Let's create a quick pro gram to take a lo o k at this situatio n. Create a pro ject named var-t ype s and assign it to the C++1_Le sso ns wo rking set. In the new pro ject, create a pro gram named var-t ype s.cpp as sho wn: Co de to Type: var-types.cpp #include <iostream> int global = 1; // Global variable to play around with int main() { int loop; // A loop counter for (loop = 0; loop < 3; ++loop) { int temp = 1; // A local variable to play around with std::cout << "global is " << global << std::endl; std::cout << "temp is " << temp << std::endl; ++global; ++temp; // Almost useless comment } return (0); } Save and run it and o bserve the o utput: Output o f var-types global is 1 temp is 1 global is 2 temp is 1 global is 3 temp is 1 The value of temp never changes—but why? The answer: scope. Let's take a clo ser lo o k at the life cycle o f t e m p. var-types.cpp #include <iostream> int global = 1; // Global variable to play around with int main() { int loop; // A loop counter for (loop = 0; loop < 3; ++loop) { int temp = 1; // A local variable to play around with std::cout << "global is " << global << std::endl; std::cout << "temp is " << temp << std::endl; ++global; ++temp; // Almost useless comment } return (0); } The variable is created by the line int t e m p = 1;. It then is incremented by the line ++t e m p, so its value is 2. It then is destro yed just after the line // Alm o st use le ss co m m e nt , so it no w has no value because it do esn't exist. The f o r lo o p starts ano ther lo o p. The variable is bo rn again with the line int t e m p = 1;. It's impo rtant to remember that the sco pe o f t e m p is lo cal and the sto rage class is tempo rary. We can make a lo cal variable permanent by putting the keywo rd st at ic in fro nt o f it. Edit yo ur pro gram as sho wn: Co de to Edit: var-types.cpp #include <iostream> int global = 1; // Global variable to play around with int main() { int loop; // A loop counter for (loop = 0; loop < 3; ++loop) { int temp = 1; // A local variable to play around with static int perm = 1; // A local, permanent variable to play with std::cout std::cout std::cout ++global; ++temp; ++perm; // Almost << "global is " << global << std::endl; << "temp is " << temp << std::endl; << "perm is " << perm << std::endl; useless comment } return (0); } No w, save and run it again and o bserve the o utput: Output o f var-types global is 1 temp is 1 perm is 1 global is 2 temp is 1 perm is 2 global is 3 temp is 1 perm is 3 The sto rage class o f pe rm is permanent. It is created and initialized when the pro gram is created, and that means that it is initialized o nce. Every time thro ugh the lo o p it is incremented by o ne, unlike t e m p, which is re-initialized every time thro ugh the lo o p. On the o ther hand, the variable pe rm always stays aro und. Note The st at ic keywo rd is the mo st o verlo aded keywo rd in C++. It has many different meanings, depending o n where yo u use it. Fo r lo cal variables, it changes the sto rage class to permanent. We will examine its o ther uses as they arise. for Loop Scope In general, the sco pe o f a lo cal variable is restricted to the blo ck ({}) in which it resides. The f o r statement is special in that yo u can declare the lo o p variable right inside the f o r itself. Edit var-types.cpp as sho wn: Co de to Edit: var-types.cpp #include <iostream> int global = 1; // Global variable to play around with int main() { int loop; // A loop counter for (int loop = 0; loop < 3; ++loop) { int temp = 1; // A local variable to play around with static int perm = 1; // A local, permanent variable to play with std::cout std::cout std::cout std::cout ++global; ++temp; ++perm; // Almost << << << << "loop is " "global is "temp is " "perm is " << loop << std::endl; " << global << std::endl; << temp << std::endl; << perm << std::endl; useless comment } return (0); } Save and run it. Yo u'll see: OBSERVE: loop is 0 global is 1 temp is 1 perm is 1 loop is 1 global is 2 temp is 1 perm is 2 loop is 2 global is 3 temp is 1 perm is 3 In this case, the lo o p variable has a sco pe o f the entire bo dy o f the f o r lo o p. Hidden Variables No w we'll discuss hidden variables. First let's see them in actio n. Create a pro gram called hidden.cpp and type in the pro gram belo w. Co de to Type: hidden.cpp /* * hidden -- A very good demonstration of what not to do. * More of a puzzle than a useful program. */ #include <iostream> int main() { int a_var = 2; int b_var = 5; std::cout << "a_var #1 is " << a_var << std::endl; std::cout << "b_var #1 is " << b_var << std::endl << std::endl; { int a_var = 3; std::cout << "a_var #2 is " << a_var << std::endl; std::cout << "b_var #2 is " << b_var << std::endl << std::endl; } std::cout << "a_var #3 is " << a_var << std::endl; std::cout << "b_var #3 is " << b_var << std::endl; return (0); } Save and run it. Yo u'll see: OBSERVE: a_var #1 is 2 b_var #1 is 5 a_var #2 is 3 b_var #2 is 5 a_var #3 is 2 b_var #3 is 5 It lo o ks like a_var switched values in the middle o f the pro gram to 3 and then back to 2. But did it? No t quite. So what's happening? Let's start by lo o king at the sco pe o f b_var since we haven't played any games with it. Sco pe o f b_var int main() { int a_var = 2; int b_var = 5; std::cout << "a_var #1 is " << a_var << std::endl; std::cout << "b_var #1 is " << b_var << std::endl << std::endl; { int a_var = 3; std::cout << "a_var #2 is " << a_var << std::endl; std::cout << "b_var #2 is " << b_var << std::endl << std::endl; } std::cout << "a_var #3 is " << a_var << std::endl; std::cout << "b_var #3 is " << b_var << std::endl; return (0); } b_var's sco pe includes all o f the co de sho wn in gre e n. No w we'll sho w the sco pe o f int a_var = 3;—we need to say int a_var = 3; to identify the variable instead o f a_var, because there are two a_var variables. This co nfusio n sho uld pro vide a clue as to why hidden variables are a bad thing. Here's the sco pe o f int a_var = 3;: Sco pe o f a_var(3) int main() { int a_var = 2; int b_var = 5; std::cout << "a_var #1 is " << a_var << std::endl; std::cout << "b_var #1 is " << b_var << std::endl << std::endl; { int a_var = 3; std::cout << "a_var #2 is " << a_var << std::endl; std::cout << "b_var #2 is " << b_var << std::endl << std::endl; } std::cout << "a_var #3 is " << a_var << std::endl; std::cout << "b_var #3 is " << b_var << std::endl; return (0); } No w let's add int a_var = 2 to the mix: Sco pe o f a_var(2) and a_var(3) int main() { int a_var = 2; int b_var = 5; std::cout << "a_var #1 is " << a_var << std::endl; std::cout << "b_var #1 is " << b_var << std::endl << std::endl; { int a_var = 3; std::cout << "a_var #2 is " << a_var << std::endl; std::cout << "b_var #2 is " << b_var << std::endl << std::endl; } std::cout << "a_var #3 is " << a_var << std::endl; std::cout << "b_var #3 is " << b_var << std::endl; return (0); } Because a_var(3) has the innermo st sco pe where it is defined, it hides a_var(2) in the middle o f the pro gram. Thus, the sco pe fo r a_var(2) has a ho le in it. In o ther wo rds, the declaratio n o f a_var(3) hides a_var(2) in the dark re d area. Avo id using hidden variables whenever po ssible. That's because if yo u say so mething like "And here I print the value o f a_var," so meo ne has to ask yo u, "Which a_var?" There's eno ugh co nfusio n in the pro graming wo rld no w witho ut us adding mo re! Yo u made it! In the next lesso n we will put sco pe to wo rk with functions. Stay tuned! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Functions C++ 1: Introduction to C++ Lesson 11 What is a Function? In prio r lesso ns, o ur pro grams were fairly sho rt. Repetitio n so far has been limited to fo r and while lo o ps. In this lesso n we'll learn ho w to use functions to o rganize frequently-used co de. A functio n is like a black bo x—yo u pro vide the bo x with so me parameters, and it returns the result. Our First Function Let's suppo se we want to co mpute the area o f a right triangle (the fo rmula is are a = (base * he ight ) / 2). Create a pro ject named t riangle and assign it to yo ur C++1_Le sso ns wo rking set. In the new pro ject, create a so urce file named t riangle .cpp as sho wn: Co de to Type: triangle.cpp #include <iostream> int main() { float width; float height; float area; width = 5.0; height = 2.0; area = (width * height) / 2.0; std::cout << "Area of the first triangle is " << area << std::endl; return(0); } Save and run the pro gram. Yo u'll see: OBSERVE: Area of the first triangle is 5 Excellent! Suppo se yo u no w want to calculate area fo r two mo re triangles. Extend yo ur pro gram as sho wn: Co de to Edit: triangle.cpp #include <iostream> int main() { float width; float height; float area; width = 5.0; height = 2.0; area = (width * height) / 2.0; std::cout << "Area of the first triangle is " << area << std::endl; width = 3.8; height = 5.9; area = (width * height) / 2.0; std::cout << "Area of the second triangle is " << area << std::endl; width = 2.8; height = 1.6; area = (width * height) / 2.0; std::cout << "Area of the third triangle is " << area << std::endl; return (0); } Save and run the pro gram. Yo u'll see: OBSERVE: Area of the first triangle is 5 Area of the second triangle is 11.21 Area of the third triangle is 2.24 In o ur pro gram, we have lines o f co de that repeat: OBSERVE: area = (width * height) / 2.0; std::cout << "Area of the (nth) triangle is " << area << std::endl; Let's take tho se lines o f co de and turn them into a functio n. Edit yo ur pro gram: Co de to Edit: triangle.cpp #include <iostream> /* * triangle -- compute the area of a triangle * * Parameters * width -- the width of the triangle * height -- the height of the triangle * * Returns * the area of the triangle */ float triangle(float width, float height) { float area = (width * height) / 2.0; return (area); } int main() { float width; float height; float area; width = 5.0; height = 2.0; area = (width * height) / 2.0; std::cout << "Area of the first triangle is " << area << std::endl; width = 3.8; height = 5.9; area = (width * height) / 2.0; std::cout << "Area of the second triangle is " << area << std::endl; width = 2.8; height = 1.6; area = (width * height) / 2.0; std::cout << "Area of the third triangle is " << area << std::endl; return (0); } Let's take a clo ser lo o k at the triangle() functio n: OBSERVE: float triangle(float width, float height) { float area = (width * height) / 2.0; return (area); } The first line specifies the re t urn t ype , nam e , and param e t e rs o f the functio n. Our functio n named t riangle will return a f lo at value. It requires two parameters—the first is a f lo at nam e d widt h, the seco nd is a f lo at nam e d he ight . After calculating the are a, the functio n re t urns it. No w that we've defined o ur functio n, let's update o ur pro gram to call it: Co de to Edit: triangle.cpp #include <iostream> /* * triangle -- compute the area of a triangle * * Parameters * width -- the width of the triangle * height -- the height of the triangle * * Returns * the area of the triangle */ float triangle(float width, float height) { float area = (width * height) / 2.0; return (area); } int main() { float width; float height; float area; width = 5.0; height = 2.0; area = (width * height) / 2.0; area = triangle(5.0, 2.0); std::cout << "Area of the first triangle is " << area << std::endl; width = 3.8; height = 5.9; area = (width * height) / 2.0; area = triangle(3.8, 5.9); std::cout << "Area of the second triangle is " << area << std::endl; width = 2.8; height = 1.6; area = (width * height) / 2.0; area = triangle(2.8, 1.6); std::cout << "Area of the third triangle is " << area << std::endl; return (0); } Save and run it. Yo u'll see the same o utput as befo re: OBSERVE: Area of the first triangle is 5 Area of the second triangle is 11.21 Area of the third triangle is 2.24 Fo r each triangle calculated, we replaced three lines o f co de with o ne. We're making pro gress! Do yo u ano ther area where we co uld save a few lines o f co de? Void Functions and Array Parameters In o ur pro gram, we co uld also add co de to the t riangle () functio n to display the message like:: OBSERVE: float triangle(float width, float height) { float area = (width * height) / 2.0; std::cout << "Area of the triangle is " << area << std::endl; return (area); } This message wo uld be a side effect o f the t riangle () functio n. A functio n has a side effect if it o utputs messages, mo difies files, o r o therwise perfo rms so me actio n besides returning a value. Generally speaking, side effects are no t a go o d idea. Instead, let's create a separate functio n to o utput the message. Change yo ur pro gram: Co de to Edit: triangle.cpp #include <iostream> /* * triangle -- compute the area of a triangle * * Parameters * width -- the width of the triangle * height -- the height of the triangle * * Returns * the area of the triangle */ float triangle(float width, float height) { float area = (width * height) / 2.0; return (area); } /* * print_it -- output a message * * Parameters * area -- the area of the triangle * what -- the name of the triangle */ void print_it(float area, char what[]) { std::cout << "The area of the " << what << " triangle is " << area << std::e ndl; } int main() { float area; // Area of a triangle area = triangle(5.0, 2.0); std::cout << "Area of the first triangle is " << area << std::endl; area = triangle(3.8, 5.9); std::cout << "Area of the second triangle is " << area << std::endl; area = triangle(2.8, 1.6); std::cout << "Area of the third triangle is " << area << std::endl; return (0); } Let's take a clo ser lo o k at print _it (): OBSERVE: void print_it(float area, char what[]) { std::cout << "The area of the " << what << " triangle is " << area << std::e ndl; } This functio n named print _it () returns vo id, which means "no thing" in C++. In o ther wo rds, o ur functio n do es no t return any value. It has two parameters—a f lo at nam e d are a and a C-St yle st ring nam e d what (a character array named what). The character array parameter has no dimensio n. That is because the dimensio n is determined by the co de that calls the print _it (), as yo u will see sho rtly. Note So me o ther languages might call print _it () a pro cedure, because it do es no t return a value, and call t riangle a functio n because it do es return a value. C++ just has o ne co nstruct, a functio n. Our functio n do es no t have a re t urn statement because it isn't required inside a vo id functio n. Let's add it, and revise o ur pro gram to call print _it (): Co de to Edit: triangle.cpp #include <iostream> /* * triangle -- compute the area of a triangle * * Parameters * width -- the width of the triangle * height -- the height of the triangle * * Returns * the area of the triangle */ float triangle(float width, float height) { float area = (width * height) / 2.0; return (area); } /* * print_it -- output a message * * Parameters * area -- the area of the triangle * what -- the name of the triangle */ void print_it(float area, char what[]) { std::cout << "The area of the " << what << " triangle is " << area << std::e ndl; return; } int main() { float area; // Area of a triangle area = triangle(5.0, 2.0); std::cout << "Area of the first triangle is " << area << std::endl; print_it(area, "first"); area = triangle(3.8, 5.9); std::cout << "Area of the second triangle is " << area << std::endl; print_it(area, "second"); area = triangle(2.8, 1.6); std::cout << "Area of the third triangle is " << area << std::endl; print_it(area, "third"); return (0); } Save and run it. Yo u'll see the same o utput again: OBSERVE: The area of the first triangle is 5 The area of the second triangle is 11.21 The area of the third triangle is 2.24 Function Overloading Our print _it () functio n wo rks fine, but what if we didn't always want to pass the seco nd parameter? In C++, we can overload a functio n, which means that we can have two o r mo re different functio ns with the same name and different parameters. Let's define a new print _it () with o nly o ne parameter instead o f two . Edit yo ur pro gram as sho wn: Co de to Edit: triangle.cpp #include <iostream> /* * triangle -- compute the area of a triangle * * Parameters * width -- the width of the triangle * height -- the height of the triangle * * Returns * the area of the triangle */ float triangle(float width, float height) { float area = (width * height) / 2.0; return (area); } /* * print_it -- output a message * * Parameters * area -- the area of the triangle * what -- the name of the triangle */ void print_it(float area, char what[]) { std::cout << "The area of the " << what << " triangle is " << area << std::e ndl; return; } /* * print_it -- output a message without the "what" * * Parameters * area -- the area of the triangle */ void print_it(float area) { std::cout << "The area of the triangle is " << area << std::endl; return; } int main() { float area; // Area of a triangle area = triangle(5.0, 2.0); print_it(area, "first"); area = triangle(3.8, 5.9); print_it(area, "second"); area = triangle(2.8, 1.6); print_it(area, "third"); return (0); } Save and run it. Yo u'll see this slightly different result: OBSERVE: The area of the triangle is 5 The area of the second triangle is 11.21 The area of the third triangle is 2.24 The first time we call print _it () with o nly o ne parameter, and C++ runs the co rrect print _it () functio n that accepts o ne parameter (the seco nd o ne in the pro gram). The next two times, we call it with two parameters, and C++ runs the co rrect functio n that accepts two parameters (the first o ne in the pro gram). C++ keeps track o f this by using function signatures. A functio n signature is the co mbinatio n o f the functio n name, return data type, parameter data types, and names. In o ur pro gram, there are actually fo ur functio ns: 1. flo at triangle(do uble width, do uble height) 2. vo id print_it(flo at area, char what[]) 3. vo id print_it(flo at area) 4. int main() In C++, the functio n name and parameters must be unique. In o ther wo rds, yo u canno t define two separate functio ns like this: 1. vo id print_it(flo at area) 2. int print_it(flo at area) Default Parameters C++ lets yo u define functio ns with default parameters. Fo r example, yo u co uld decide that triangles have a default height o f 2.0 . Yo u can add a small bit o f co de to the parameter list to specify this: OBSERVE: float triangle(float width, float height = 2.0) { To see this change in actio n, edit yo ur pro gram: Co de to Edit: triangle.cpp #include <iostream> /* * triangle -- compute the area of a triangle * * Parameters * width -- the width of the triangle * height -- the height of the triangle * * Returns * the area of the triangle */ float triangle(float width, float height = 2.0) { float area = (width * height) / 2.0; return (area); } /* * print_it -- output a message * * Parameters * area -- the area of the triangle * what -- the name of the triangle */ void print_it(float area, char what[]) { std::cout << "The area of the " << what << " triangle is " << area << std::e ndl; return; } void print_it(float area) { std::cout << "The area of the triangle is " << area << std::endl; return; } int main() { float area; // Area of a triangle area = triangle(5.0, 2.0); print_it(area); area = triangle(3.8, 5.9); print_it(area, "second"); area = triangle(2.8, 1.6); print_it(area, "third"); return (0); } Save and run it. Yo u'll see the same results as befo re: OBSERVE: The area of the first triangle is 5 The area of the second triangle is 11.21 The area of the third triangle is 2.24 If we DO pro vide a height, the functio n uses it; o tehrwise, it uses the default 2.0 . WARNING Using default parameters hides info rmatio n and can make pro grams co nfusing. While yo u may enco unter default parameters in existing pro grams, yo u wo uld be wise to avo id using them in new pro grams. We co vered a lo t o f info rmatio n in this lesso n! In the next lesso n, we'll co ntinue o ur discussio n o f parameters and types. Stay tuned! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Parameters and Return Types C++ 1: Introduction to C++ Lesson 12 Welco me back! In the last lesso n we discussed functio ns, and learned ho w to write o ur o wn functio ns with parameters. In this lesso n, we'll explain just ho w parameters wo rk. Passing Parameters C++ pro vides many ways o f passing parameters to functio ns. Kno wing what cho ices yo u have and ho w to use them is key to writing go o d C++ co de. Pass by Value Let's start with a sho rt pro gram. Create a pro ject named var-pass and assign it to yo ur C++1_Le sso ns wo rking set. In the new pro ject, create a pro gram named var-pass.cpp as sho wn: Co de to Type: var-pass.cpp #include <iostream> void test(int a) { std::cout << "test: a is " << a << std::endl; a = 5; std::cout << "test: a is " << a << std::endl; } int main() { int i; // Variable to play around with i = 2; test(i); std::cout << "main: i is " << i << std::endl; return(0); } Save and run the pro gram, and o bserve the o utput: Output o f var-pass test: a is 2 test: a is 5 main: i is 2 We passed i as a parameter to t e st (), where it was labeled a. We changed the value o f a inside t e st (), but that change did no t make its way back to i. Why did this happen? It happened because the parameters to the t e st () functio n were passed by value. Internally, C++ co pies the values o f any variables passed by value and passes the co py to the functio n. Any changes to this co py will no t be reflected in the calling pro cedure. This is the default way C++ passes parameters to functio ns. Remember when we discussed ho w variables were like mailbo xes? Passing by value is like making pho to co pies o f yo ur mail, then putting the co pies in the mailbo x (the functio n), keeping the o riginals safe. C++ lets yo u pass by re f e re nce as well, using the reference (&) o perato r. Edit yo ur pro gram as sho wn: Co de to Edit: var-pass.cpp #include <iostream> void test(int& b) { std::cout << "test: b is " << b << std::endl; b = 6; std::cout << "test: b is " << b << std::endl; } int main() { int i; // Variable to play around with i = 2; test(i); std::cout << "main: i is " << i << std::endl; return(0); } Save and run it. Yo u see: Output o f var-pass test: b is 2 test: b is 6 main: i is 6 In this pro gram, i passed by reference, so the t e st () functio n changed its value: m ain: i is 6 ! With pass by reference, C++ makes the parameter b a reference to main's lo cal variable i. A reference means that these variables are the same thing. As a result, any change to b is a change to i. Using the mailbo x analo gy again, passing by reference is like putting the o riginal letter in the mailbo x, so the recipient (the functio n) can lo o k at and po tentially change it. Array Parameters No w let's see ho w functio ns wo rk with arrays. We'll add an array parameter to o ur pro gram. Co de to Edit: var-pass.cpp #include <iostream> void test(int k[]) { std::cout << "test: k[0] is " << k[0] << std::endl; k[0] = 7; std::cout << "test: k[0] is " << k[0] << std::endl; } int main() { int k[3] = {10, 20, 30}; // Array to play around with test(k); std::cout << "main: k[0] is " << k[0] << std::endl; return(0); } Save and run it. Yo u'll see: OBSERVE: test: k[0] is 10 test: k[0] is 7 main: k[0] is 7 No tice that the value o f k[0 ] is changed, even tho ugh we didn't use the & reference o perato r. That's because arrays are auto matically passed by reference. In fact, there is no way to make them pass by value. What happens if yo u pass k[0 ] to a functio n instead? Let's try it: Co de to Edit: var-pass.cpp #include <iostream> void test(int a) { std::cout << "test: a is " << a << std::endl; a = 5; std::cout << "test: a is " << a << std::endl; } int main() { int k[3] = {10, 20, 30}; // Array to play around with test(k[0]); std::cout << "main: k[0] is " << k[0] << std::endl; return(0); } Save and run it. Yo u'll see: OBSERVE: test: a is 10 test: a is 5 main: k[0] is 10 A single array element is just like a single variable—so by default, C++ passes by value. Const Parameters Let's no w pro duce a pro gram with a functio n that returns the maximum o f two integers. Start a new pro ject named m ax and assign it to yo ur C++1_Le sso ns wo rking set. Create a so urce file named m ax.cpp as sho wn: Co de to Type: max.cpp #include <iostream> // Function comments int max(int i1, int i2) { if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; std::cout << "Max is " << max(i,j) << std::endl; return (0); } Save and run it. Yo u'll see: OBSERVE: Max is 2 No tice that the values o f i1 and i2 are never changed in the m ax() functio n. Given the nature o f the functio n, they never sho uld be changed. But what if so meo ne decided to change the parameter? Edit the pro gram as sho wn: Co de to Edit: max.cpp #include <iostream> // Function comments int max(int i1, int i2) { i1 = 99; if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; std::cout << "Max is " << max(i,j) << std::endl; return (0); } Save and run it. Yo u'll see: OBSERVE: Max is 99 The functio n sho uld no t change the value o f the parameters! To help ensure that the parameters do n't change, put the mo difier co nst in fro nt o f them. Edit yo ur pro gram as sho wn: Co de to Edit: max.cpp #include <iostream> int max(const int i1, const int i2) { i1 = 99; if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; std::cout << "Max is " << max(i,j) << std::endl; return (0); } Save yo ur pro gram—yo u'll see this erro r: Co de that attempts to change the value o f a co nstant parameter results in a co mpile-time erro r. In this case, the co de i1 = 9 9 is the o ffender. References References let different variables po int to the same underlying value. It is like having a two -sided mailbo x— the po stal wo rker o pens the bo x o n o ne side to depo sit mail, and yo u o pen the bo x o n the o ther side to retrieve it. Bo th do o rs po int to the same co ntents. Let's take a deeper lo o k at references. Change yo ur co de as sho wn: Co de to Edit: max.cpp #include <iostream> int& max(const int& i1, const int& i2) { i1 = 99; if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; std::cout << "Max is " << max(i,j) << std::endl; return (0); } Save and run it—yo u'll see the o riginal message again. No w, let's add a new variable (l), which is a reference to j. We'll then zero this reference, which sho uld cause i to be zero ed. Change the co de as sho wn: Co de to Edit: max.cpp #include <iostream> int& max(int& i1, int& i2) { if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; std::cout << "Max is " << max(i,j) << std::endl; { int& l = j; // l now refers to j l = 0; // Since l is j, j is now zero std::cout << "j #1 is " << j << std::endl; } std::cout << "j #2 is " << j << std::endl; return (0); } Save and run it. Sure eno ugh, l and i bo th po int to the same place, and i ends up being set to 0 : OBSERVE: Max is 2 j #1 is 0 j #2 is 0 This is because o ur latest and greatest m ax() functio n returns a reference to i. Because it's a reference, we can use it o n the left side o f the equals sign (=) as well as the right. Make the changes indicated in the pro gram to remo ve the reference k and replace it with the reference max(i, j). Co de to Edit: max.cpp #include <iostream> int& max(int& i1, int& i2) { if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; std::cout << "Max is " << max(i,j) << std::endl; { max(i, j) = 0; // Assigning a reference l = 0; // Since l is j, j is now zero std::cout << "j #1 is " << j << std::endl; } std::cout << "j #2 is " << j << std::endl; return (0); } Save and run it. Yo u'll see: OBSERVE: Max is 2 j #1 is 0 j #2 is 0 Sure eno ugh, the reference returned by m ax(i,j), which po inted to the same place as j, was changed to zero . Const Return Values In the last example, we co uld assign a value to the reference returned by m ax(i,j). To keep this fro m happening, let's change the functio n so it returns a co nst reference. Co de to Edit: max.cpp #include <iostream> const int& max(int& i1, int& i2) { if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; std::cout << "Max is " << max(i,j) << std::endl; { max(i, j) = 0; // Assigning a reference std::cout << "j #1 is " << j << std::endl; } std::cout << "j #2 is " << j << std::endl; return (0); } Once yo u save yo ur file yo u will no tice that we can no lo nger assign a value to m ax(). Because it is a co nstant, we can o nly retrieve the result, no t change it: Problems with Reference Returns Returning a reference as an int has its benefits, but it can be very tricky to use. Let's change o ur co de so that m ax() assigns the result to a lo cal variable and returns that variable instead. Co de to Edit: max.cpp #include <iostream> const int& max(int& i1, int& i2) { int result; // Which one to use if (i1 > i2) result = i1; else result = i2; // This is a bad thing to do return(result); } int main() { int i = 1; int j = 2; std::cout << "Max is " << max(i,j) << std::endl; { max(i, j) = 0; // Assigning a reference std::cout << "i is " << i << std::endl; } return (0); } Save it—yo u'll see a warning: The co mpiler warns yo u that yo u are returning a reference to a local variable. This is reminding yo u that the variable re sult will be destro yed when m ax() returns. This is like remo ving yo ur mailbo x fro m the wall—the po stal wo rker can't put anything into the bo x, and yo u can't either. So ... what do es the reference generated by the re t urn statement refer to ? Absolutely nothing. The value referenced is no t in sco pe, so it is no t legal to reference it. This is yet ano ther area o f undefined behavio r in C++. Yo ur pro gram might wo rk just fine, o r it co uld crash, o r it co uld cause strange and mysterio us data erro rs. When a reference refers to so mething that is no lo nger in sco pe, it's called a dangling reference. Yo u can't (le gally) re t urn a re f e re nce t o a lo cal variable f ro m inside a f unct io n. No w let's try ano ther experiment with o ur pro gram. Edit the pro gram so that it uses expressio ns as parameters to m ax(): Co de to Edit: max.cpp #include <iostream> const int& max(int& i1, int& i2) { int result; // Which one to use if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; int answer; answer = max(i+1, j+1); std::cout << "Max is " << answer << std::endl; return (0); } This pro gram to o has a dangling reference that is hard to spo t, but the co mpiler wo n't let it by. Save it and yo u'll see: When a functio n expects a reference parameter such as m ax(), the co mpiler perfo rms a number o f o peratio ns behind the scenes: 1. It creates a tempo rary variable and assigns it the value o f the expressio n. 2. It perfo rms the functio n call. 3. It destro ys the tempo rary variable. So the co de the co mpiler generates lo o ks so mething like: The co mpiler's versio n o f max.cpp #include <iostream> int& max(int& i1, int& i2) { if (i1 > i2) return (i1); return(i2); } int main() { int i = 1; int j = 2; int answer; { int tmp1 = i + 1; int tmp2 = j + 1; answer = max(tmp1, tmp2); // At this point answer is a reference to tmp2 } // At this point tmp2 does not exist std::cout << "Max is " << answer << std::endl; return (0); } Yo u will rarely need to use references to variables as return values, but when yo u do need to use them, be very careful abo ut what yo u are do ing. Yo u made it! In the next lesso n we'll discuss yo ur final pro ject fo r the co urse. Go o d luck! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information. Final Project C++ 1: Introduction to C++ Lesson 13 Putting It All T ogether At this po int we've learned eno ugh to create yo ur very o wn pro gram fro m scratch. Assignment To start, create a pro ject named f inal_pro je ct assigned to yo ur C++1_Ho m e wo rk wo rking set, with a so urce file named f inal_pro je ct .cpp. Yo ur assignment is to create a pro gram that will co unt the number o f wo rds in a file. It is up to yo u to define what a "wo rd" is. "hello " is a wo rd. But what abo ut "high-five"—is that o ne wo rd o r two ? And ho w abo ut so mething like "gro und_po int"? So me pro grammers might co nsider that o ne wo rd and o thers think it was two . Did yo u co nsider so mething like "O'Reilly"? Whatever yo u decide to co nsider a wo rd, do cument yo ur decisio n in a file named re quire m e nt s.t xt . The specificatio n is as exact a descriptio n as yo u can get o f what the pro gram is go ing to do . So metimes yo u do n't kno w ho w a pro gram is go ing to end up until yo u start co ding. In that case, yo u start with a preliminary specificatio n and refine it as yo u go o n. At the end o f co ding, the specificatio n sho uld be detailed eno ugh that yo u can use it as a user guide. Create a file named spe c.t xt and write yo ur specificatio n in it. Code Design The design is a general o utline o f ho w yo u are go ing to create yo ur pro gram. The design fo r this wo rd co unt pro gram sho uld be fairly sho rt. A go o d paragraph describing the general o peratio n o f the co de sho uld do it. Create a file named de sign.t xt and enter yo ur design. Agile Development Years ago there was pro gramming technique called "fast pro to typing." To day, it has been renamed "agile develo pment." Basically, it means that yo u create the smallest wo rking pro gram yo u can. Test it, enhance it, and repeat until yo u get what yo u want. The idea is that yo u start with a wo rking co py and build a wo rking pro gram o n to p o f that. That way, yo u have a wo rking pro gram to see where yo u are and to give yo u an idea o f what the co mputer can do . This lets yo u refine yo ur specificatio n as yo u learn mo re abo ut what's happening with yo ur system. In this case, there are three stages that we go thro ugh in o ur develo pment: 1. Make a pro gram that reads a character at a time, co unting no thing. 2. Make the pro gram co unt characters. 3. Change the pro gram to co unt wo rds. Coding Notes To help yo u get started, the fo llo wing is co de that will read each character fro m a file called input .t xt and will o utput it. It uses f st re am . Co de to Type: final_pro ject.cpp #include <iostream> #include <fstream> int main () { char c; std::ifstream myfile ("input.txt"); // Make sure the file can be read from if (myfile.is_open()) { // While we have not reached the end of file (EOF) while (! myfile.eof() ) { c = myfile.get(); std::cout << c; } myfile.close(); } else std::cout << "Unable to open file"; return 0; } Create a file named input .t xt in yo ur pro ject, add so me appro priate text to it, and then save and run this co de to see ho w it wo rks. Yo ur pro gram will pro mpt fo r user input instead o f using a file. T esting Testing co mes next. Write up a test plan fo r yo ur pro gram named t e st .t xt . Take care to test all majo r co mpo nents o f yo ur pro gram. I wo uld suggest that yo u create a file named "input.txt" co ntaining the input that yo u want to use fo r testing the pro gram. To actually test the pro gram: 1. Open the input.txt file. 2. Select Edit | Se le ct All. 3. Select Edit | Co py. 4. Run the pro gram. 5. Click in the co nso le and select Edit | Past e to paste the test file's co ntents into yo ur pro gram's input. 6 . Type [Ct rl+Z ] to signal end o f file. Revisions Yo ur pro gram co unts wo rds. Think o f ho w yo u might want to enhance it. Create a file named "rev.txt" co ntaining the wish list fo r yo ur new pro gram. Then be thankful that yo u've reached the end o f the lesso n and yo u do n't have to implement any o f tho se revisio ns! When yo u finish, hand in yo ur pro ject. GOOD LUCK! Copyright © 1998-2013 O'Reilly Media, Inc. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. See http://creativecommons.org/licenses/by-sa/3.0/legalcode for more information.