Answers to all exercises of Ammeraal, L. (2000) C++ for Programmers, 3rd Edition, Chichester: John Wiley, ISBN 0-471-60697-9. See also http://home.wxs.nl/~ammeraal/ Exercise 1.1 // p01_01.cpp: Name and address. #include using namespace std; int main() { cout << "John Brown\n" << "1234 Church Street\n" << "London\n"; return 0; } Exercise 1.2 // p01_02.cpp: Computing your age. #include using namespace std; int main() { int curYear, yearOfBirth; cout << "Current year: "; cin >> curYear; cout << "Year of birth: "; cin >> yearOfBirth; cout << "Your computed age at the end of this\n" << "year is " << curYear - yearOfBirth << endl; return 0; } Exercise 1.3 a. 15 b. -16 c. 2k - 1 d. -2k Exercise 1.4 a. 00000000 00000000 00000000 000010011 b. 11111111 11111111 11111111 111111000 Exercise 1.5 // p01_05.cpp: Output of double quotes and slashes. #include using namespace std; int main() { cout << "One double quote: \"\n" "Two double quotes: \"\"\n" "Backslash: \\\n"; return 0; } Exercise 1.6 include // should be: #include int main(); // should be: int main() { int i, j // should be: { int i, j; i = 'A'; // is correct j = "B"; // should be: j = 'B'; i = 'C' + 1; // is correct cout >> "End of // should be: std::cout << "End of " program/n"; // should be: "program\n"; return 0 // should be: return 0; } Exercise 1.7 // p01_07.cpp: Hexadecimal constant #include using namespace std; int main() { cout << 0x55555555 << endl; return 0; } Exercise 1.8 Single quote: ' Double quote: " Backslash: \ The End. Exercise 2.1 // p02_01.cpp: The largest of some positive integers. #include using namespace std; int main() { int x, maximum = 0; cout << "Enter some positive integers, followed\n" "by a negative integer:\n"; for (;;) { cin >> x; if (x < 0) break; if (x > maximum) maximum = x; } cout << "Largest: " << maximum << endl; return 0; } Exercise 2.2 // p02_02.cpp: The average of some positive numbers. #include using namespace std; int main() { double x, sum = 0; int n = 0; cout << "Enter some positive numbers, followed by a\n" "negative number:\n"; for (;;) { cin >> x; if (x < 0) break; sum += x; ++n; } if (n == 0) cout << "No numbers read.\n"; else cout << "Average: " << sum/n << endl; return 0; } Exercise 2.3 // p02_03: Sum of final two decimal digits. #include using namespace std; int main() { int x; cout << "Enter an integer: "; cin >> x; if (x < 0) x = -x; cout << "The sum of the final two digits is " << x % 10 + x % 100 / 10 << endl; return 0; } Exercise 2.4 // p02_04.cpp: Given an sequence of 20 integers, how // often is an element of this sequence // immediately followed by a smaller one? #include using namespace std; int main() { int xOld, xNew, i, nLargePrecedesSmall = 0; cout << "Enter 20 integers: \n"; cin >> xOld; for (i=2; i<=20; ++i) { cin >> xNew; if (xOld > xNew) nLargePrecedesSmall++; xOld = xNew; } cout << "A larger integer is immediately followed by " << "a smaller one " << nLargePrecedesSmall << " times.\n"; return 0; } Exercise 2.5 // p02_05.cpp: The second smallest of an input sequence // of 10 integers. // Note that the second smallest of // 1 1 1 1 1 2 3 4 5 6 // is 2, not 1. #include using namespace std; int main() { int x, minimum, secondSmallest; cout << "Enter 10 integers:\n"; cin >> x; minimum = secondSmallest = x; for (int i=1; i<10; ++i) { cin >> x; if (minimum == secondSmallest) { if (x < minimum) minimum = x; else secondSmallest = x; } else if (x < minimum) { secondSmallest = minimum; minimum = x; } else if (x > minimum && x < secondSmallest) secondSmallest = x; } if (minimum == secondSmallest) cout << "Ten equal integers read.\n"; else cout << "The second smallest is " << secondSmallest << endl; return 0; } Exercise 2.6 // p02_06.cpp: Three sides of a triangle? #include using namespace std; int main() { double a, b, c, h; const double eps = 1e-8; cout << "Enter three numbers a, b and c: "; cin >> a >> b >> c; if (a > c){h = a; a = c; c = h;} // Now c >= a if (b > c){h = b; b = c; c = h;} // Now c >= b if (a + b < c + eps) cout << "No triangle possible with these data.\n"; else { double v = a * a + b * b - c * c; if (v < -eps) cout << "The triangle has an obtuse angle.\n"; else if (v > +eps) cout << "The triangle has three acute angles\n"; else cout << "This is a right angled triangle.\n"; } return 0; } Exercise 2.7 // p02_07.cpp: Compute all sequences of two or more successive // integers whose sum is equal to a given number. // The solution below is not the simplest one, but // it is very efficient in that it does not contain // any nested loops. #include using namespace std; int main() { int s, n, k, ndiv2, t1, tn; cout << "Enter the desired sum: "; cin >> s; for (n=2; n using namespace std; int main() { int n, k; const char white = ' ', black = '*'; cout << "Chessboard of n x n squares; each black square\n" << "consists of k x k asterisks.\n" << "Enter n and k: "; cin >> n >> k; int nk = n * k; for (int I=0; I using namespace std; int main() { int minim, maxim, iMin, iMax, x, i; cout << "Enter 20 integers:\n"; cin >> minim; maxim = minim; iMin = iMax = 1; for (i=2; i<=20; ++i) { cin >> x; if (x < minim){minim = x; iMin = i;} if (x >= maxim){maxim = x; iMax = i;} } cout << "Smallest: " << minim << " (first occurrence at position: " << iMin << ").\n"; cout << "Largest: " << maxim << " (last occurrence at position: " << iMax << ").\n"; return 0; } Exercise 2.10 // p02_10.cpp: With a given n x n matrix, compute the // maximum distance of a nonzero element to the // main diagonal. (This distance is zero if only // this diagonal contains nonzero elements.) #include #include using namespace std; int main() { int n, max = 0, i, j, d; float x; cout << "Enter n: "; cin >> n; cout << "Enter all n x n matrix elements:\n"; for (i=1; i<=n; ++i) for (j=1; j<=n; ++j) { cin >> x; if (x != 0) { d = abs(i - j); if (d > max) max = d; } } cout << "The desired distance is equal to " << max << endl; cout << "(This is the maximum value of |i - j|\n" "for which aij is nonzero.)\n"; return 0; } Exercise 3.1 // p03_01.cpp: Largest integer and its frequency in a sequence #include using namespace std; int main() { cout << "Enter integers, followed by a nonnumeric character:\n"; int maxim, n = 1, x; cin >> maxim; if (!cin) cout << "Error: no integer read at all.\n"; else while (cin >> x) { if (x > maxim) { maxim = x; ++n; } } cout << "Largest: " << maxim << ". This occurs " << n << " times.\n"; return 0; } Exercise 3.2 // p03_02.cpp: How many numbers, read from the keyboard, // are multiples of 2, 3, and 5? #include using namespace std; int main() { int x, n2 = 0, n3 = 0, n5 = 0; cout << "Enter some integers, followed by a " "nonnumeric character:\n"; while (cin >> x) { if (x % 2 == 0) n2++; if (x % 3 == 0) n3++; if (x % 5 == 0) n5++; } cout << n2 << " multiples of 2\n"; cout << n3 << " multiples of 3\n"; cout << n5 << " multiples of 5\n"; return 0; } Exercise 3.3 // p03_03.cpp: Sum of 1st, 3rd, 6th, 10th, 15th,... elements // of a number sequence entered by the user. #include using namespace std; int main() { float x, s = 0; int i = 0, iAdd = 1, diff = 1; cout << "Add numbers followed by a nonnumeric character: \n"; while (cin >> x) { if (++i == iAdd) { s += x; iAdd += ++diff; } } cout << "Sum (of 1st, 3rd, 6th, 10th, 15th,... number) is " << s << endl; return 0; } Exercise 3.4 // p03_04.cpp: How many distinct integers are read? // (Duplicates are not counted.) #include using namespace std; int main() { const int maxN = 20; // At most 20 distinct integers, with unlimited numbers of // duplicates. cout << "Enter integers, followed by a nonnumeric "character:\n"; int n=0, i, a[maxN], x; while (cin >> x) { for (i=0; i #include using namespace std; int main() { int f[64] = {0}, x; cout << "Enter integers, followed by a " "nonnegative character:\n"; while (cin >> x) ++f[x & 0x3F]; cout << " i freq[i]\n\n"; for (int i=0; i<64; ++i) if (f[i] > 0) cout << setw(2) << i << setw(8) << f[i] << endl; return 0; } Exercise 3.6 // p03_06.cpp: Read month, day, year (for example, 12 31 1999) // and compute the day number (within one year) of this date. #include using namespace std; int main() { int day, month, year, i, dayNumber=0, cal[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; cout << "Enter month, day and year, such as 12 31 1999:\n"; cin >> month >> day >> year; if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ++cal[2]; for (i=1; i<=12; i++) if (i < month) dayNumber += cal[i]; else break; dayNumber += day; cout << "Day number, counted from January 1st, is " << dayNumber << endl; return 0; } Exercise 3.7 // p03_07.cpp: Storing four nonnegative integers of four bits // in a short int. #include using namespace std; int main() { int a0, a1, a2, a3, i; short int x; cout << "Enter four nonnegative integers " "a0, a1, a2 en a3,\n" "each less than 16:\n"; cin >> a0 >> a1 >> a2 >> a3; x = a3 << 12 | a2 << 8 | a1 << 4 | a0; cout << "Enter 0, 1, 2, or 3 to retrieve the first,\n" << "second, third, or fourth of these integers:\n"; cin >> i; int nShift = 4 * i; int ai = (static_cast(x) >> nShift) & 0xF; cout << "Retrieved: " << ai << endl; return 0; } Exercise 3.8 // p03_08.cpp: Using the operators << and + to multiply by 100. #include using namespace std; int main() { int x, y; cout << "x = "; cin >> x; y = (x << 6) + (x << 5) + (x << 2); if (x > 0 && y < x || x < 0 && y > x) cout << "Take a smaller number for x.\n"; else cout << "100x = " << y << endl; return 0; } Exercise 3.9 // p03_09.cpp: Swapping bits 0 and 7, 1 and 6, 2 and 5, and 3 and 4. #include using namespace std; int main() { unsigned int x, leftPart, y=0, i; cout << "Enter a hexadecimal number; for example, a5f0: "; cin >> hex >> x; leftPart = x & ~0xFF; for (i=0; i<8; i++) { y <<= 1; // Shift y one position to the left y |= x & 1; // Transport the rightmost bit from x to y x >>= 1; // Shift x one position to the right } y |= leftPart; cout << "After swapping, we obtain " << hex << y << " (hex).\n"; return 0; } Exercise 3.10 // p03_10.cpp: As Exercise 3.9, but bits 0-7 are rotated // one position to the left. #include using namespace std; int main() { unsigned int x, leftPart, rightPart, newBit0, y=0; cout << "Enter a hexadecimal integer; for example, a5f0: "; cin >> hex >> x; leftPart = x & ~0xFF; rightPart = x & 0xFF; newBit0 = (x & 0x80) >> 7; y = (rightPart << 1) & 0xFF | leftPart | newBit0; cout << "After rotating the rightmost eight bits one\n" "position to the left, we obtain: " << hex << y << endl; return 0; } Exercise 3.12 // p03_11.cpp: Application of Horner's rule. #include using namespace std; int main() { int n, i; float x, y, a; cout << "Enter n, x, a(n), a(n-1), ..., a(0): "; cin >> n >> x; y = 0; for (i=n; i>=0; i--) { cin >> a; y = x * y + a; } cout << "Result = " << y << endl; return 0; } Exercise 3.12 // p03_12.cpp: Read ten integers and compute the position // of the one that is equal to the final one. If there // are several, take the first that you encounter. #include using namespace std; int main() { int a[10], i; cout << "Enter 10 integers (a[0], ..., a[9]):\n"; for (i=0; i<10; ++i) cin >> a[i]; i = 0; while (a[i] != a[9]) ++i; cout << "a[" << i << "] = a[9]\n"; return 0; } Exercise 3.13 // p03_13.cpp: Straight selection sort. // (This should in practice not be done in this way, // but rather by means of the sort algorithm, as discussed // in Section 9.13.) #include using namespace std; void SelSort(float *a, int n) // Sort a[0], a[1], ..., a[n-1] { int i, j, imin; float min; for (i=0; i> x; if (cin.fail()) break; a[n] = x; } // We will now deal with a[0], ..., a[n-1], where n <= N. SelSort(a, n); cout << "The same numbers in ascending order:\n"; for (i=0; i #include using namespace std; int main() { int a[25], i, j, max = 0; cout << "Enter 25 positive integers, not greater than 40:\n"; for (j=0; j<25; ++j) { if (!(cin >> a[j]) || a[j] <= 0 || a[j] > 40) { cout << "Incorrect input.\n"; return 1; } if (a[j] > max) max = a[j]; } cout << endl; for (i=max; i>0; --i) { for (j=0; j<25; ++j) cout << (a[j] >= i ? " I" : " "); cout << endl; } for (j=0; j<25; ++j) cout << setw(3) << j; cout << endl; return 0; } Exercise 3.15 // p03_15.cpp: Count how often each of the integers // 0, 1, ..., 15 occurs in an input sequence. #include #include using namespace std; int main() { int i, a[16] = {0}; cout << "Enter integers, followed by a nonnumeric " "character:\n"; while (cin >> i) if (i >= 0 && i < 16) a[i]++; cout << "\nThe integers 0, 1, ..., 15 have been entered " "with the following frequencies:\n\n"; cout << "Number Frequency\n"; for (i=0; i<16; ++i) if (a[i] > 0) cout << setw(4) << i << setw(9) << a[i] << endl; return 0; } Exercise 3.16 // p03_16.cpp: A symmetric table. #include #include using namespace std; int main() { int i, j, n; cout << "Enter a (reasonably small) positive integer n: "; cin >> n; cout << endl; for (i=1; i<=n; ++i) { for (j=1; j<=n; ++j) cout << setw(3) << (i < j ? i : j); cout << endl; } return 0; } Exercise 3.17 // p03_17.cpp: Average, variance, and range of a sequence of // real numbers. #include using namespace std; int main() { double x, s = 0, s2 = 0, minim, maxim; int n = 0; cout << "Enter two or more numbers, followed by a " "nonnumeric character:\n"; while (cin >> x) { ++n; if (n == 1) minim = maxim = x; else { if (x < minim) minim = x; if (x > maxim) maxim = x; } s += x; s2 += x * x; } if (n < 2) cout << "At least two numbers, please.\n"; else { cout << "Average: " << s/n << endl; cout << "Variance: " << (s2 - s * s / n)/(n - 1) << endl; cout << "Range: " << maxim - minim << endl; } return 0; } Exercise 4.1 // p04_01.cpp: Rectangle of asterisks. #include using namespace std; void rectangle(int w, int h, bool outline) { for (int i=1; i<=h; ++i) { for (int j=1; j<=w; ++j) cout << (!outline || i == 1 || i == h || j == 1 || j == w ? '*' : ' '); cout << endl; } } int main() { cout << "Enter the rectangle's width and height: "; int width, height; cin >> width >> height; cout << "Do you want to print only the outline? (Y/N): "; char ch; cin >> ch; bool outlineOnly = (ch == 'Y' || ch == 'y'); rectangle(width, height, outlineOnly); return 0; } Exercise 4.2 // p04_02.cpp: Sum of the decimal digits of an integer. #include #include using namespace std; int digitsum(int n) { int sum=0; n = abs(n); while (n > 0) { sum += n % 10; n /= 10; } return sum; } int main() { int k; cout << "Enter an integer: "; cin >> k; cout << "The sum of its decimal digits is " << digitsum(k) << ".\n"; return 0; } Exercise 4.3 // p04_03.cpp: Display all positive integers x less than 100, // such that a given digit d occurs both in x and // in x * x. #include #include using namespace std; bool occursIn(int d, int x) // Does digit d occur in integer x? { while (x != 0) { if (d == x % 10) return true; x /= 10; } return false; } int main() { int d, x; cout << "Enter a decimal digit (0 - 9): "; cin >> d; for (x=1; x<100; ++x) { if (occursIn(d, x) && occursIn(d, x * x)) cout << setw(2) << x << setw(6) << x * x << endl; } return 0; } Exercise 4.4 // p04_04.cpp: The functions sort4 and sort4p to sort // four integers. #include #include using namespace std; // C++ reference parameters: void sort2(int &x, int &y) { if (x > y){int t = x; x = y; y = t;} } void sort4(int &w, int &x, int &y, int &z) { sort2(w, x); sort2(y, z); // w or y is now the minimum; // x or z the maximum. sort2(w, y); // w is now the minimum. sort2(x, z); // z is now the maximum. sort2(x, y); // Now w <= x <= y <= z. } // C style pointer parameters: void sort2p(int *p, int *q) { if (*p > *q) { int h=*p; *p = *q; *q = h; } } void sort4p(int *pa, int *pb, int *pc, int *pd) { sort2p(pa, pb); sort2p(pc, pd); sort2p(pa, pc); sort2p(pb, pd); sort2p(pb, pc); } int main() { int a, b, c, d, a0, b0, c0, d0; cout << "Enter four integers: "; cin >> a0 >> b0 >> c0 >> d0; a = a0; b = b0; c = c0; d = d0; sort4(a, b, c, d); cout << "Sorted by sort4 (reference parameters): " << endl << a << " " << b << " " << c << " " << d << endl; a = a0; b = b0; c = c0; d = d0; sort4p(&a, &b, &c, &d); cout << "Sorted by sort4p (pointer parameters): " << endl << a << " " << b << " " << c << " " << d << endl; return 0; } Exercise 4.5 // p04_05.cpp: Writing a number as a product of prime factors. #include using namespace std; void tryFactor(unsigned long *p, unsigned i) { static int factorPrinted = 0; while (*p % i == 0) { if (factorPrinted) cout << " x "; else { cout << " = "; factorPrinted = 1; } cout << i; *p /= i; } } int main() { unsigned long a, a0, i; do { cout << "Enter a positive integer: "; cin >> a; } while (a < 1); a0 = a; cout << endl << a; tryFactor(&a, 2); for (i=3; i*i <= a0; i+=2) tryFactor(&a, i); if (a > 1) tryFactor(&a, a); cout << endl; return 0; } Exercise 4.6 Let us denote the output for k = n as u(n). Then u(k) is empty (no output) for negative or zero k. Each other u(k) consists of u(k - 2) and u(k - 1), separated by the value k: u(1) = u(-1) 1 u(0) = 1 u(2) = u(0) 2 u(1) = 2 1 u(3) = u(1) 3 u(2) = 1 3 2 1 u(4) = u(2) 4 u(3) = 2 1 4 1 3 2 1 u(5) = u(3) 5 u(4) = 1 3 2 1 5 2 1 4 1 3 2 1 Exercise 4.7 // p04_07.cpp: Recursive and nonrecursive computation // of the greatest common divisor (gcd). #include using namespace std; int gcd(int x, int y) // Recursive { return y == 0 ? x : gcd(y, x % y); } int gcd1(int x, int y) // Nonrecursive { int t; while (y > 0) { t = x; x = y; y = t % y; } return x; } int main() { int a, b; cout << "Enter two integers a and b (not both zero):\n"; cin >> a >> b; a = abs(a); b = abs(b); if (a + b == 0) cout << "a = b = 0 is not allowed.\n"; else { cout << "gcd (a, b) = " << gcd(a, b) << endl; cout << "gcd1(a, b) = " << gcd1(a, b) << endl; } return 0; } Exercise 4.8 // p04_08.cpp: Solution to the Towers of Hanoi problem. #include using namespace std; /* A tower of n disks is moved from peg src to peg dest; peg aux may be used temporarily. */ void Hanoi(char src, char aux, char dest, int n) { if (n > 0) { Hanoi(src, dest, aux, n-1); cout << "Disk " << n << " from peg " << src << " to peg " << dest << '.' << endl; Hanoi(aux, src, dest, n-1); } } int main() { int n; cout << endl; cout << "Enter n, the number of disks: "; cin >> n; Hanoi('A', 'B', 'C', n); cout << endl; return 0; } Exercise 4.09 // p04_09.cpp: Macros max2 and max3. #include using namespace std; #define max2(x, y) ((x) > (y) ? (x) : (y)) #define max3(x, y, z) max2(x, max2(y, z)) int main() { int a, b, c; cout << "2 times the maximum of " << "a = 3 + 4, b = 2 + 3 en c = 5 - 3 is " << 2 * max3(a = 3 + 4, b = 2 + 3, c = 5 - 3) << endl; return 0; } Exercise 4.10 // p04_10.cpp: Binary coded decimal. (Only the least // significant two digits are taken). #include using namespace std; unsigned char bcd(int n) { return (n/10 % 10 << 4) | n % 10; } int main() { int result = bcd(12345); cout << "The BCD representation of the final two digits of 12345\n" "is the byte " << hex << result << " (hex).\n"; // 45 return 0; } Exercise 4.11 // p04_11.cpp: Real quadratic equation ax2 + bx + c = 0. #include #include using namespace std; int main() { double a, b, c, D, sq; const double eps = 1e-8; cout << "Enter a, b, and c: "; cin >> a >> b >> c; if (a == 0) { if (b == 0) { if (c == 0) cout << "Any x is a root of this equation.\n"; else cout << "No solution.\n"; } else // a == 0, b != 0: cout << "x = " << -c/b << endl; } else // a != 0 { D = b * b - 4 * a * c; if (D < -eps) cout << "No solution.\n"; else if (D > +eps) { sq = sqrt(D); cout << "Two roots: " << (-b+sq)/(2*a) << " and " << (-b-sq)/(2*a) << endl; } else cout << "Two equal roots: " << -b/(2*a) << endl; } return 0; } Exercise 4.12 // p04_12.cpp: Compute the maximum of // |a2-a1|, |a3-a2|, ..., |a20-a19|, // where the sequence a1, a2, ..., a20 // is read from the keyboard. #include #include using namespace std; int main() { int maxdif = 0, x, xOld, dif; cout << "Enter 20 integers:\n"; cin >> x; for (int i=2; i<=20; ++i) { xOld = x; cin >> x; dif = abs(x - xOld); if (dif > maxdif) maxdif = dif; } cout << "The maximum absolute difference between any\n" << "two elements in the sequence is equal to " << maxdif << endl; return 0; } Exercise 4.13 // p04_13.cpp: The equation sin x - 0.5x = 0 solved // numerically by using Newton-Raphson. #include #include #include using namespace std; double f(double x){return sin(x) - 0.5 * x;} double f1(double x){return cos(x) - 0.5;} int main() { double x = 3, x0 = 0, y; int i; cout << "Intermediate results:\n" << setiosflags(ios::showpoint | ios::showpos); for (i=1; i<100; ++i) { y = f(x); cout << "x = " << fixed << setprecision(16) << x << " y = " << scientific << setprecision(4) << y << endl; if (fabs(y) < 1e-12 && fabs(x - x0) < 1e-12) break; x0 = x; x = x - y/f1(x); } cout << "\nThe solution to sin x - 0.5x = 0\n" "(to twelve decimals) is " << fixed << setprecision(12) << x << ".\n"; cout << "Number of iteration steps: " << showpos << i << endl; if (i == 100) cout << "Result unreliable (no convergence in 100 steps).\n"; return 0; } Exercise 4.14 /* p04_04.cpp: Ladder against wall. The ladder is the hypotenuse BC of triangle ABC. AB is on the floor and AC on the wall. BC is equal to the given ladder length L and touches the square ADEF (with sides equal to 1) at E, where D is on AB and F on AC. We make use of the variables a = BE and b = EC, and we will solve this problem both analytically and iteratively. (Obviously, only one solution is actually required.) The functions 'analytical' and 'iterative' below take the ladder length L as an argument and return the desired distance x = DB. */ #include #include #include using namespace std; void error() { cout << "Enter a reasonable value of L " "(between 2.83 and 1000000)\n"; exit(1); } double analytical(double L) { /* With alpha = angle DBE = angle FEC we have cos alpha = 1/b and sin alpha = 1/a. It follows that 1/(b*b) + 1/(a*a) = 1. Furthemore, a + b = L. Therefore a*a + b*b = a*a*b*b and a*a + 2ab + b*b = L*L. Combining these equations, we find a*a*b*b + 2ab = L*L. We set p = ab, obtaining p*p + 2p - L*L = 0. Solving this for p, we find p = sqrt(L*L + 1) - 1. From ab = p and a + b = L it follows that b*b - Lb + p = 0, so b = (L + sqrt(L*L - 4p))/2. Since x : a = 1 : b we have x = a/b = ab/(b*b) = p/(b*b). */ double p, b, L2 = L * L, Discr; p = sqrt(L2 + 1) - 1; Discr = L2 - 4 * p; if (Discr < 0) error(); b = (L + sqrt(L2 - 4 * p))/2; return p/(b * b); // = x } double iterative(double L, int &i) { const double eps = 1e-12; double xLow = eps, xHigh = 1, x, a, b, delta, h; // x will be between xLow and xHigh. for (i=0; i<1000; ++i) { x = (xLow + xHigh)/2; a = sqrt(x * x + 1); // Pythagoras (triangle DBE) b = a/x; // Because x : a = 1 : b h = a + b; // Hypotenuse delta = h - L; // Should be zero if (delta > eps) xLow = x; // x was too small else if (delta < -eps) xHigh = x; // x was too large else break; // fabs(delta) <= eps } if (i == 1000) error(); return x; } int main() { double L; int n; cout << "Ladder length L: "; cin >> L; cout << "Computed analytically: x = " << analytical(L) << endl; cout << "Computed iteratively: x = " << iterative(L, n) << endl; cout << "(computed in " << n << " iteration steps)\n"; return 0; } Exercise 4.15 // p04_15.cpp: Compute e, using a series. #include #include using namespace std; #define NR_OF_TERMS_REQUIRED 1 #if NR_OF_TERMS_REQUIRED int iGlobal; // Only for debug version #endif double exp1(double x) { const double eps = 1e-10; double s, t; bool neg = (x < 0); if (neg) x = -x; s = 1 + x; t = x; int i = 2; // Already 2 terms computed; t = most recently used term // In the following loop we start with the third // term, t = x * x / (2!) do s += (t *= x/i++); while (t > eps); // i = number of used terms of the series #if NR_OF_TERMS_REQUIRED iGlobal = i; // Only for debug version #endif return neg ? 1/s : s; // exp(-x) = 1/exp(x) } int main() { double x; cout << "Enter x: "; cin >> x; cout << "Standard library function: exp(x) = " << exp(x) << endl; cout << "Our own function exp1(x) = " << exp1(x) << endl; #if NR_OF_TERMS_REQUIRED cout << iGlobal << " terms of series computed" << endl; #endif return 0; } Exercise 4.16 // p04_16.cpp: Continued fraction. #include #include using namespace std; long gcd(long a, long b) // Greatest Common Divisor { return b ? gcd(b, a % b) : a; // See Exercise 4.7 } int main() { long a0, b0, a, b, d, q, r; cout << "Enter the positive integers a and b (a < b)\n" "of fraction a/b:\n"; cin >> a0 >> b0; if (a0 <= 0 || b0 <= 0) { cout << "a and b must be positive.\n"; exit(1); } if (a0 >= b0) { cout << "a must be less than b.\n"; exit(1); } if ((d = gcd(a0, b0)) == 1) { a = a0; b = b0; } else { a = a0/d; b = b0/d; cout << "Instead of " << a0 << "/" << b0 << ", we take " << a << "/" << b << endl; } cout << "The following sequence represents the " "desired continuous fraction:\n"; while (a) { q = b / a; r = b % a; cout << q << " "; b = a; a = r; } cout << endl; return 0; } Exercise 4.17 // p04_17.cpp: For the given sequence a1, a2, ..., an, // we look for pairs (i, j) (i < j) so that // gcd(ai, aj) = 1. #include #include #include using namespace std; int gcd(int a, int b) // see also Exercise 4.7 { return b ? gcd(b, a % b) : a; } int main() { int n, i, j; int *a; cout << "Enter n, followed by a sequence of n integers: "; cin >> n; a = new int[n+1]; for (i=1; i<=n; ++i) cin >> a[i]; cout << "Pairs (i, j) (where i and j range from 1 to n),\n" "followed by ai and aj so that gcd(ai, aj) = 1, :\n"; for (i=1; i<=n; ++i) for (j=i+1; j<=n; ++j) if (gcd(a[i], a[j]) == 1) cout << setw(3) << i << " " << setw(3) << j << " " << "==>" << setw(5) << a[i] << " " << setw(5) << a[j] << endl; delete[]a; return 0; } Exercise 4.18 // p04_18.cpp: Fibonacci sequence. #include #include using namespace std; int main() { long previousF = 0, F = 1, h; const long double pi = 3.14159265358979323846; unsigned n, i; cout << "Enter the (nonnegative) integer n: "; cin >> n; if (n == 0) {cout << "F(0) = 0\n"; return 0;} if (n == 1) {cout << "F(1) = 1\n"; return 0;} for (i=1; i=0; --i) cout << s[i]; cout << endl; return 0; } Exercise 5.2 // p05_02.cpp: The same as Exercise 5.1 but without // type 'string'. #include #include using namespace std; int main() { const int N = 200; char s[N]; cout << "Enter a line of text:\n"; int i = N - 1; s[i] = '\0'; char ch; while (cin.get(ch), ch != '\n' && i > 0) s[--i] = ch; if (ch != '\n') // Happens only if length >= N cout << "Input string truncated.\n"; cout << "Reverse:\n"; cout << s + i << endl; // or: &s[i] return 0; } Exercise 5.3 // p05_03.cpp: Determine if two strings are each other's // reverse. #include #include using namespace std; bool reverse(const string &s, const string &t) { int ns = s.length(), i=0, j; if (ns != t.length()) return false; for (j=ns-1; j>=0; --j) if (s[i++] != t[j]) return false; return true; } int main() { string a = "ABC", b = "CBA", c = "ABCD", d = "abc"; cout << "reverse(" << a << ", " << b << ") = " << reverse(a, b) << endl; cout << "reverse(" << b << ", " << c << ") = " << reverse(b, c) << endl; cout << "reverse(" << b << ", " << d << ") = " << reverse(b, d) << endl; return 0; } Exercise 5.4 // p05_04.cpp: For each element in a sequence of length 20, // count how many smaller elements follow. #include using namespace std; int main() { const int N = 20; int a[N], n, x, i, j; cout << "Enter " << N << " integers:\n"; for (i=0; i> a[i]; for (i=0; i using namespace std; int main() { const int n = 10; float a[n], b[n]; int i, j; cout << "Enter two nondecreasing sequences of " << n << " integers:\n"; for (i=0; i> a[i]; for (j=0; j> b[j]; i = j = 0; while (i < n && j < n) cout << (a[i] < b[j] ? a[i++] : b[j++]) << " "; while (i < n) cout << a[i++] << " "; while (j < n) cout << b[j++] << " "; cout << endl; return 0; } Exercise 5.6 // p05_06.cpp: Sorting three program arguments. #include #include using namespace std; void sort2(char* &p, char* &q) { if (strcmp(p, q) > 0) { char* t = p; p = q; q = t; } } int main(int argc, char *argv[]) { if (argc == 4) { sort2(argv[1], argv[2]); sort2(argv[2], argv[3]); sort2(argv[1], argv[3]); for (int i=1; i<4; ++i) cout << argv[i] << endl; } else cout << "Supply three program arguments!\n"; return 0; } Exercise 5.7 // p05_07.cpp: Longest of several input lines. #include #include using namespace std; int main() { string s, max; cout << "Enter some text lines, the last one followed by\n" << "a line consisting only of a period (.):\n"; getline(cin, max); for (;;) { getline(cin, s); if (s == ".") break; if (s.length() > max.length()) max = s; } cout << "The longest line read is:\n" << max << endl; return 0; } Exercise 5.8 // p05_08.cpp: Pascal's triangle. #include #include using namespace std; int main() { const int MAX = 12; int a[MAX+1], i, j, n; cout << "Enter n (at most " << MAX << "): "; cin >> n; if (n > MAX) { cout << "Too large.\n"; return 1; } for (i=0; i<=n; ++i) { a[i] = 1; for (j=i-1; j>=1; --j) a[j] = a[j-1] + a[j]; for (j=(n-i)*3; j>0; --j) cout << ' '; for (j=0; j<=i; ++j) cout << setw(6) << a[j]; cout << endl; } return 0; } Exercise 5.9 a. D b. DEFG c. CDEFG d. C e. 0 f. CDEFG g. A Exercise 6.1 // p06_01.cpp: Names and ages of ten people. #include #include #include using namespace std; struct Person {string name; int age;}; int main() { const int n = 10; Person a[n]; int i, sum = 0; cout << "For each of " << n << " persons, enter name (without\n" "any internal space characters) and age:\n"; for (i=0; i> a[i].name >> a[i].age; sum += a[i].age; } double average = sum / static_cast(n); cout << "\nAverage age: " << fixed << setw(5) << setprecision(1) << average << endl << endl; cout << "Name Age Age deviation\n"; for (i=0; i using namespace std; class String { public: String(char *s = NULL) // Default constructor { if (s == NULL) { len = 0; ptr = NULL; } else { len = 0; while (s[len] != '\0') ++len; ptr = new char[len]; for (int i=0; i #include using namespace std; class Dates { public: Dates() { int c[13]; // Calendar c[1] = 31; c[2] = 28; c[3] = 31; c[4] = 30; c[5] = 31; c[6] = 30; c[7] = 31; c[8] = 31; c[9] = 30; c[10]= 31; c[11]= 30; c[12]= 31; preceding[0] = 0; for (int i=1; i<12; ++i) preceding[i+1] = preceding[i] + c[i]; } void read2() { cout << "Enter two dates, each coded as a 4-digit " "integer (mmdd):\n"; absDayNr1 = dayNr(); absDayNr2 = dayNr(); } int difference(){return absDayNr2 - absDayNr1;} private: int absDayNr1, absDayNr2, preceding[13]; int dayNr() { int mmdd, mm, dd; cin >> dec >> mmdd; // 'dec' required; otherwise 0101 would be octal dd = mmdd % 100; mm = mmdd / 100; if (dd < 1 || dd > 31 || mm < 1 || mm > 12) { cout << "Invalid input.\n"; exit(1); } return preceding[mm] + dd; } }; int main() { Dates dd; dd.read2(); cout << "The second date falls " << dd.difference() << " after the first.\n"; return 0; } Exercise 6.4 // p06_04.cpp: All sequences of length n, with each element // ranging from a given lower bound to a given // upper bound. #include #include using namespace std; class VarNestedLoops { public: VarNestedLoops(int n) { r = new int[n]; l = new int[n]; u = new int[n]; this->n = n; } ~VarNestedLoops(){delete[]r; delete[]l; delete[]u;} void readBounds() { cout << "Enter n input lines, each with two integers, the\n" "lower and upper bounds li and ui, where li <= ui:\n"; for (int i=0; i> l[i] >> u[i]; } void generate(int k = 0) { if (k == n) display_r(); else for (r[k] = l[k]; r[k] <= u[k]; ++r[k]) generate(k+1); } private: int n, *r, *l, *u; void display_r() { for (int i=0; i> n; VarNestedLoops v(n); v.readBounds(); cout << "Result:\n"; v.generate(); return 0; } Exercise 6.5 // p06_05.cpp: A class 'verylongint'. // Preliminary version, based on pointers // (see also Exercise 9.9). #include #include using namespace std; class verylongint { public: verylongint(const string &s = "0") { int n = s.length(); nph = len = 0; ptr = NULL; reserve(n); for (int i=0; i y.len) return y * x; // Now x.len <= y.len if (x.len == 0) return verylongint(); verylongint p(y), prod; for (int i=0; i=0; --i) os << x.ptr[i]; return os; } private: void check() { while (len > 0 && ptr[len-1] == 0) --len; } void tentimes() { if (len > 1 || ptr[0] != 0) { reserve(len + 1); for (int i=len; i>0; --i) ptr[i] = ptr[i-1]; ++len; ptr[0] = 0; } } verylongint mul(int k)const// k = 0, 1, ..., 9 { verylongint y; if (k == 0 || len == 1 && ptr[0] == 0) return verylongint(); int d = 0; for (int i=0; i using namespace std; class BitSequences { public: BitSequences(int n) { this->n = n; r = new int[n]; } ~BitSequences(){delete[]r;} void generate(int k = 0) { // This function will print the fixed // values r[0], r[1], ..., r[k-1], // followed by all possible values of // r[k], r[k+1], ..., r[n-1]. // To achieve this, both for r[k] = 0 (if allowed) // and for r[k] = 1, // we recursively call generate(k + 1): if (k == n) printn(); else { if (k == 0 || r[k-1] != 0) { r[k] = 0; generate(k+1); } r[k] = 1; generate(k+1); } } private: int n, *r; void printn() { for (int i=0; i> n; BitSequences b(n); b.generate(); return 0; } Exercise 7.1 // p07_01.cpp: Function template to display three values // in ascending order. #include #include using namespace std; template void displaysorted3(T p, T q, T r) { T t; if (q < p){t = p; p = q; q = t;} if (r < q){t = q; q = r; r = t;} // Now r is the largest if (p < q) cout << p << " " << q; else cout << q << " " << p; cout << " " << r << endl; } int main() { double x = 3.4, y = 7.5, z = 1.2; string s("John"), t("Peter"), u("Nicholas"); displaysorted3(x, y, z); displaysorted3(s, t, u); return 0; } Exercise 7.2 // p07_02.cpp: Class 'row' of Section 6.9 turned // into a template. #include #include using namespace std; template class row { public: row(int n = 3); // Default constructor row(const row &r); // Copy constructor ~row(); // Destructor row &operator=(const row &r); // Copy assignment operator void printrow(const string &str)const; private: T *ptr; int len; }; template row::row(int n) // default = 3 not repeated here { len = n; ptr = new T[n]; for (int i=0; i row::row(const row &r) // Copy constructor { len = r.len; ptr = new T[len]; for (int i=0; i row::~row() {delete[] ptr;} // Destructor template row &row::operator=(const row &r) // Copy assignment operator { if (&r != this) { delete[] ptr; len = r.len; ptr = new T[len]; for (int i=0; i void row::printrow(const string &str)const { cout << str; for (int i=0; i ri, si(5), ti(si); ri = si; ri.printrow("ri: "); si.printrow("si: "); ti.printrow("ti: "); row rd, sd(5), td(sd); rd = sd; rd.printrow("rd: "); sd.printrow("sd: "); td.printrow("td: "); return 0; } Exercise 8.1 // p08_01.cpp: Input of integers with exception handling. #include using namespace std; class NumInputFailure { }; void readInt(int &x) { cin >> x; if (cin.fail()) throw NumInputFailure(); } int main() { int k, n; cout << "Enter two integers:\n"; try { readInt(k); cout << "Read: k = " << k << endl; readInt(n); cout << "Read: n = " << n << endl; } catch (NumInputFailure) { cout << "Could not read a number.\n"; exit(1); } return 0; } Exercise 8.2 // p08_02.cpp: Exception handling dealing with negative // argument of square-root function. #include #include using namespace std; class NegArg {}; double sqrt1(double x) { if (x < 0) throw NegArg(); return sqrt(x); } int main() { try { cout << sqrt1(0.04) << endl; // Output: 0.2 cout << sqrt1(-0.03) << endl; // Throws a NegArg exception cout << sqrt1(0.09) << endl; // No output due to previous statement } catch(NegArg) { cout << "Negative argument used for sqrt1.\n"; } return 0; } Exercise 9.1 // p09_01: Read an integer and display its digits in // the number system with base b, where b (at // least 2 and at most 10) is also read from // the keyboard. // Use a stack to store these digits. #include #include using namespace std; int main() { cout << "Enter an integer: "; long x; cin >> x; cout << "Enter the base of the desired number system (2-10): "; int b; cin >> b; if (b < 2 || b > 10){cout << "Invalid.\n"; return 1;} stack s; if (x == 0){cout << "0\n"; return 0;} if (x < 0){cout << "-"; x = -x;} while (x) { s.push(x % b); x /= b; } while (!s.empty()) { cout << s.top(); s.pop(); } cout << endl; return 0; } Exercise 9.2 // p09_02.cpp: Pairs of gears. // The q-values will appear in ascending order. #include #include #include #include using namespace std; using namespace std::rel_ops; struct line { bool operator<(const line &y)const { return q < y.q; } bool operator==(const line &y)const { return q == y.q; } int a, b; float q; }; int main() { int a, b, s, k = 0; float q; int z[]={30, 35, 37, 40, 45, 47, 50, 52, 55, 57, 60, 65, 68, 70, 75, 78, 80, 82, 85, 86, 87, 90, 95, 97, 99}; const int n = sizeof(z)/sizeof(z[0]); line pairs[n * n / 2 + 1]; // In total, there are n * n ordered pairs (a, b). // Among these, there are as many with q < 1 as there // are with q > 1. Only those with q < 1 are acceptable, // which means that the number of output lines will // not exceed n * n / 2 + 1. This explains the size of // the above array pairs, in which we store triples // (a, b, q) before we sort them: for (int i=0; i= 130 && s <= 140) { q = float(a)/b; if (q >= 0.5) // q < 1 is true because z[i] < z[j] { pairs[k].a = a; pairs[k].b = b; pairs[k++].q = q; } } } sort(pairs, pairs + n); cout << "The following " << k << " pairs satify the requirements:\n"; cout << " a b q\n"; for (int h=0; h #include #include #include using namespace std; int main() { deque D; int n; cout << "How many modification of the deque do you want? "; cin >> n; cout << "i Deque contents\n"; srand(time(NULL)); for (int i=0; i #include #include #include #include #include using namespace std; typedef set settype; typedef map maptype; bool wordread(string &word, int &linenr) { char ch; // scan for first letter: for (;;) { cin.get(ch); if (isalpha(ch)) break; if (ch == '\n') { linenr++; cin.get(ch); if (ch == '.') return false; cin.putback(ch); } } word = ""; // scan for first non-alpha character: do { word += tolower(ch); cin.get(ch); } while (isalpha(ch)); cin.putback(ch); // ch may be '\n' return true; } int main() { maptype M; maptype::iterator im; settype::iterator is, isbegin, isend; string word; int linenr = 1; cout << "Enter lines of text, " "terminated by a line containing\n" "only a period (.):\n"; while (wordread(word, linenr)) { im = M.find(word); if (im == M.end()) im = M.insert(maptype::value_type(word, settype())).first; (*im).second.insert(linenr); } cout << "\nWords and line numbers:\n"; for (im = M.begin(); im != M.end(); im++) { cout << setiosflags(ios::left) << setw(15) << (*im).first.c_str(); isbegin = (*im).second.begin(); isend = (*im).second.end(); for (is=isbegin; is != isend; is++) cout << " " << *is; cout << endl; } return 0; } Exercise 9.5 // p09_05.cpp: Read a sequece a of integers, followed by a // nonnumeric character. Skip this character and // then read another sequence, b, of equal length. // Build yet another sequence, c, again of the same // length, such that each element a[i] is equal to // the larger of a[i] and b[i]. #include #include #include using namespace std; int main() { vector a, b, c; int x; char ch; cout << "Enter two sequences (of integers) of equal\n" "length, separated by a nonnumeric character:\n"; while (cin >> x) a.push_back(x); cin.clear(); cin.get(ch); int n = a.size(), i; for (i=0; i> x; b.push_back(x); c.push_back(max(a[i], b[i])); // Only vector a is really useful here, while // the use of b and c can be easily avoided. } cout << "Pairwise maximum values c[i]:\n"; for (i=0; i #include #include using namespace std; int main() { set S1, S2, unionOfSets, intersection; cout << "Enter two lines of text:\n"; char ch; while (cin.get(ch), ch != '\n') S1.insert(ch); while (cin.get(ch), ch != '\n') S2.insert(ch); set_union(S1.begin(), S1.end(), S2.begin(), S2.end(), inserter(unionOfSets, unionOfSets.end())); set_intersection(S1.begin(), S1.end(), S2.begin(), S2.end(), inserter(intersection, intersection.end())); cout << "Characters, just entered, in alphabetic order:\n"; set::iterator i; for (i=unionOfSets.begin(); i!=unionOfSets.end(); ++i) cout << *i; cout << "\nCharacters occurring on both input lines:\n"; for (i=intersection.begin(); i!=intersection.end(); ++i) cout << *i; cout << endl; return 0; } Exercise 9.7 // p09_07.cpp. Sieve of Eratosthenes // (computing all prime numbers under 100000). #include #include #include using namespace std; int main() { int i; long k, maximum, howmany = 0; const int n = 100000, sqrtn = 317; // 316 * 316 = 99856 and 317 * 317 = 100489. // If you change n, you should make sqrtn equal to the // square root of n, rounded up to an integer. bitset b; // b[i] = 1 means: the integer i has a nontrivial divisor // (i = 2, 3, 4, ...) for (i=2; i #include using namespace std; typedef list::iterator iter; iter step(list &L, iter i) { iter i1 = ++i; return (i1 == L.end() ? L.begin() : i1); } int main() { int n, k, j; cout << "Initially, n persons are placed in a circle.\n" "All persons in the circle are visited in turn\n" "and each time the kth person is removed.\n" "Enter n and k: "; cin >> n >> k; list L; for (j=1; j<=n; ++j) L.push_back(j); iter i1 = L.end(), i; --i1; for (j=0; j #include #include using namespace std; class verylongint { public: verylongint(const string &s = "0") { for (int i = s.size()-1; i>=0; --i) v.push_back(s[i] - '0'); check(); } verylongint(const verylongint &x) { v = x.v; } verylongint(long x) { v.push_back(x % 10); for (;;) { x /= 10; if (x == 0) break; int r = x % 10; v.push_back(r); } check(); } verylongint &operator=(const verylongint &x) { v = x.v; return *this; } friend verylongint operator+(const verylongint &x, const verylongint &y) { verylongint s; int d = 0; for (int i=0; i y.v.size()) return y * x; // length of x <= length of y if (x.v.size() == 0) return verylongint(); verylongint p=y, prod; for (int i=0; i=0; --i) os << x.v[i]; os << endl; return os; } private: void check() { while (v.size() > 0 && v[v.size()-1] == 0) v.pop_back(); } void tentimes() { v.insert(v.begin(), 0); } verylongint mul(int k)// k = 0, 1, ..., 9 { verylongint y; if (k == 0 || v.size() == 0) return verylongint(); int d = 0; for (int i=0; i v; }; verylongint kwad(verylongint x) { return x * x; } int main() { verylongint x(30000), y(20000), y1(y), z = "123456789012345", result; result = x * x * x * x + y * y * y * y1 + z; cout << result << endl; return 0; } Exercise 10.1 // p10.01.cpp: Display the longest line of a given text file. #include #include #include using namespace std; int main() { string filename, s, longest = ""; int maxlen = 0; cout << "Name of input file: "; cin >> filename; ifstream in(filename.c_str()); if (in.fail()) { cout << "Cannot open input file\n"; return 1; } while (getline(in, s, '\n'), !in.fail()) if (s.length() > maxlen) { longest = s; maxlen = s.length(); } cout << "Longest line read:\n"; cout << longest << endl; return 0; } Exercise 10.2 // p10.02.cpp: Counting words (separated by space characters) // in an input file. #include #include #include #include using namespace std; int main() { set words; string filename, s, longest = ""; int maxlen = 0; cout << "Name of input file: "; cin >> filename; ifstream in(filename.c_str()); if (in.fail()) { cout << "Cannot open input file\n"; return 1; } while (in >> s) words.insert(s); cout << "There are " << words.size() << " distinct words in the input file.\n\n"; // The following is not really required in the exercise: for (set::iterator i=words.begin(); i != words.end(); ++i) cout << *i << endl; return 0; } Exercise 10.3 // p10.03.cpp: Make sure that every comma is followed by a // space character. #include #include #include #include using namespace std; int main() { string sIn, sOut; char ch; ifstream in; ofstream out; cout << "Name of input file: "; cin >> sIn; in.open(sIn.c_str()); if (in.fail()) { cout << "Cannot open input file.\n"; exit(1); } cout << "Name of output file: "; cin >> sOut; out.open(sOut.c_str()); if (out.fail()) { cout << "Cannot open output file.\n"; exit(1); } while (in.get(ch)) { out.put(ch); if (ch == ',') { in.get(ch); if (ch != ' ') out.put(' '); in.putback(ch); } } cout << "Ready.\n"; return 0; } Exercise 10.4 // p10.04.cpp: Merging two sorted files of integers. #include #include #include #include #include using namespace std; int main() { int n=0, x1, x2, y; ifstream in1, in2; ofstream out; cout << "Enter the names of two input files and\n" << "of one output file:\n"; string sIn1, sIn2, sOut; cin >> sIn1; in1.open(sIn1.c_str()); if (in1.fail()) { cout << "Cannot open first input file.\n"; exit(1); } cin >> sIn2; in2.open(sIn2.c_str()); if (in2.fail()) { cout << "Cannot open second input file.\n"; exit(1); } cin >> sOut; out.open(sOut.c_str()); if (in1.fail()) { cout << "Cannot open output file.\n"; exit(1); } in1 >> x1; in2 >> x2; while (!in1.fail() && !in2.fail()) { if (x1 <= x2) { y = x1; in1 >> x1; } else { y = x2; in2 >> x2; } out << setw(5) << y << (++n % 10 == 0 ? "\n" : " "); } while (!in1.fail()) { out << setw(5) << x1 << (++n % 10 == 0 ? "\n" : " "); in1 >> x1; } while (!in2.fail()) { out << setw(5) << x2 << (++n % 10 == 0 ? "\n" : " "); in2 >> x2; } cout << "Ready.\n"; return 0; } Exercise 10.5 // p10.05.cpp: Merging two sorted files of words. #include #include #include #include #include using namespace std; int main() { string x1, x2, y; ifstream in1, in2; ofstream out; cout << "Enter the names of two input files and\n" << "of one output file:\n"; string sIn1, sIn2, sOut; cin >> sIn1; in1.open(sIn1.c_str()); if (in1.fail()) { cout << "Cannot open first input file.\n"; exit(1); } cin >> sIn2; in2.open(sIn2.c_str()); if (in2.fail()) { cout << "Cannot open second input file.\n"; exit(1); } cin >> sOut; out.open(sOut.c_str()); if (in1.fail()) { cout << "Cannot open output file.\n"; exit(1); } in1 >> x1; in2 >> x2; while (!in1.fail() && !in2.fail()) { if (x1 <= x2) { y = x1; in1 >> x1; } else { y = x2; in2 >> x2; } out << y << endl; } while (!in1.fail()) { out << x1 << endl; in1 >> x1; } while (!in2.fail()) { out << x2 << endl; in2 >> x2; } cout << "Ready.\n"; return 0; } Exercise 10.6 // p10.06.cpp: Binary I/O and random access. #include #include #include #include using namespace std; int main() { char ch, ch1; string fname; fstream f; int x=0; long k, n; cout << "Name of input file: "; cin >> fname; f.open(fname.c_str(), ios_base::in | ios_base::out | ios_base::binary); if (f.fail()) { // The file does not exist. We will now create it: cout << "Enter the desired file length " "(number of integers): "; cin >> n; f.clear(); f.open(fname.c_str(), ios_base::out | ios_base::binary); if (f.fail()) { cout << "Cannot open output file.\n"; exit(1); } for (k=0; k(&x), sizeof(int)); cout << "The file now contains " << n << " zeros.\n" "Start the program again to modify the file.\n"; return 0; } // The file already exists. We will determine its length // and modify it. f.seekg(0, ios_base::end); n = f.tellg()/sizeof(int); cout << "The file accommodates " << n << " numbers of type int.\n"; for (;;) { cout << "Enter a position number k less than " << n << " or enter\n" "anything else to terminate the program: "; cin >> k; if (cin.fail() || k < 0 || k >= n) break; f.seekg(k * sizeof(int), ios_base::beg); f.read(reinterpret_cast(&x), sizeof(int)); cout << "This position contains " << x << endl; cout << "Do you want to change this value? (Y/N): "; cin >> ch; while (cin.get(ch1) && ch1 != '\n') ; // Skip the rest if (ch == 'Y' || ch == 'y') { cout << "New value: "; cin >> x; f.seekg(k * sizeof(int), ios_base::beg); f.write(reinterpret_cast(&x), sizeof(int)); } } return 0; } Exercise 10.7 // p10.07.cpp: From text file to (sorted) binary file. #include #include #include #include #include #include #include #include using namespace std; using namespace std::rel_ops; class rec { public: rec(const string &s = "", int i = 0) { strncpy(name, s.c_str(), 25); name[25] = '\0'; nr = i; } bool operator<(const rec &r)const { return strcmp(name, r.name) < 0; } bool operator==(const rec &r)const { return strcmp(name, r.name) == 0; } char *getName(){return name;} int getNr(){return nr;} private: char name[26]; int nr; }; int main() { string fNameIn, fNameOut, name; cout << "Name of input file: "; cin >> fNameIn; ifstream fIn(fNameIn.c_str()); if (fIn.fail()) { cout << "Cannot open input file."; exit(1); } cout << "Name of output file: "; cin >> fNameOut; ofstream fOut(fNameOut.c_str(), ios_base::binary); if (fOut.fail()) { cout << "Cannot open output file."; exit(1); } int i, n = 0; vector table; while (fIn >> name >> i) { table.push_back(rec(name, i)); ++n; } cout << n << " records read from input file.\n"; if (!fIn.eof()) { cout << "File contents incorrect.\n"; exit(1); } sort(table.begin(), table.end()); for (int k=0; k(&table[k]), sizeof(rec)); fOut.close(); // We now open the same file for input: ifstream fBin(fNameOut.c_str(), ios_base::binary); rec r; while (fBin.read(reinterpret_cast(&r), sizeof(rec))) { cout << setw(27) << left << r.getName() << right << setw(8) << r.getNr() << endl; } return 0; } Exercise 10.8 // p10_08.cpp: Read the numbers // n, a1, a2, ..., an, b1, b2, ..., bn, // in that order, from an input file, and // compute the sum of all values max(ai, bi) // (i = 1, 2, ..., n). #include #include #include #include using namespace std; void error(const char *s) { cout << s << endl; exit(1); } int main() { cout << "Input file name: "; string fname; cin >> fname; ifstream in(fname.c_str()); if (in.fail()) error("Cannot open input file.\n"); int i, n; double *a, sum = 0, x; in >> n; a = new double[n]; for (i=0; i> a[i]; if (in.fail()) error("Too few numbers in input file"); } for (i=0; i> x; if (in.fail()) error("Too few numbers in input file"); sum += (a[i] > x ? a[i] : x); } cout << "The sum of all max(ai, bi) values is " << sum << endl; delete[] a; return 0; } Exercise 10.9 // p10_09.cpp: Compute the coefficients a and b of the // regression line y = a + bx. #include #include #include using namespace std; int main() { int n = 0; double x, y, sx = 0, sx2 = 0, sy = 0, sxy = 0, D; cout << "Enter the name of an input file, which\n" << "contains pairs of numbers x, y, to be used\n" << "for linear regression: "; string fname; cin >> fname; ifstream in(fname.c_str()); if (in.fail()) { cout << "Cannot open input file.\n"; return 1; } while (in >> x >> y) { ++n; sx += x; sx2 += x * x; sy += y; sxy += x * y; } D = n * sx2 - sx * sx; if (D == 0) cout << "Incorrect input (determinant = 0)\n"; else { cout << "The regression line y = a + bx approximates the\n"; cout << "given points, where\n"; cout << "a = " << (sy * sx2 - sx * sxy)/D << endl; cout << "b = " << (n * sxy - sx * sy)/D << endl; } return 0; } Exercise 10.10 // p10_10.cpp: The name of a text file is // given as a program argument. This file contains // the integers k and n, followed by a table of // k rows and n columns. The table contains real // numbers and is read row by row. // This program computes the average of each column. #include #include #include using namespace std; void error(const char *s) { cout << s << endl; exit(1); } int main(int argc, char *argv[]) { if (argc != 2) error("File name as program argument. please."); ifstream f(argv[1]); if (!f) error("Cannot open input file."); int k, n, i, j; f >> k >> n; if (f.fail()) error("Cannot read k and n."); double x, *sum = new (double [n]); // Row of n column sums for (j=0; j> x; if (f.fail()) { cout << "k = " << k << " n = " << n << endl; error("Cannot read k x n numbers."); } sum[j] += x; } } f >> x; // This should fail! if (!f.eof()) error("More than k x n numbers in input file."); for (j=0; j #include #include using namespace std; class NumFile { public: NumFile() { okFlag = true; n = s = 0; string fname; cout << "Input file name: "; cin >> fname; fstream in(fname.c_str()); if (in.fail()) okFlag = false; else { for (;;) { int x; in >> x; if (in.fail()) { in.clear(); in.get(); // Try to read a single character if (in.eof()) break; } else { ++n; s += x; } } } } bool ok() {return okFlag;} int nr(){return n;} int sum(){return s;} private: bool okFlag; int n, s; }; int main() { NumFile nf; // Constructor does everything. if (nf.ok()) { cout << "The input file contains " << nf.nr() << " integers.\n"; cout << "Their sum is " << nf.sum() << endl; } else cout << "Cannot open input file.\n"; return 0; } Exercise 10.12 // p10_12.cpp: Concordance. #include #include #include #include #include #include #include using namespace std; typedef set settype; typedef map maptype; bool wordread(ifstream &ifstr, string &word, int &linenr) { char ch; // scan for first letter: for (;;) { ifstr.get(ch); if (ifstr.fail()) return false; if (isalpha(ch)) break; if (ch == '\n') ++linenr; } word = ""; // scan for first non-alpha character: do { word += tolower(ch); ifstr.get(ch); } while (!ifstr.fail() && isalpha(ch)); if (ifstr.fail()) return false; ifstr.putback(ch); // ch may be '\n' return true; } int main() { maptype M; maptype::iterator im; settype::iterator is, isbegin, isend; string inpfilename, word; ifstream ifstr; int linenr = 1; cout << "Enter name of input file: "; cin >> inpfilename; ifstr.open(inpfilename.c_str()); if (!ifstr) { cout << "Cannot open input file.\n"; exit(1); } while (wordread(ifstr, word, linenr)) { im = M.find(word); if (im == M.end()) im = M.insert(maptype::value_type(word, settype())).first; (*im).second.insert(linenr); } for (im = M.begin(); im != M.end(); ++im) { cout << left << setw(15) << (*im).first.c_str(); isbegin = (*im).second.begin(); isend = (*im).second.end(); for (is=isbegin; is != isend; ++is) cout << " " << setw(2) << *is; cout << endl; } return 0; } Exercise 10.13 // p10_13.cpp: A textfile and a word are given as program // arguments. When reading all lines of the // textfile, we display each line that contains // the given word. #include #include #include #include using namespace std; class FileWord { public: FileWord(const char *s) { in.open(s); if (in.fail()) { cout << "Cannot open input file.\n"; exit(1); } } void readlines(const char *w) // We will look for w { string str; while (getline(in, str), !in.fail()) { if (str.find(w) != string::npos) cout << str << endl; } } private: ifstream in; }; int main(int argc, char *argv[]) { if (argc < 3) { cout << "Supply file name and word as " "program arguments.\n"; return 1; } FileWord fs(argv[1]); fs.readlines(argv[2]); return 0; } Exercise 10.14 // p10_14.cpp: For an input file (genenerated if it // does not exist), we count how many bits are in // position 0, in position 1, ..., in position 7 // of each byte. #include #include #include using namespace std; int main() { ifstream in; int ch, count[8]={0}, i; in.open("element.dat", ios_base::binary); if (in.fail()) { cout << "Because there is no input file element.dat,\n" "an example of such a file will be generated.\n"; in.close(); in.clear(); ofstream out("element.dat", ios_base::binary); if (out.fail()) { cout << "Cannot open file 'element.dat' for " "output either.\n"; return 1; } out.put('\x3E'); out.put('\xA2'); out.put('\x77'); out.close(); cout << "The file 'element.dat' now contains:\n" "0011 1110 (= hex 3E)\n" "1010 0010 (= hex A2)\n" "0111 0111 (= hex 77)\n"; in.open("element.dat", ios_base::binary); if (in.fail()) { cout << "Cannot open this file for input (strange).\n"; return 1; } } while ((ch = in.get()) != EOF) { for (i=0; i<8; i++) { count[i] += ch & 1; ch >>= 1; } } cout << "Count result (= bit frequencies):\n"; cout << "Count result:\n"; puts(" E0 E1 E2 E3 E4 E5 E6 E7"); for (i=0; i<8; i++) cout << setw(6) << count[i]; cout << endl; return 0; } Exercise 10.15 // p10_15.cpp: The longest and the second longest // lines of a given textfile are displayed. #include #include #include #include using namespace std; class InputLines { public: InputLines(const string &fname) { in.open(fname.c_str()); if (!in) { cout << "Cannot open input file.\n"; exit(1); } n = n1 = -1; } void readFile() { string s; int len; for (;;) { getline(in, s); if (in.fail()) break; len = s.length(); if (len > n){max1 = max; n1 = n; max = s; n = len;} else if (len < n && len > n1){max1 = s; n1 = len;} } } void showResults() { if (n1 == -1) { cout << "There were no two lines of different length.\n"; exit(1); } cout << "Longest line:\n" << max << endl; cout << "Second longest line:\n" << max1 << endl; } private: ifstream in; string max, max1; int n, n1; }; int main() { string fname; cout << "Input file name: "; cin >> fname; InputLines inputlines(fname); inputlines.readFile(); inputlines.showResults(); return 0; } Exercise 10.16 // p10_16.cpp Count how often a given (whole) word occurs // in an input file. Hyphenation is dealt with correctly. #include #include #include #include using namespace std; int readWord(string &buffer, ifstream &in) { int ch, n=0; // Skip any nonalphabetic text: while (ch = in.get(), ch != EOF && !isalpha(ch)) ; if (ch == EOF) return EOF; // Read a (possibly hypenated) word: buffer = ""; do { buffer += static_cast(tolower(ch)); ch = in.get(); if (ch == '-') { ch = in.get(); if (ch == '\n') ch = in.get(); } } while (isalpha(ch)); return buffer.length(); } int main() { string word, fname, buffer; int wordLength, len, count=0; cout << "Enter the word to be counted: "; cin >> word; wordLength = word.length(); cout << "Input file name: "; cin >> fname; ifstream in(fname.c_str()); if (in.fail()) { cout << "Cannot open input file.\n"; return 1; } for (;;) { len = readWord(buffer, in); if (len == EOF) break; if (len == wordLength && word == buffer) count++; } cout << "The given word occurs " << count << " times in the given file.\n"; return 0; } Exercise 10.17 // p10_17.cpp: Sets of words, read from two files, tested // for equality. #include #include #include #include using namespace std; int main() { string nameA, nameB; cout << "Enter name of first input file: "; cin >> nameA; ifstream inA(nameA.c_str()); if (inA.fail()) { cout << "Cannot open this file.\n"; return 1; } cout << "Enter name of second input file: "; cin >> nameB; ifstream inB(nameB.c_str()); if (inA.fail()) { cout << "Cannot open this file.\n"; return 1; } set A, B; string s; while (inA >> s) A.insert(s); while (inB >> s) B.insert(s); if (A == B) cout << "The files contain the same words.\n"; else cout << "The files do not contain the same words.\n"; return 0; } Exercise 10.18 // p10_18.cpp: Justification of text. #include #include #include #include #include using namespace std; class Words { public: Words(const char *fNameIn, const char *fNameOut) { in.open(fNameIn); if (!in) { cout << "Cannot open input file.\n"; exit(1); } out.open(fNameOut); if (!out) { cout << "Cannot open output file.\n"; exit(1); } } void askLineLength() { cout << "What is the desired line length? "; cin >> lineLength; } void readAndWrite() { vector wordList; string s; int cumLength = 0; int nWordsOnLine = 0; for (;;) { in >> s; if (in.fail()) break; int len = s.length(), nWords = wordList.size(); if (cumLength + nWords + len > lineLength) { // s cannot be added to current line, so write // all nWords words that are stored in wordList: if (nWords > 1) { // There are nWords - 1 word separators, each // taking at least one space character: int nRemaining = lineLength - cumLength - (nWords - 1), nOpenSpaces = nWords - 1, q = nRemaining / nOpenSpaces, r = nRemaining % nOpenSpaces; // nRemaining = q * nOpenSpaces + r // We rewrite this to show the number of extra // spaces (besides the one already taken // account of) between each two successive // words: // nRemaining = // (nOpenSpaces - r) * q + r * (q + 1) for (int j=0; j #include #include #include using namespace std; class SyntaxCheck { public: SyntaxCheck(const string &fname) { in.open(fname.c_str()); if (!in) { cout << "Cannot open input file.\n"; exit(1); } } void validSequence() { while (parentheses() || braces()) ; } void read(int ch0) { if (!trychar(ch0)) { cout << "Parentheses and braces do not match.\n"; exit(1); } } private: ifstream in; bool trychar(int ch0) { int ch; for (;;) { ch = in.peek(); if (ch == EOF || ch == '(' || ch == '{' || ch == ')' || ch == '}') break; in.get(); } // Everything has been skipped until ch is one // of the following five: EOF ( { } ). We now read // this if this is the desired character ch0: if (ch == ch0) { in.get(); return true; } return false; } bool parentheses() { if (trychar('(')) { validSequence(); read(')'); return true; } return false; } bool braces() { if (trychar('{')) { validSequence(); read('}'); return true; } return false; } }; int main() { string fname; cout << "Input file name: "; cin >> fname; SyntaxCheck check(fname); check.validSequence(); cout << "Input OK.\n"; return 0; } Exercise 10.20 // p10_20.cpp: Test comments and string literals. #include #include #include #include using namespace std; class CheckComment { public: CheckComment(const string &fname) { in.open(fname.c_str()); if (in.fail()) { cout << "Cannot open input file.\n"; exit(1); } } void check() { int ch; while ((ch = readChar()) != EOF) { if (ch == '/') CPPstyleComment() || CstyleComment(); else if (ch == '"' || ch == '\'') StringOrCharConst(ch); else if (ch == '*' && in.peek() == '/') error("unmatched */"); } cout << "\nThe file is correct with respect to comment.\n"; } private: string line, oldLine; ifstream in; int readChar() { int ch; ch = in.get(); cout << static_cast(ch); if (ch == '\n') { oldLine = line; line = ""; } else if (ch != EOF) line += ch; return ch; } void error(const string &s) { cout << "\nError: " << s << endl; exit(1); } bool CPPstyleComment() // Slash (/) read; if possible, read // second slash and rest of comment: { int ch = in.peek(); if (ch == EOF) return true; if (ch == '/') { do { ch = readChar(); } while (ch != '\n' && ch != EOF); return true; } return false; } bool CstyleComment() // Slash (/) read; if possible, read // asterisk and all text until '*/' { int ch = in.peek(); if (ch == EOF) return true; if (ch == '*') { readChar(); // Now '/*' has been read for (;;) { ch = readChar(); if (ch == EOF) error("unmatched /*"); if (ch == '*') { ch = in.peek(); if (ch == EOF) error("unmatched /*"); if (ch == '/') { readChar(); // Now */ has been read return true; } } } } return false; } void StringOrCharConst(char chr) // chr (= single or double quote) has been read { int ch; for (;;) { ch = readChar(); if (ch == '\n' || ch == EOF) error("string or char literal does not " "end correctly."); if (ch == '\\') { ch = readChar(); if (ch == EOF) error("EOF in literal after \\"); } else if (ch == chr) return; } } }; int main() { string fname; cout << "Enter name of a C++ program file: "; cin >> fname; CheckComment cmnt(fname); cmnt.check(); return 0; } Exercise 11.1 // p11.01.cpp: Demonstration of the functions // isalpha, isxdigit, and toupper. #include #include using namespace std; int main() { char ch; cout << "Enter a character: "; cin >> ch; if (isalpha(ch)) cout << "This is a letter.\n"; else cout << "This is not a letter.\n"; if (isxdigit(ch)) cout << "This is a hexadecimal digit.\n"; else cout << "This is not a hexadecimal digit.\n"; char ch1 = toupper(ch); cout << "Result of applying toupper: " << ch1 << endl; return 0; } Exercise 11.2 // p11_02.cpp: Demonstrating C-style output. #include int main() { printf(" x f(x)\n\n"); for (int i=20; i<=40; i+=2) { double x = i/10.0; printf("%3.1f %15.10f\n", x, x * x + x + 1/x); } return 0; } Exercise 11.3 // p11.03.cpp: Random three-letter sequences. #include #include #include #include using namespace std; string gen3() { string s; for (int k=0; k<3; ++k) { int j = rand() % 26; char ch = 'A' + j; s += ch; } return s; } int main() { // To obtain different sequences each time we // run the program, we start as follows: srand(time(NULL)); for (int i=0; i<50; ++i) { cout << gen3(); cout << (i % 10 == 9 ? '\n' : ' '); } return 0; } Exercise 11.4 // p11.04.cpp: A simple problem with NDEBUG. #define NDEBUG #include // This program solves the problem. // This version terminates normally because // NDEBUG is defined BEFORE the inclusion of // the header assert.h. // In contrast, NDEBUG has no effect if we // define it AFTER that header, as was done // in the exercise. int main() { assert(false); return 0; }