C++ How to Program, 4/e

Tour of the Book

© 1992-2002. Deitel & Associates, Inc. All Rights Reserved.  

Chapter 1—Introduction to Computers and C++ Programming—discusses what computers are, how they work and how they are programmed. It introduces the notion of structured programming and explains why these techniques have fostered a revolution in the way programs are written. The chapter gives a brief history of the development of programming languages from machine languages, to assembly languages, to high-level languages. The origin of the C++ programming language is discussed. The chapter introduces a typical C++ programming environment and gives a concise introduction to writing C++ programs. A detailed treatment of decision making and arithmetic operations in C++ is presented. We have introduced a new, more open, easier to read "look and feel" for our C++ source programs, most notably using syntax coloring to highlight keywords, comments and regular program text and to make programs more readable. We have also introduced a new background highlight to focus readers’ attention on the new features presented in each program. After studying this chapter, the student will understand how to write simple, but complete, C++ programs. We discuss the explosion of interest in the Internet that has occurred with the advent of the World Wide Web. We discuss namespaces and the using statements. Readers plunge right into object-orientation in the "Thinking About Objects" section that introduces the basic terminology of object technology.

Chapter 2—Control Structures—introduces the notion of algorithms (procedures) for solving problems. It explains the importance of using control structures effectively in producing programs that are understandable, debuggable, maintainable and more likely to work properly on the first try. It introduces the sequence structure, selection structures (if, if/else and switch) and repetition structures (while, do/while and for). It examines repetition in detail and compares counter-controlled loops and sentinel-controlled loops. It explains the technique of top-down, stepwise refinement that is critical to the production of properly structured programs and presents the popular program design aid, pseudocode. The methods and approaches used in Chapter  are applicable to effective use of control structures in any programming language (not just C++). This chapter helps the student develop good programming habits in preparation for dealing with the more substantial programming tasks in the remainder of the text. The chapter concludes with a discussion of logical operators—&& (and), || (or) and ! (not). We introduce the static_cast operator, which is safer than using the old-style casting C++ inherited from C. We added the "Peter Minuit" exercise, so students can see the wonders of compound interest—with the computer doing most of the work! We discuss the scoping rules for loop counters in for-loops. In the optional "Thinking About Objects" section, we begin the first phase of an object-oriented design (OOD) for the elevator simulator—identifying the classes needed to implement the simulator. We also introduce the UML use case, class and object diagrams and discuss the concepts of associations, multiplicity, composition, roles and links.

Chapter 3—Functions—discusses the design and construction of program modules. C++’s function-related capabilities include standard-library functions, programmer-defined functions, recursion, call-by-value and call-by-reference capabilities. The techniques presented in Chapter  are essential to the production of properly structured programs, especially the kinds of larger programs and software that system programmers and application programmers are likely to develop in real-world applications. The "divide and conquer" strategy is presented as an effective means for solving complex problems by dividing them into simpler interacting components. Students enjoy the treatment of random numbers and simulation, and they appreciate the discussion of the dice game of craps, which makes elegant use of control structures. The chapter offers a solid introduction to recursion and includes a table summarizing the dozens of recursion examples and exercises distributed throughout the remainder of the book. Some texts leave recursion for a chapter late in the book; we feel this topic is best covered gradually throughout the text. The extensive collection of 60 exercises at the end of the chapter includes several classic recursion problems such as the Towers of Hanoi. The chapter discusses the so-called "C++ enhancements to C," including inline functions, reference parameters, default arguments, the unary scope resolution operator, function overloading and function templates. The header files table introduces many of the header files that the reader will use throughout the book. In the optional "Thinking About Objects" section, we determine many of the class attributes needed to implement the elevator simulator. We also introduce the UML statechart and activity diagrams and the concepts of events and actions as they relate to these diagrams.

