Computer ScienceTextbook

How to Think Like a Computer Scientist: C++ Version

Not rated yetRate this book

Allen B. Downey's How to Think Like a Computer Scientist: C++ Version is supplied as Think C++, version 1.1.2. Fifteen chapters move from expressions and control flow to structured data,…

FormatExternal access
LanguageEnglish
SubjectComputer Science
LevelIntroductory undergraduate
No. of pages191
Published2012

Free reading is available at the official source. Opens in a new tab.

How to Think Like a Computer Scientist: C++ VersionFree

About this book

Allen B. Downey's How to Think Like a Computer Scientist: C++ Version is supplied as Think C++, version 1.1.2. Fifteen chapters move from expressions and control flow to structured data, member functions, card collections, class invariants, and file processing. This is a historically situated introduction that uses teaching libraries such as apstring, apvector, and apmatrix. Those names are part of the source, not modern standard-library types. The guide follows the linked text while helping readers separate transferable ideas about decomposition, representation, and debugging from the particular classroom tools used to teach them.

AI-assisted book summary

Allen B. Downey's How to Think Like a Computer Scientist: C++ Version is supplied as Think C++, version 1.1.2. Fifteen chapters move from expressions and control flow to structured data, member functions, card collections, class invariants, and file processing. This is a historically situated introduction that uses teaching libraries such as apstring, apvector, and apmatrix. Those names are part of the source, not modern standard-library types. The guide follows the linked text while helping readers separate transferable ideas about decomposition, representation, and debugging from the particular classroom tools used to teach them.

Chapter-by-chapter summaries

Chapter 1: The way of the program

Programming is introduced as a practice of expressing a solution precisely enough for a machine to execute it. The distinction between syntax and meaning explains why compiling successfully does not establish that a program solves the intended problem. Compile-time, runtime, and logical errors require different kinds of evidence. Downey treats debugging as an experiment: form a hypothesis, change something informative, and inspect what follows. The first small program establishes a workable cycle of editing, compiling, and running before complexity is added. This cycle becomes the practical foundation for the later emphasis on incremental development.

Study task. Compile a minimal program, introduce one error of each major kind, and record how you identified it.

Chapter 2: Variables and types

Values acquire names and types so a program can store intermediate results and express relationships. Assignment changes a variable's value; it is not a mathematical assertion that two expressions are permanently equal. Operators, precedence, characters, and composition determine how expressions are evaluated. The type of an operand can change the meaning of an operation, so a calculation that looks familiar may produce an unexpected result. Tracing values after each statement makes these distinctions concrete. The chapter establishes the vocabulary needed to reason about a program's state rather than infer that state from its final printed output.

Study task. Trace a short calculation statement by statement and explain the effect of changing one operand's type or adding parentheses.

Chapter 3: Function

Functions package a computation behind a name and parameter list. Mathematical library calls introduce floating-point results and conversions, while new function definitions make the flow of control explicit. A parameter belongs to a particular call and should be distinguished from the argument expression that supplies its value. Local variables help separate one function's internal work from another's. The chapter also introduces functions with results, preparing for the more systematic treatment that follows. Good decomposition gives a reader a manageable contract for each operation, reducing the need to understand every implementation detail at once.

Study task. Write a small function, draw the sequence of calls, and identify which names exist only inside each call.

Chapter 4: Conditionals and recursion

Conditional execution allows the program to choose among actions according to a test. Chained and nested branches organize different decision structures, while the remainder operator supports useful integer questions. Recursion adds a function call that solves a smaller instance of the same task. It needs both a terminating case and progress toward it; a valid-looking recursive call can otherwise continue without end. Stack diagrams show why multiple active calls have separate local state. The chapter connects logical conditions with execution order so a reader can explain why a particular branch or return occurs.

Study task. Trace a recursive function on a small input, marking its base case, separate stack frames, and the order in which calls finish.

Chapter 5: Fruitful functions

