8.2.5. name_box.cpp, Version 2

Time: 00:12:47 | Download: Large Small | Streaming
Review

Please review the following concepts as needed to understand better the second version of the name-box problem:

Like the first version of the name_box program, the second version continues to display a user's name inside a box drawn with ASCII characters. But for the second version, we change how users enter their names: the second version takes the user's name from the command line. Although the second program's output is the same as the first, taking the input from the command line requires us to solve some additional, challenging sub-problems.

name_box2CranstonQ.Snort
NameSpacesargc
Cranston 0 2
CranstonSnort 1 3
CranstonQ.Snort 2 4
(a)(b)
Entering the user's name on the command line.
  1. A command line is a C-string that names a program, the command, that a user wants the system to run, name_box2 in this example. Some programs allow users to add a space-separated list of arguments following the command name - the user's name in this example (red boxes represent spaces). Our program is not responsible for processing the initial command line. Instead, part of the operating system called the command line processor reads the command line and parses or separates it into its elements, discarding the spaces as it does so. The command line processor places each element into the argv array, which is one of the parameters of the main function that starts every C++ program. So, our program begins with the program's and the user's names in argv:
    • argv[0] = name_box2
    • argv[1] = Cranston
    • argv[2] = Q.
    • argv[3] = Snort
  2. Armed with the above information, we're now ready to design an algorithm to print the user's name on the console. As described in part (a), we know that the command line processor provides the command line arguments to our program as a parameter named argv. It also passes another parameter named argc, the number of command-line arguments. The command-line processor includes the name of the command or program in argv and counts it in argc, but we don't include the command name or the space between it and the first argument in the Table (b). Most of our effort goes to printing the sides of the box and all the users' names.
    1. In program 1, we could print the sides of the box and the name with a single statement, but in this version, the user's full name consists of multiple strings saved in an array. So, we'll use a for-loop controlled by argc.
    2. In this version of the problem, the constraint of not allowing spaces before or after the name becomes significant. The constraint, coupled with the loop used to print all the user's names, is another example of the fence post problem. Our program will use one of the fence post problem solutions.
    3. To draw the dashes for the top and bottom of the box, we need to know the total number of characters in the user's name. Users may enter any number of names, and the command line processor will discard the spaces between them. So, we'll need to adjust the number of dashes for each removed space. We need to generalize the three examples in Table (b), which shows the relationship between the number of names and the number of spaces the processor removed.
The following program implements the solution outlined here. The second program follows the above solution but makes a few changes.
#include <iostream>
#include <cstring>
using namespace std;

int main(int argc, char* argv[])		// (a)
{
	if (argc == 1)				// (b)
		return 0;

	int	count = 0;			// (c)

	for (int i = 1; i < argc; i++)		// (d)
		count += strlen(argv[i]);
	count += argc - 2;			// (e)

	cout << "+";				// (f)
	for (int i = 0; i < count; i++)		// (g)
		cout << "-";
	cout << "+" << endl;			// (h)

	cout << "|";				// (i)
	for (int i = 1; i < argc - 1; i++)	// (j)
		cout << argv[i] << " ";
	cout << argv[argc - 1] << "|" << endl;	// (k)

	cout << "+";				// (f)
	for (int i = 0; i < count; i++)		// (g)
		cout << "-";
	cout << "+" << endl;			// (h)

	return 0;
}
name_box2.cpp (version 1). The operating system passes information into a program through two argv (short for argument vector where "vector" is a synonym for array) and argc (short for argument count). Steps (i, j, and k) implement one fence-post-problem solution, eliminating a space between the name and the box's right side. This version prints the names without saving them.
  1. Add the command line arguments to main (argc must come before argv)
  2. End the program if there aren't names in argv. We could also use return 0;, but only in main.
  3. Create an accumulator to count the total number of characters in the user's name
  4. Count the letters in each name of the user's full name; starting with 1, skip the name of the program in argv[0]
  5. Adjust count to account for the removed spaces: subtract 1 from argc as part of the fence post problem solution, and subtract another 1 because argc includes the name of the program in the count
  6. Draw the top and bottom left corner of the box
  7. Draw the top and bottom of the box
  8. Draw the top and bottom right corner of the box, and enter a new line to end the line
  9. Draw the left side of the box
  10. Print all of the user's names, except the last one, followed by a space
  11. Print the user's last name, the right side of the box, and a new line to end the printed line
int main(int argc, char* argv[])			// (a)
{
	if (argc == 1)					// (b)
		exit(0);

	char	name[100] = "";				// (c)

	for (int i = 1; i < argc - 1; i++)		// (d)
	{
		strcat_s(name, 100, argv[i]);
		strcat_s(name, 100, " ");
	}
	strcat_s(name, 100, argv[argc - 1]);		// (e)

	//strcpy_s(name, 100, argv[1]);			// (f)
	//for (int i = 2; i < argc; i++)		// (g)
	//{
	//	strcat_s(name, 100, " ");
	//	strcat_s(name, 100, argv[i]);
	//}

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

	cout << "|" << name << "|" << endl;		// (k)

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

	return 0;
}
name_box2.cpp (version 2). This solution creates and initializes a local character array or C-string for the name. It builds the name before printing it to the console. The program demonstrates two versions of the fence-post-problem solution. Parts (d) and (e) treat the last "fence post" (name) as a special case, moving the concatenation function call outside and below the loop. Parts () and (g) (commented out) treat the first "fence post" (name) as a special case, moving the concatenation function call outside and above the loop.
  1. Add the command line arguments to main (argc must come before argv).
  2. End the program if there aren't names in argv. We could also use return 0;, but only in main.
  3. Create a C-string accumulator; it must be initialized to an empty string for the first fence-post-problem solution.
  4. Concatenate all the names in argv together into a singe C-string named name. Starting the loop at 1 skips the name of the program in argv[0]; ending the loop at argc-1 skips the last name. During the first iteration of the loop, name is empty, so the first strcat_s function call copies argv[1] to name. The second strcat_s call adds a space between names.
  5. Concatenates the last name to name without adding a space.
  6. An alternate solution: copies the first name in argv[1] into name. The program doesn't need to initialize name to empty for this version.
  7. Concatenates a space and then the rest of the names in argv to name.
  8. Draw the upper left corner of the box
  9. Draw the top of the box
  10. prints the top and bottom right-hand corners, moving the cursor to the next line.
  11. Draws the left side of the box, prints the user's full name, saved in name, draws the right side of the box, and ends the line.

Command Line Arguments In Visual Studio

  1. Select "Project" from the main menu OR in the Solution Explorer, right-click the project name
  2. Select "project name Properties" (at the bottom of the popup menu; project name is the name you used when you created the project)
  3. Locate "Configuration Properties" (on the left); if needed, click the hollow arrow to expand the Configuration Properties list and select "Debugging
  4. Find the "Command Arguments" in the center of the window. It may be hard to see, but there is an input box to the right of the "Command Arguments" label - click inside of that box to select it
  5. Enter the arguments separated by spaces (do not include the program name)
  6. Press "OK
Entering command line arguments in Visual Studio. It is possible to run a program requiring command line input directly from Visual Studio.