Chapter 4—Arrays—discusses the structuring of data into arrays, or groups, of related data items of the same type. The chapter presents numerous examples of both single-subscripted arrays and double-subscripted arrays. It is widely recognized that structuring data properly is just as important as using control structures effectively in the development of properly structured programs. Examples in the chapter investigate various common array manipulations, printing histograms, sorting data, passing arrays to functions and an introduction to the field of survey data analysis (with simple statistics). A feature of this chapter is the discussion of elementary sorting and searching techniques and the presentation of binary searching as a dramatic improvement over linear searching. The 121 end-of-chapter exercises include a variety of interesting and challenging problems, such as improved sorting techniques, the design of a simple airline-reservations system, an introduction to the concept of turtle graphics (made famous in the LOGO language) and the Knight’s Tour and Eight Queens problems that introduce the notion of heuristic programming so widely employed in the field of artificial intelligence. The exercises conclude with many recursion problems including the selection sort, palindromes, linear search, binary search, the Eight Queens, printing an array, printing a string backwards and finding the minimum value in an array. This chapter still uses C-style arrays, which, as you will see in Chapter  , are really pointers to the array contents in memory. In the "Thinking About Objects" section of Chapter  , we determine many of the operations (behaviors) of the classes in the elevator simulation. We also introduce the UML sequence diagram and the concept of messages that objects can send to each other.

Chapter 5—Pointers and Strings—presents one of the most powerful and difficult-to-master features of the C++ language—pointers. The chapter provides detailed explanations of pointer operators, call by reference, pointer expressions, pointer arithmetic, the relationship between pointers and arrays, arrays of pointers and pointers to functions. There is an intimate relationship between pointers, arrays and strings in C++, so we introduce basic string-manipulation concepts and discuss of some of the most popular string-handling functions, such as getline (input a line of text), strcpy and strncpy (copy a string), strcat and strncat (concatenate two strings), strcmp and strncmp (compare two strings), strtok ("tokenize" a string into its pieces) and strlen (compute the length of a string). The 134 chapter exercises include a simulation of the classic race between the tortoise and the hare, card-shuffling and dealing algorithms, recursive quicksort and recursive maze traversals. A special section entitled "Building Your Own Computer" also is included. This section explains machine-language programming and proceeds with a project involving the design and implementation of a computer simulator that allows the reader to write and run machine-language programs. This unique feature of the text will be especially useful to the reader who wants to understand how computers really work. Our students enjoy this project and often implement substantial enhancements, many of which are suggested in the exercises. In Chapter  , another special section guides the reader through building a compiler; the machine language produced by the compiler then is executed on the machine language simulator produced in the Chapter  exercises. Information is communicated from the compiler to the simulator in sequential files, which we discuss in Chapter  . A second special section includes challenging string-manipulation exercises related to text analysis, word processing, printing dates in various formats, check protection, writing the word equivalent of a check amount, Morse Code and metric-to-English conversions. The reader will want to revisit these string-manipulation exercises after studying class string in Chapter  . Many people find that the topic of pointers is, by far, the most difficult part of an introductory programming course. In C and "raw C++" arrays and strings are pointers to array and string contents in memory (even function names are pointers). Studying this chapter carefully should reward you with a deep understanding of the complex topic of pointers. Again, we cover arrays and strings as full-fledged objects later in the book. In Chapter  , we use operator overloading to craft customized Array and String classes. Chapter  also introduces Standard Library classes string and vector for manipulating strings and arrays as objects. These classes are explained in detail in Chapter  and Chapter  , respectively. Chapter  is loaded with challenging exercises. Please be sure to try the Special Section: Building Your Own Computer. In the "Thinking About Objects" section, we determine many of the collaborations (interactions among objects in the system) needed to implement the elevator system and represent these collaborations using the UML collaboration diagram. We also include a bibliography and a list of Internet and World Wide Web resources that contain the UML specifications and other reference materials, general resources, tutorials, FAQs, articles, whitepapers and software.