Returning a value makes a function usable as part of a larger expression. Incremental development helps build these functions by testing simpler intermediate versions before combining them. Boolean values and logical operators support functions that answer yes-or-no questions, and overloading allows related operations to share a name when their signatures differ. Recursive value-returning functions require attention to both the recursive result and the operation applied to it. The useful abstraction is a clear statement of what a call returns for permitted inputs. This contract allows callers to compose functions without duplicating their internal reasoning.

Study task. Develop a value-returning function in tested stages and compare its written contract with boundary-case results.

Chapter 6: Iteration

Loops repeatedly execute a block while program state changes. A correct while loop needs an appropriate initial state, a condition with the intended meaning, and an update that moves toward completion. Tables and nested repetitions show how a compact control structure can generate many results. Encapsulation and generalization then turn a specific loop into a reusable operation. Local variables make the implementation easier to reason about, but variable scope alone does not guarantee that its logic is sound. Manual traces are particularly useful for identifying off-by-one mistakes and distinguishing a terminating loop from one that happens to stop on a few examples.

Study task. Trace a loop for zero, one, and several iterations, then generalize it into a function with explicit input assumptions.

Chapter 7: Strings and things

Strings provide a concrete setting for indexed access, traversal, search, counting, concatenation, and character classification. The valid index range differs from the length itself, creating a common boundary error. A search function also needs a clear result for absence, not just success. The teaching string type used by the source has its own interface, so readers should check that interface rather than assume every later C++ library behaves identically. Comparing a library search with an explicit implementation reveals the algorithm underneath the convenient call. Mutation introduces the additional task of tracking how the contents change over time.

Study task. Implement a character search and test an empty string, repeated matches, the final position, and a missing character.

Chapter 8: Structures

A structure groups related values into a compound object, illustrated through points and rectangles. Functions can receive structures, return them, or modify them through references. Passing a copy and passing a reference create different relationships between caller and function, so a diagram of objects and variables helps predict side effects. The chapter also extends references to other types and introduces user input. Choosing a representation makes some operations natural and others awkward. Before calculating, identify what each component means and what assumptions make the combined object valid.

Study task. Compare two functions with the same apparent purpose, one taking a structure by value and the other by reference, and trace caller-visible changes.

Chapter 9: More structures

A Time structure supports a comparison of pure functions, modifiers, and functions that fill a result supplied by the caller. These designs distribute responsibility differently and should be evaluated through their contracts and effects. Const parameters make a promise about modification, while normalization and generalization reduce duplicated special cases. The chapter contrasts planned design with incremental development without treating either as a universal recipe. An algorithm can often be made clearer by changing the representation of its data. The central question is whether the representation and function interface make correct use easy to understand and verify.

Study task. Implement a time operation in both a result-returning and modifying form, then explain their side effects and normalization rules.

Chapter 10: Vectors

A vector organizes multiple values under indexed access and gives loops a collection to traverse. Copying, size, and function arguments extend the earlier ideas about values and state to many elements. Random-number experiments motivate counting, statistics, and histograms, with a single-pass method illustrating how a better organization can reduce repeated work. A seed controls reproducibility rather than making pseudo-random output intrinsically more representative. Keep the teaching apvector interface distinct from current std::vector. The important reasoning concerns index validity, the meaning of each position, and whether an algorithm visits the necessary elements exactly as intended.

Study task. Build a reproducible frequency histogram and compare a repeated-scan method with a single-pass counting algorithm.

Chapter 11: Member functions

Moving an operation into a structure or class changes how the relevant object is supplied: it becomes the receiver whose members are available implicitly. Constructors provide a controlled way to create an initialized object, while header files separate declarations from implementation. The chapter revisits earlier examples to show that object-oriented syntax reorganizes existing reasoning rather than replacing it. A member function still needs a clear contract and a careful account of mutation. Distinguish creating an object in a valid initial state from assigning values to an already existing object, especially when several construction paths are available.

Study task. Convert an earlier free function into a member function and explain the receiver, constructor behavior, and any changed call syntax.

Chapter 12: Vectors of Objects

