Summary
This lesson opens the eighth and last unit of the course, devoted to larger programs. It explains its purpose: to organize, verify and debug programs that no longer fit in one file or in one's head; it presents its three lessons and the thread that joins them, which closes the circle opened in the first lesson of the course (specify, build, verify); it recalls what the unit takes for granted, which is the whole course; it states the problem the unit solves, that of a single-file program that works with the data it was tested with and keeps silent about a defect at the boundary of its specification; it anticipates the difference between testing and proving; and it shows where it leads, in the final project and in Programming in C++ II.
Learning objectives
- Describe the sequence of contents of the unit and explain what each lesson contributes to the next.
- Recall, with an example, the difference between declaring and defining a function, the contract that specifies it and the stages (compilation and linking) that turn several files into a program.
- Anticipate, with an example, the difference between testing a program with some cases and proving that it is correct for all admissible ones.
- Recognize what one is expected to be able to do at the end of the unit and of the course, and distinguish it from what will be learned in Programming in C++ II.
Entry assessment
Before working through the unit, it is worth measuring the starting point. This assessment is not graded: it guides your study. The first seven questions check what the unit takes for granted (declaring and defining, the precondition, the contract of a function from unit 6, the linker messages, the cases of a binary search, the trace table and reading outside a vector); the next three touch, in the order of the lessons, on the central ideas of the unit, and in them “I don’t know yet” is an honest answer. Each answer explains the point and names the lesson that deals with it; the same skills are measured again in the synthesis lesson.
Before starting the unit, measure your starting point. It is a short self-assessment: it is not graded and its result is stored only in your browser.
Question 1From earlier unitsWhat does the line
int gcd(int a, int b);written beforemaindo?It confuses declaration and definition: without a body there is nothing to execute, and no function runs because it is written, but when it is called.It confuses declaring with calling: a call does not carry the types of the parameters.It ignores that the signature is enough for the compiler to check a call; the missing body, if nobody writes it, is discovered by the linker, not by the compiler.A declaration is enough for the compiler to check each call; the definition, with the body, can be further down or in another file. The whole lesson Multiple files and custom libraries rests on this separation: the header declares, the implementation file defines.Review: Functions
Question 2From earlier unitsThe function
toBase(n, base)has the precondition “n >= 0and2 <= base <= 10”. Who must guarantee it?It confuses the precondition with input validation: validating is the task of the program's boundary, not of each function.It believes that comments are verified; the compiler discards them.It does not see that the contract distributes obligations; without it, nobody knows who made the mistake when something fails.The precondition is the part of the contract that binds the caller; in exchange, the function guarantees its postcondition. If the precondition is violated, the function promises nothing. The lesson Testing will teach how to check it withassertwhile the program is being developed.Review: Functions
Question 3From earlier unitsThe function
binarySearch(values, target)of lesson 6.4 returns a position oftarget, orvalues.size()if it is not there. What is its precondition?With the empty vector the loop does not run a single iteration and the function returns 0, which isvalues.size(): the case is covered by the postcondition.The function reports absence; requiring presence would make it useless.With repeated elements the function returns one of the positions of the value, which the postcondition allows.Each iteration discards half of the interval by comparing with the middle element, and that is valid only if the vector is sorted. With unsorted data the function answers, without warning, something false. The precondition is written in the contract, where the caller sees it.Review: Searching and sorting
Question 4From earlier unitsA program compiles without errors and, when the executable is built,
undefined reference to `tetrahedral(int)'appears. Which stage failed?It does not distinguish the compiler's messages, which cite a file and a line, from the linker's, which cite objects and names.The program never came into existence: without an executable there is no execution.A missing#includeproduceswas not declared in this scopewhen compiling, not this message.The compiler accepted each call because it saw a declaration; the linker looked for the definition in all the objects and in the libraries, and did not find it. The lesson Multiple files and custom libraries explains its usual causes: a file that was not compiled, or a declaration copied with another type.Review: Programs, compilers and C++
Question 5From earlier unitsWhich of these sets of cases best puts a binary search to the test?
It confuses quantity with coverage: it never tests absence or the boundaries, where defects usually lie.A case that has already passed is the one least likely to uncover something new.They are infinitely many, or astronomically many within the limits of the type: testing requires choosing.Each case exercises a different boundary of the interval : the interval that is empty from the start, the one that shrinks to one element, the ends and the three ways of not being there. Choosing the cases from the specification, by regions and boundaries, is the subject of the lesson Testing.Review: Searching and sorting
Question 6From earlier unitsWhat are the values of
aandbafterint a{0}; int b{1}; for (int i{0}; i < 4; ++i) { const int t{a + b}; a = b; b = t; }?It counts one iteration too many: withi < 4the body is executed four times, not five.It counts one iteration too few, the symmetric off-by-one error.It forgets thattkeeps the sum computed beforeachanges: in the last iterationareceives the 3 ofb, butbreceives that sum, 5, and not the new value ofa.Question 7From earlier unitsWhy does
std::vector<int> v{1, 2}; std::println("{}", v[2]);stop with the course options and, compiled only with-O2, without the sanitizers, possibly print an arbitrary number?It believes that optimization repairs errors; it only removes checks and assumes that the program does not violate the standard.It inverts the effect: the check that stops the program is the library's, without optimization.It is the off-by-one error of indices: those of a vector of two elements are 0 and 1.Question 8A header with include guards defines (not merely declares)
double scale(double x), withoutinline, and bothmain.cppandreport.cppinclude it. What happens when the program is built?It believes that guards act across files; they act within each translation unit.It confuses the file being compiled with the whole program: within each file there is a single definition.It is an honest answer: lesson 8.1 shows it with the real linker message.Guards prevent a header from entering the same file twice, but each.cppis compiled separately and receives its own copy of the definition: the linker finds two. It is the one-definition rule, from the lesson Multiple files and custom libraries.Question 9A function passes five hundred carefully chosen automated tests. What can be asserted?
It confuses abundance with proof; a defect at a boundary that no case touched survives any number of interior cases.The cases are not a random sample of the possible defects, and the frequency of successes does not measure the probability that the program is right.It is an honest answer: lesson 8.2 begins with this question.A test can show the presence of a defect, never its absence: asserting correctness for all cases requires an argument, like the invariant of lesson 4.3, not a list of cases. Well-chosen tests make it unlikely that a common defect slips through, and that is why they are worth so much. The lesson Testing develops this distinction.Review: Testing
Question 10A breakpoint is on the line
total += k;, inside a loop, and the program stops there for the third time. What does the highlighted line indicate?It confuses the stop with the step already taken.It confuses the place where the program stops, which the person debugging chooses, with the cause of the failure.It is an honest answer: lesson 8.3 deals with breakpoints and steps.
Loading the content…
Completed
Sign in to save your progress