Chapter 6—Classes and Data Abstraction—begins our discussion of object-based programming. The chapter represents a wonderful opportunity for teaching data abstraction the "right way"—through a language (C++) expressly devoted to implementing abstract data types (ADTs). In recent years, data abstraction has become a major topic in introductory computing courses. Chapter  –Chapter  include a solid treatment of data abstraction. Chapter  discusses implementing ADTs as C++-style classes and why this approach is superior to using structs, accessing class members, separating interface from implementation, using access functions and utility functions, initializing objects with constructors, destroying objects with destructors, assignment by default memberwise copy and software reusability. The chapter exercises challenge the student to develop classes for complex numbers, rational numbers, times, dates, rectangles, huge integers and playing tic-tac-toe. Students generally enjoy game-playing programs. Mathematically inclined readers will enjoy the exercises on creating class Complex (for complex numbers), class Rational (for rational numbers) and class HugeInteger (for arbitrarily large integers). The "Thinking About Objects" section asks you to write a class header file for each of the classes in your elevator simulator. In the "Thinking About Objects" section, we use the UML class diagram developed in previous sections to outline the C++ header files that define our classes. We also introduce the concept of handles to objects, and we begin to study how to implement handles in C++.

Chapter 7—Classes Part II—continues the study of classes and data abstraction. The chapter discusses declaring and using constant objects, constant member functions, composition—the process of building classes that have objects of other classes as members, friend functions and friend classes that have special access rights to the private and protected members of classes, the this pointer, which enables an object to know its own address, dynamic memory allocation, static class members for containing and manipulating class-wide data, examples of popular abstract data types (arrays, strings and queues), container classes and iterators. The chapter exercises ask the student to develop a savings-account class and a class for holding sets of integers. In our discussion of const objects, we briefly mention keyword mutable which, as we will see in Chapter  , is used in a subtle manner to enable modification of "non-visible" implementation in const objects. We discuss dynamic memory allocation using new and delete. When new fails, the program terminates by default because new "throws an exception" in standard C++. Chapter  discusses catching and handling exceptions. We motivate the discussion of static class members with a video-game-based example. We emphasize how important it is to hide implementation details from clients of a class; then, we show private data in our class headers, which certainly reveals implementation. We discuss proxy classes, which provide a means of hiding implementation from clients of a class. The "Thinking About Objects" section asks you to incorporate dynamic memory management and composition into your elevator simulator. Students will enjoy the exercise creating class IntegerSet. This motivates the treatment of operator overloading in Chapter  . In the "Thinking About Objects" section, we present a complete elevator simulator C++ program (approximately 1,250 lines of code) and a detailed code walkthrough. The code follows directly from the UML-based design created in previous sections and employs our good programming practices, including the proper use of static and const data members and functions. We also discuss dynamic-memory allocation, composition and object interaction via handles, and how to use forward declarations to avoid the "circular-include" problem.

Chapter 8—Operator Overloading; String and Array Objects—presents one of the most popular topics in our C++ courses. Students really enjoy this material. They find it a perfect match with the discussion of abstract data types in Chapter  and Chapter  . Operator overloading enables the programmer to tell the compiler how to use existing operators with objects of new types. C++ already knows how to use these operators with objects of built-in types, such as integers, floats and characters. But suppose that we create a new string class—what would the plus sign mean when used between string objects? Many programmers use plus with strings to mean concatenation. In Chapter  , the programmer will learn how to "overload" the plus sign, so when it is written between two string objects in an expression, the compiler will generate a function call to an "operator function" that will concatenate the two strings. The chapter discusses the fundamentals of operator overloading, restrictions in operator overloading, overloading with class member functions vs. with nonmember functions, overloading unary and binary operators and converting between types. A feature of the chapter is the collection of substantial case studies including an array class, a string class, a date class, a huge integer class and a complex numbers class (the last two appear with full source code in the exercises). Mathematically inclined students will enjoy creating the polynomial class in the exercises. This material is different from what you do in most programming languages and courses. Operator overloading is a complex topic, but an enriching one. Using operator overloading wisely helps you add that extra "polish" to your classes. The discussions of class Array and class String are particularly valuable to students who will go on to use the standard library classes string and vector, which are introduced with test programs that use string and vector to mimic the capabilities shown in the String and Array examples. Introducing string and vector here gives students valuable experience with software reuse by using existing classes, rather than "reinventing the wheel." With the techniques of Chapter  –Chapter  , it is possible to craft a Date class that, if we had been using it for the last two decades, could easily have eliminated a major portion of the so-called "Year 2000 (or Y2K) Problem." The exercises encourage the student to add operator overloading to classes Complex, Rational and HugeInteger to enable convenient manipulation of objects of these classes with operator symbols—as in mathematics—rather than with function calls as the student did in the Chapter  exercises.