Card objects combine named attributes with a collection of many instances. Equality and ordering require deliberate definitions: a representation does not automatically provide the comparison needed by a particular algorithm. Sequential and bisection searches illustrate the connection between data organization and search strategy. Bisection depends on sorted order under the same comparison being used to search. Subdecks also force careful decisions about interval endpoints. The chapter therefore joins object design with algorithm preconditions, showing why a fast method can return incorrect results when its assumptions are omitted even though every individual statement compiles.

Study task. Define a card ordering, sort a small collection, and trace both linear and bisection search for present and absent targets.

Chapter 13: Objects of Vectors

A Deck object owns a vector of cards, moving collection behavior behind an interface. Enumerated types and switch statements support explicit domain choices, while shuffling, dealing, sorting, and subdeck operations give the class useful behavior. Merge sort connects recursive decomposition with an operation that recombines already ordered results. Internal storage choices should be distinguished from what callers need to know. A deck operation can preserve or violate properties such as card count and uniqueness, so those properties provide useful test conditions. The chapter develops composition: an object can contain a collection of other objects without inheriting from them.

Study task. Test a shuffle-and-deal sequence for preserved card count and uniqueness, then trace one merge step using the chosen ordering.

Chapter 14: Classes and invariants

A class can protect its representation so users interact through operations intended to preserve its rules. An invariant states a condition that should hold for every valid object state. Constructors must establish it, and public operations must maintain it. This is stronger than merely moving fields behind private access: an interface can still permit invalid transitions if its logic is wrong. The chapter uses the contrast between exposed structures and controlled classes to explain information hiding. Debugging becomes easier when a failed invariant identifies the point at which a representation no longer matches its intended meaning.

Study task. Write an invariant for a class from the card or time examples and check every constructor and mutator against it.

Chapter 15: File Input/Output and apmatrixes

The final chapter moves information between programs and external files and introduces two-dimensional storage through apmatrix. Input can fail or reach the end of a file, so a robust algorithm must treat stream state as part of its control flow. Rows and columns require separate dimensions and a consistent interpretation of indices. The source's teaching matrix library belongs to its historical environment; the transferable ideas are structured access, validation, and decomposition. Closing the book means combining these tools with earlier functions and classes to process data whose size or quality is not entirely under the programmer's control.

Study task. Read a small tabular file, validate its dimensions and records, and explain how the program responds to incomplete or malformed input.

Appendix A: Quick reference for AP classes

The appendix documents the historical teaching classes used by the examples. Read it as an interface reference for reproducing this edition, not as documentation for the current C++ standard library. Keep a translation table when adapting an exercise, identifying both corresponding operations and semantic differences.

Study instructions

  1. Compile and run the source's smallest examples first, noting which teaching-library headers must be supplied.
  2. For every function, record inputs, return value, side effects, and required conditions before implementation.
  3. Use stack and object diagrams to explain recursion, copying, references, and mutation.
  4. Test collection operations with empty, one-element, missing-target, and boundary cases.
  5. Build a small file-based card or statistics program and document its representation invariants and error handling.

Questions for reflection

  • Which bugs survive successful compilation?
  • When does a reference clarify an interface, and when does it conceal a side effect?
  • What must remain true after every operation on a class?

Sources and coverage

This original study guide follows the linked source edition and its complete main chapter sequence. It explains the ideas in new wording and adds reading tasks; it does not replace the textbook, reproduce its exercises, or supply an answer key. Publisher and book source; Complete source PDF.

About access & copyright

This page provides book information and study material. Full-text access is provided by the original publisher or authorised source; a listing does not grant permission to republish the book.

Read our Library Access & Copyright policy

Explore the contents

Check the chapters covered in this edition.

Visit the official source

See reading, preview or purchase options.

Save for later

Keep this textbook in your saved collection.

Reader ratings & reviews

Be the first to rate

No ratings yet

0%0%
0%0%
0%0%
0%0%
0%0%

Share your thoughts

Your review helps other students choose the right resources.

Rate this book

How helpful was this book?No sign-up needed. Your rating appears instantly.