Exercise 4-3
What happens if we rewrite the previous program to allow values up to but not including 1000 but neglect to change the arguments to setw? Rewrite the program to be more robust in the face of changes that allow i to grow without adjusting the setw arguments.
Solution
Though there are many ways to solve this problem, below is the solution strategy that I use, with the aim of enhanced flexibility:
- Obtain the asymmetric range [m,n) from the user with the condition of n > m. In other words, m is the startNumber. n – 1 is the endNumber.
- Compute the number of elements within this asymmetric range as n – m. This is equivalent to the number of loops required (or number of rows to output).
- Create a function getStreamWidth that will be used to automatically compute the maximum width required for column 1 (the list of numbers), and column 2 (the square of column 1). This function is capable of dealing with both negative and non-negative input values.
- Have a for loop to output column 1 and 2 using the corresponding column stream widths computed upfront (step 3 above).
The Project
I have decided to partition the program as follows – for practice sake.
C++ Source Files
- main.cpp – this is the first program that is run during the implementation phase.
- getStreamWidth.cpp – contains all functions relating to obtaining the stream widths.
C++ Header Files
- getStreamWidth.h– declare the functions as defined in getStreamWidth.cpp.
This diagram below shows what the Code::Block Management Tree look like after successful creation of these files.
The actual content of the source and header files are documented in the following sections.
Source Files
main.cpp
#include <iostream> #include <ios> #include <iomanip> #include <algorithm> #include "getStreamWidth.h" using std::cout; // <iostream> using std::cin; // <iostream> using std::endl; // <iostream> using std::streamsize; // <ios> using std::setw; // <iomanip> using std::max; // <algorithm> int main() { #include <iostream> #include <ios> #include <iomanip> #include <algorithm> #include "getStreamWidth.h" using std::cout; // <iostream> using std::cin; // <iostream> using std::endl; // <iostream> using std::streamsize; // <ios> using std::setw; // <iomanip> using std::max; // <algorithm> int main() { // display program intro message cout << "***********************************************************\n" << "*** This program computes the square of the numbers ***\n" << "*** in the asymmetric range [m,n). ***\n" << "*** (Limitation: please ensure n > m) ***\n" << "*** e.g. [3,7) contains elements 3, 4, 5, 6 (but not 7) ***\n" << "***********************************************************"; cout << endl; // ask user to supply m cout << "Enter m: "; int m; cin >> m; // ask user to supply n cout << "Enter n: "; int n; cin >> n; // ensure m and n are input correctly. If not, exit program. if (n <= m) { cout << "Please make sure n > m"; return 1; } // initialise value const int startNumber = m; // first output integer const int endNumber = n - 1; // last output integer const int numLoops = n - m; // number of rows to output // find the maxwidth for column 1 and 2 const streamsize col1Width = max(getStreamWidth(startNumber), getStreamWidth(endNumber)); const streamsize col2Width = max(getStreamWidth(startNumber * startNumber), getStreamWidth(endNumber * endNumber)); // display a summary cout << "Asymmetric range: [" << m << "," << n << ")" << endl; cout << "Number of rows = " << numLoops << endl; cout << "Column 1 width = " << col1Width << " | Column 2 width = " << col2Width << endl; // get ready to print report int y = startNumber; for (int i = 0; i != numLoops; ++i) { cout << setw(col1Width) << y << setw(col2Width) << (y * y) << setw(0) << endl; ++y; } return 0; }
getStreamWidth.cpp
#include <ios> using std::streamsize; // return the required streamsize to fit a particular integer number streamsize getStreamWidth(int number) { streamsize numDigits; // initialise numDigits and number depending on whether value is positive / negative. // If negative, require at least 2 spaces to fit the leading empty space string and the negative sign // If positive, require at least 1 space to fit the leading empty space string if (number < 0) { numDigits = 2; number *= -1; } else numDigits = 1; // numDigits is the number of divisions required to make number approaches zero (plus leading space and sign) // i.e. this is equivalent to the total stream width required while (number != 0) { ++numDigits; number /= 10; } return numDigits; }
Header Files
getStreamWidth.h
#ifndef GUARD_GETSTREAMWIDTH_H #define GUARD_GETSTREAMWIDTH_H std::streamsize getStreamWidth(int number); #endif // GUARD_GETSTREAMWIDTH_H
Test Results
Asymmetric range [-3, 4)
*********************************************************** *** This program computes the square of the numbers *** *** in the asymmetric range [m,n). *** *** (Limitation: please ensure n > m) *** *** e.g. [3,7) contains elements 3, 4, 5, 6 (but not 7) *** *********************************************************** Enter m: -3 Enter n: 4 Asymmetric range: [-3,4) Number of rows = 7 Column 1 width = 3 | Column 2 width = 2 -3 9 -2 4 -1 1 0 0 1 1 2 4 3 9
Asymmetric range [995,1006)
*********************************************************** *** This program computes the square of the numbers *** *** in the asymmetric range [m,n). *** *** (Limitation: please ensure n > m) *** *** e.g. [3,7) contains elements 3, 4, 5, 6 (but not 7) *** *********************************************************** Enter m: 995 Enter n: 1006 Asymmetric range: [995,1006) Number of rows = 11 Column 1 width = 5 | Column 2 width = 8 995 990025 996 992016 997 994009 998 996004 999 998001 1000 1000000 1001 1002001 1002 1004004 1003 1006009 1004 1008016 1005 1010025
Asymmetric range [-1005,-996)
*********************************************************** *** This program computes the square of the numbers *** *** in the asymmetric range [m,n). *** *** (Limitation: please ensure n > m) *** *** e.g. [3,7) contains elements 3, 4, 5, 6 (but not 7) *** *********************************************************** Enter m: -1005 Enter n: -996 Asymmetric range: [-1005,-996) Number of rows = 9 Column 1 width = 6 | Column 2 width = 8 -1005 1010025 -1004 1008016 -1003 1006009 -1002 1004004 -1001 1002001 -1000 1000000 -999 998001 -998 996004 -997 994009
Asymmetric range [0,1000)
*********************************************************** *** This program computes the square of the numbers *** *** in the asymmetric range [m,n). *** *** (Limitation: please ensure n > m) *** *** e.g. [3,7) contains elements 3, 4, 5, 6 (but not 7) *** *********************************************************** Enter m: 0 Enter n: 1000 Asymmetric range: [0,1000 Number of rows = 1000 Column 1 width = 4 Column 2 width = 7 0 0 1 1 2 4 ... 993 986049 994 988036 995 990025 996 992016 997 994009 998 996004 999 998001