Chapter 9—Object-Oriented Programming: Inheritance—introduces one of the most fundamental capabilities of object-oriented programming languages. Inheritance is a form of software reusability in which programmers create classes that absorb an existing class’s data and behaviors and enhance them with new capabilities. The chapter discusses the notions of base classes and derived classes, protected members, public inheritance, protected inheritance, private inheritance, direct base classes, indirect base classes, constructors and destructors in base classes and derived classes, and software engineering with inheritance. The chapter compares inheritance ("is a" relationships) with composition ("has a" relationships) and introduces "uses-a" and "knows-a" relationships. A feature of the chapter is the example that implements a point, circle, cylinder class hierarchy. Using this "mechanical" example, we examine the relationship between base classes and derived classes, then show how derived classes use inherited data members and member functions. In the "Thinking About Objects" section, we update the elevator simulation design and implementation to incorporate inheritance. We also suggest further modifications that the student may design and implement.

Chapter 10—Object-Oriented Programming: Polymorphism—deals with another fundamental capability of object-oriented programming, namely polymorphic behavior. When many classes are related to a common base class through inheritance, each derived-class object may be treated as a base-class object. This enables programs to be written in a general manner independent of the specific types of the derived-class objects. New kinds of objects can be handled by the same program, thus making systems more extensible. Polymorphism enables programs to eliminate complex switch logic in favor of simpler "straight-line" logic. A screen manager of a video game, for example, can send a draw message to every object in a linked list of objects to be drawn. Each object knows how to draw itself. An object of a new class can be added to the program without modifying that program (as long as that new object also knows how to draw itself). This style of programming is typically used to implement today’s popular graphical user interfaces (GUIs). The chapter discusses the mechanics of achieving polymorphic behavior via virtual functions. It distinguishes between abstract classes (from which objects cannot be instantiated) and concrete classes (from which objects can be instantiated). Abstract classes are useful for providing an inheritable interface to classes throughout the hierarchy. We demonstrate abstract classes and polymorphic behavior by revisiting the point, circle, cylinder hierarchy of Chapter  . We introduce an abstract Shape base class, from which class Point inherits directly and classes Circle and Cylinder inherit indirectly. In response to this hierarchy, our professional audiences insisted that we provide a deeper explanation that shows precisely how polymorphism is implemented in C++, and hence, precisely what execution time and memory "costs" are incurred when programming with this powerful capability. We responded by developing an illustration and a precision explanation of the vtables (virtual function tables) that the C++ compiler builds automatically to support polymorphism. To conclude Chapter  , we introduce run-time type information (RTTI) and dynamic casting, which enable a program to determine an object’s type at execution time, then act on that object accordingly. We show this in the context of a more "natural" inheritance hierarchy—several classes derived from an abstract Employee base class, in which each employee has a common earnings function to calculate an employee’s weekly pay. Using RTTI and dynamic casting, we give a 10% pay increase to employees of a specific type, then calculate the earnings for such employees. For all other employee types, we calculate their earnings.

Chapter 11—Templates—discusses one of the more recent additions to C++. Function templates were introduced in Chapter  . Chapter  presents an additional function template example. Class templates enable the programmer to capture the essence of an abstract data type (such as a stack, an array, or a queue) and create—with minimal additional code—versions of that ADT for particular types (such as a queue of int, a queue of float, a queue of strings, etc.) and to provide specific type information as a parameter when creating an instance of that ADT. For this reason, class templates often are called parameterized types. The chapter discusses using type parameters and nontype parameters and considers the interaction among templates and other C++ concepts, such as inheritance, friends and static members. The exercises challenge the student to write a variety of function templates and class templates and to employ these in complete programs. We greatly enhance the treatment of templates in our discussion of the Standard Template Library (STL) containers, iterators and algorithms in Chapter  .

