8.2.3. name_box.cpp, Version 1

Review

The name_box1 program is the first of three versions exploring strings and their operations. The programs and the problems they solve are similar, but each demonstrates a different string implementation or different data input. The first version demonstrates C-strings reading input from the console.

+-----------------+
|Cranston Q. Snort|
+-----------------+
The name-box problem.

 

The name-box1 algorithm. The purpose of the first name-box example is to demonstrate C-strings and a few of their operations. When a program draws a two-dimensional picture on the console using characters (e.g., the pyramid drawn in Chapter 3), it must start at the top-left corner, draw left to right, and top to bottom. The algorithm solving the first version of the name-box problem is straightforward, consisting of a sequence of program steps:
  1. Define a C-string long enough to store a name of unknown length; it is not necessary to initialize it.
  2. Input a string of unknown length, allowing for embedded spaces.
  3. Draw the top of the box:
    1. Draw the top left box corner.
    2. Determine how many dashes to draw for the top of the box and draw it.
    3. Draw the top right box corner and a newline.
  4. Print the left side of the box.
  5. Print the user's name.
  6. Print the right side of the box and a newline.
  7. Draw the bottom of the box, repeating steps 3(a) through 3(c) but at the bottom of the box.

I recommend that software developers learning to solve problems with programs, develop them incrementally. The first increment includes four fundamental tasks: First, outline the program. At a minimum, the outline includes the necessary headers and defines the main function with its return statement. The second task is to define a minimal set of variables. Third, the program performs the first input operation. And lastly, the program echoes the just-read data to the console; this last step may require writing code that is unnecessary for the completed program, and is discarded as development progresses.

Attempt 1Attempt 2
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char	name[100];

	cout << "Please enter your name: ";
	cin >> name;
	cout << name;

	return 0;
}
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char	name[100];

	cout << "Please enter your name: ";
	cin.getline(name, 100);
	cout << name;

	return 0;
}
Incremental development: Attempts 1 and 2. Incremental program development begins with a minimal program that tests and validates the variables and I/O operations. This approach has two advantages:
  1. It is easier to localize and correct syntax, logical, and runtime errors when the amount of untested code is small.
  2. It helps identify "obviously correct" input code that is, in fact, incorrect. Errors in input operations are often subtle, leading programmers to fruitlessly focus on subsequent, complex operations without finding the error.
Attempt 1 compiles without error. Testing the input with Cranston Q. Snort, the program displays Cranston on the console. The review, problem statement, and algorithm all hinted at this problem: the extractor, >>, doesn't read past whitespace characters. However, "real-world" problems are generally less helpful. The review also suggested the correct input function: getline. Attempt 2 demonstrates the correct output, completing the first two incremental attempts.

 

Attempt 3Attempt 4
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char	name[100];

	cout << "Please enter your name: ";
	cin.getline(name, 100);

	for (size_t i = 0; i < strlen(name); i++)
		cout << "-";
	cout << endl << name;

	return 0;
}
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char	name[100];

	cout << "Please enter your name: ";
	cin.getline(name, 100);

	cout << "+";
	for (size_t i = 0; i < strlen(name); i++)
		cout << "-";
	cout << "+" << endl;
	cout << "|" << name << "|" <<;

	return 0;
}
-----------------
Cranston Q. Snort
+-----------------+
|Cranston Q. Snort|
Incremental development: Attempts 3 and 4. Attempt 2 completes the algorithmic steps 1 and 2 listed in Figure 2, leaving step 3 as the next outstanding task. It's clear from Figure 1 that the number of dashes required to draw the top of the box is equal to the number of characters in the entered name, including the embedded spaces. Therefore, attempt 3 uses a for-loop to draw a line of dashes and prints the name below it for comparison. The for-loop doesn't print a newline, printing the dashes on a single line, but requires the program to print one before the name. The output, shown below the code, validates the 3.b part of the algorithm.

To complete algorithmic step 3, attempt 4 prints the corners of the box, one at each end of the top line. It moves printing the newline up from the name to the right-hand corner. To maintain the character alignment, the attempt also completes steps 4, 5, and 6, printing the name surrounded by the left and right sides of the box. The output, shown below the code, validates the partial program.

 

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char	name[100];				// step 1

	cout << "Please enter your name: ";
	cin.getline(name, 100);				// step 2

	cout << "+";					// step 3.a
	for (size_t i = 0; i < strlen(name); i++)	// step 3.b
		cout << "-";
	cout << "+" << endl;				// step 3.c

	cout << "|" << name << "|" << endl;		// steps 4, 5, and 6

	cout << "+";					// step 7.a
	for (size_t i = 0; i < strlen(name); i++)	// step 7.b
		cout << "-";
	cout << "+" << endl;				// step 7.c

	return 0;
}
name_box1.cpp. Recognizing that the bottom of the box is identical to its top allows us to complete the program. The step comments correspond to the algorithm described in Figure 2.