Chapter 12 —C++ Stream Input/Output—contains a comprehensive treatment of standard C++ object-oriented input/output. The chapter discusses the various I/O capabilities of C++, including output with the stream insertion operator, input with the stream-extraction operator, type-safe I/O, formatted I/O, unformatted I/O (for performance), stream manipulators for controlling the numeric base (decimal, octal, or hexadecimal), floating-point-number formatting, controlling field widths, user-defined manipulators, stream format states, stream error states, I/O of objects of user-defined types and tying output streams to input streams (to ensure that prompts appear before the user is expected to enter responses).

Chapter 13—Exception Handling—discusses how exception handling enables programmers to write programs that are robust, fault tolerant and appropriate for business-critical and mission-critical environments. The chapter discusses when exception handling is appropriate; introduces the basic capabilities of exception handling with try blocks, throw statements and catch blocks; indicates how and when to rethrow an exception; explains how to write an exception specification and process unexpected exceptions; and discusses the important ties between exceptions and constructors, destructors and inheritance. The exercises in this chapter show the student the diversity and power of C++’s exception-handling capabilities. We discuss rethrowing an exception, and we illustrate both ways new can fail when memory is exhausted. Prior to the C++ draft standard, new failed by returning 0, much as malloc fails in C by returning a NULL pointer value.We show the new style of new failing by throwing a bad_alloc (bad allocation) exception. We illustrate how to use set_new_handler to specify a custom function to be called to deal with memory-exhaustion situations. We discuss how to use the auto_ptr class template to delete dynamically allocated memory implicitly, thus avoiding memory leaks. To conclude this chapter, we present the standard library exception hierarchy.

Chapter 14—File Processing—discusses techniques for processing text files with sequential access and random access. The chapter begins with an introduction to the data hierarchy from bits, to bytes, to fields, to records and to files. Next, we present the C++ view of files and streams. We discuss sequential-access files and build programs that show how to open and close files, how to store data sequentially in a file and how to read data sequentially from a file. We then discuss random-access files and build programs that show how to create a file for random access, how to read and write data to a file with random access and how to read data sequentially from a randomly accessed file. The fourth random-access program combines the techniques of accessing files both sequentially and randomly into a complete transaction-processing program. Students in our industry seminars have mentioned that, after studying the material on file processing, they were able to produce substantial file-processing programs that were immediately useful in their organizations. The exercises ask the student to implement a variety of programs that build and process both sequential-access files and random-access files.

Chapter 15—Class string and String Stream Processing—The chapter also discusses C++’s capabilities for inputting data from strings in memory and outputting data to strings in memory; these capabilities often are referred to as in-core formatting or string-stream processing. Class string is a required component of the standard library. We preserved the treatment of C-like strings in Chapter  and later for several reasons. First, it strengthens the reader’s understanding of pointers. Second, for the next decade or so, C++ programmers will need to be able to read and modify the enormous amounts of C legacy code that has accumulated over the last quarter of a century—this code processes strings as pointers, as does a large portion of the C++ code that has been written in industry over the last many years. In Chapter  we discuss string assignment, concatenation and comparison. We show how to determine various string characteristics such as a string’s size, capacity and whether or not it is empty. We discuss how to resize a string. We consider the various find functions that enable us to find a substring in a string (searching the string either forwards or backwards), and we show how to find either the first occurrence or last occurrence of a character selected from a string of characters, and how to find the first occurrence or last occurrence of a character that is not in a selected string of characters. We show how to replace, erase and insert characters in a string. We show how to convert a string object to a C-style char * string.

Chapter 16—Web Programming with CGI—This new chapter has everything you need to begin developing your own Web-based applications that will really run on the Internet! You will learn how to build so-called n-tier applications, in which the functionality provided by each tier can be distributed to separate computers across the Internet or executed on the same computer. In particular, we build a three-tier online bookstore application. The bookstore's information is stored in the application's bottom tier, also called the data tier. In industrial-strength applications, the data tier is typically a database such as Oracle, Microsoft® SQL Server or MySQL. For simplicity, we use text files and employ the file-processing techniques of Chapter 14 to access these files. The user enters requests and receives responses at the application's top tier, also called the user-interface tier or the client tier, which is typically a computer running a popular Web browser such as Microsoft Internet Explorer or Netscape®. Web browsers, of course, know how to communicate with Web sites throughout the Internet. The middle tier, also called the business-logic tier, contains both a Web server and an application specific C++ program (e.g., our bookstore application). The Web server communicates with the C++ program (and vice versa) via the CGI (Common Gateway Interface) protocol. This program is referred to as a CGI script. We use the popular Apache Web server, which is available free for download from the Apache Web site, www.apache.org. Apache Installation instructions for many popular platforms, including Linux and Windows systems, are available at that site and at www.deitel.com and www.prenhall.com/deitel. The Web server knows how to talk to the client tier across the Internet using a protocol called HTTP (Hypertext Transfer Protocol). We discuss the two most popular HTTP methods for sending data to a Web server—GET and POST. We then discuss the crucial role of the Web server in Web programming and provide a simple example that requests an Extensible HyperText Markup Language (XHTML) document from a Web server. We discuss CGI and how it allows a Web server to communicate with the top tier and CGI applications. We provide a simple example that gets the server’s time and renders it in a browser. Other examples demonstrate how to process form-based user input via the string processing techniques introduced in Chapter 15. In our forms-based examples we use buttons, password fields, check boxes and text fields. We present an example of an interactive portal for a travel company that displays airfares to various cities. Travel-club members can log in and view discounted airfares. We also discuss various methods of storing client-specific data, which include hidden fields (i.e., information stored in a Web page but not rendered by the Web browser) and cookies—small text files that the browser stores on the client’s machine. The chapter examples conclude with a case study of an online book store that allows users to add books to a shopping cart. This case study contains several CGI scripts that interact to form a complete application. The online book store is password protected, so users first must log in to gain access. The chapter’s Web resources include information about the CGI specification, C++ CGI libraries and Web sites related to the Apache Web server.

Chapter 17—Data Structures—discusses the techniques used to create and manipulate dynamic data structures. The chapter begins with discussions of self-referential classes and dynamic memory allocation, then proceeds with a discussion of how to create and maintain various dynamic data structures, including linked lists, queues (or waiting lines), stacks and trees. For each type of data structure, we present complete, working programs and show sample outputs. The chapter also helps the student master pointers. The chapter includes abundant examples that use indirection and double indirection—particularly difficult concepts. One problem when working with pointers is that students have trouble visualizing the data structures and how their nodes are linked together. We have included illustrations that show the links and the sequence in which they are created. The binary-tree example is a superb capstone for the study of pointers and dynamic data structures. This example creates a binary tree, enforces duplicate elimination and introduces recursive preorder, inorder and postorder tree traversals. Students have a genuine sense of accomplishment when they study and implement this example. They particularly appreciate seeing that the inorder traversal prints the node values in sorted order. We include a substantial collection of exercises. A highlight of the exercises is the special section "Building Your Own Compiler." The exercises walk the student through the development of an infix-to-postfix-conversion program and a postfix-expression-evaluation program. We then modify the postfix-evaluation algorithm to generate machine-language code. The compiler places this code in a file (using the techniques of Chapter  ). Students then run the machine language produced by their compilers on the software simulators they built in the exercises of Chapter  . The 47 exercises include recursively searching a list, recursively printing a list backwards, binary-tree node deletion, level-order traversal of a binary tree, printing trees, writing a portion of an optimizing compiler, writing an interpreter, inserting/deleting anywhere in a linked list, implementing lists and queues without tail pointers, analyzing the performance of binary-tree searching and sorting, implementing an indexed-list class and a supermarket simulation that uses queueing. After studying Chapter  , the reader is prepared for the treatment of STL containers, iterators and algorithms in Chapter  . The STL containers are pre-packaged, templatized data structures that most programmers will find sufficient for the vast majority of applications they will need to implement. STL is a giant leap forward in achieving the vision of reuse.

Chapter 18—Bits, Characters, Strings and Structures—presents a variety of important features. C++’s powerful bit-manipulation capabilities enable programmers to write programs that exercise lower-level hardware capabilities. This helps programs process bit strings, set individual bits and store information more compactly. Such capabilities, often found only in low-level assembly languages, are valued by programmers writing system software, such as operating systems and networking software. As you recall, we introduced C-style char * string manipulation in Chapter  and presented the most popular string-manipulation functions. In Chapter  , we continue our presentation of characters and C-style char * strings. We present the various character-manipulation capabilities of the <cctype> library—these include the ability to test a character to determine whether it is a digit, an alphabetic character, an alphanumeric character, a hexadecimal digit, a lowercase letter or an uppercase letter. We present the remaining string-manipulation functions of the various string-related libraries; as always, every function is presented in the context of a complete, working C++ program. Structures in C++ are like records in other languages— they aggregate data items of various types. A feature of the chapter is its high-performance card-shuffling and dealing simulation. This is an excellent opportunity for the instructor to emphasize the quality of algorithms. The 91 exercises encourage the student to try out most of the capabilities discussed in the chapter. The feature exercise leads the student through the development of a spelling-checker program. Chapter  –Chapter  and Chapter  –Chapter  are mostly the "C legacy" portion of C++. In particular, this chapter presents a deeper treatment of C-like, char * strings for the benefit of C++ programmers who are likely to work with C legacy code. Again, Chapter  discusses class string and discusses manipulating strings as full-fledged objects.

Chapter 19—Preprocessor—provides detailed discussions of the preprocessor directives. The chapter includes more complete information on the #include directive, which causes a copy of a specified file to be included in place of the directive before the file is compiled and the #define directive that creates symbolic constants and macros. The chapter explains conditional compilation for enabling the programmer to control the execution of preprocessor directives and the compilation of program code. The # operator that converts its operand to a string and the ## operator that concatenates two tokens are discussed. The various predefined preprocessor symbolic constants (__LINE__, __FILE__, __DATE__, __STDC__, __TIME__ and __TIMESTAMP__) are presented. Finally, macro assert of the header file <cassert> is discussed, which is valuable in program testing, debugging, verification and validation.

Chapter 20—C Legacy-Code Topics—presents additional topics including several advanced topics not ordinarily covered in introductory courses. We show how to redirect program input to come from a file, redirect program output to be placed in a file, redirect the output of one program to be the input of another program (piping) and append the output of a program to an existing file. We develop functions that use variable-length argument lists and show how to pass command-line arguments to function main and use them in a program. We discuss how to compile programs whose components are spread across multiple files, register functions with atexit to be executed at program termination and terminate program execution with function exit. We also discuss the const and volatile type qualifiers, specifying the type of a numeric constant using the integer and floating-point suffixes, using the signal-handling library to trap unexpected events, creating and using dynamic arrays with calloc and realloc, using unions as a space-saving technique and using linkage specifications when C++ programs are to be linked with legacy C code. As the title suggests, this chapter is intended primarily for C++ programmers who will be working with C legacy code.

Chapter 21—Standard Template Library (STL)—Throughout this book, we discuss the importance of software reuse. Recognizing that many data structures and algorithms commonly were used by C++ programmers, the C++ standard committee added the Standard Template Library (STL) to the C++ Standard Library. The STL defines powerful, template-based, reusable components that implement many common data structures and algorithms used to process those data structures. The STL offers proof of concept for generic programming with templates—introduced in Chapter  and demonstrated in detail in Chapter  . This chapter introduces the STL and discusses its three key components— containers (popular templatized data structures), iterators and algorithms. The STL containers are data structures capable of storing objects of any data type. We will see that there are three container categories—first-class containers, adapters and near containers. STL iterators, which have similar properties to pointers, are used by programs to manipulate the STL-container elements. In fact, standard arrays can be manipulated as STL containers, using standard pointers as iterators. We will see that manipulating containers with iterators is convenient and provides tremendous expressive power when combined with STL algorithms—in some cases, reducing many lines of code to a single statement. STL algorithms are functions that perform common data manipulations such as searching, sorting, comparing elements (or entire data structures), etc. There are approximately 70 algorithms implemented in the STL. Most of these algorithms use iterators to access container elements. We will see that each first-class container supports specific iterator types, some of which are more powerful than others. A container’s supported iterator type determines whether the container can be used with a specific algorithm. Iterators encapsulate the mechanism used to access container elements. This encapsulation enables many of the STL algorithms to be applied to several containers without regard for the underlying container implementation. As long as a container’s iterators support the minimum requirements of the algorithm, then the algorithm can process that container’s elements. This also enables programmers to create algorithms that can process the elements of multiple different container types. Chapter  discusses how to implement data structures with pointers, classes and dynamic memory. Pointer-based code is complex, and the slightest omission or oversight can lead to serious memory-access violations and memory-leak errors with no compiler complaints. Implementing additional data structures such as deques, priority queues, sets, maps, etc. requires substantial additional work. In addition, if many programmers on a large project implement similar containers and algorithms for different tasks, the code becomes difficult to modify, maintain and debug. An advantage of the STL is that programmers can reuse the STL containers, iterators and algorithms to implement common data representations and manipulations. This reuse results in substantial development-time and resource savings. This chapter is meant to be an introduction to the STL. It is neither complete nor comprehensive. However, it is a friendly, accessible chapter that should convince you of the value of the STL and encourage further study. This might be one of the most important chapters in the book in terms of your appreciation of software reuse.

Chapter 22—Other Topics—is a collection of miscellaneous C++ topics. This chapter discusses two cast operators—const_cast and reinterpret_cast. These operators, along with static_cast (Chapter  ) and dynamic_cast (Chapter  ), provide a more robust mechanism for converting between types than do the original cast operators C++ inherited from C. We discuss namespaces, a feature particularly crucial for software developers who build substantial systems, especially for those who build systems from class libraries. Namespaces prevent naming collisions, which can hinder such large software efforts. We discuss the operator keywords, which are useful for programmers who do not like cryptic operator symbols. The primary use of these symbols is in international markets, where certain characters are not always available on local keyboards. We discuss keyword explicit, which prevents the compiler from invoking conversion constructors in undesirable situations; explicit-conversion constructors can be invoked only through constructor syntax, not through implicit conversions. We discuss keyword mutable, which allows a member of a const object to be changed. Previously, this was accomplished by "casting away const-ness", which is considered a dangerous practice. We also discuss pointer-to-member operators .* and ->*, multiple inheritance (including the problem of "diamond inheritance") and virtual base classes.

Appendix A—Operator Precedence Chart—presents the complete set of C++ operator symbols, in which each operator appears on a line by itself with the operator symbol, its name and its associativity.

Appendix B—ASCII Character Set—All the programs in this book use the ASCII character set, which is presented in this appendix

Appendix C—Number Systems—discusses the binary, octal, decimal and hexadecimal number systems. It considers how to convert numbers between bases and explains the one’s complement and two’s complement binary representations.

Appendix D—C++ Internet and Web Resources—contains a listing of valuable C++ resources, such as demos, information about popular compilers (including "freebies"), books, articles, conferences, job banks, journals, magazines, help, tutorials, FAQs (frequently asked questions), newsgroups, Web-based courses, product news and C++ development tools.

Appendix E—Introduction to XHTML—provides an introduction to XHTML—a markup language for describing the elements of a Web page so that a browser, such as Microsoft Internet Explorer or Netscape, can render that page. The reader should be familiar with the contents of this appendix before studying Chapter  , Web Programming with CGI. This appendix does not contain any C++ programming. Some key topics covered include incorporating text and images in an XHTML document, linking to other XHTML documents, incorporating special characters (such as copyright and trademark symbols) into an XHTML document, separating parts of an XHTML document with horizontal lines (called horizontal rules), presenting information in lists and tables, and collecting information from users browsing a site.

Appendix F—XHTML Special Characters—lists many commonly used XHTML special characters, called character entity references.

Bibliography—over 100 books and articles to encourage the student to do further reading on C++ and OOP.

Index—The book contains a comprehensive index to enable the reader to locate by keyword any term or concept throughout the text.

[ top ]

© 1992-2002. Deitel & Associates, Inc. All Rights Reserved.