• No se han encontrado resultados

4.3. Diseño de interfaz(gráfica)

4.3.1. Descripción de las interfaces

The easiest way to generate formatted output in C++ is to use the << operator. This operator is called the insertion operator because it has the effect of inserting data into a stream. The operand on the left is the output stream; the operand on the right is the data you want to insert into that stream. The << operator is overloaded so that the operand on the right can be a string or any primitive value. If this operand is not a string, the << operator converts it to string form before sending it to the output stream. This feature makes it easy to display the values of variables, because C++ handles the output conversion automatically.

C++ makes generating output even more convenient by having the << operator return the value of the stream. This design decision makes it possible to chain several output operations together, as you have already seen in several examples in this text. Suppose, for example, that you want to display the value of the variable

total on an output line that begins with some text telling the user what that value

represents. In C++, you would start with the expression

cout << "The total is "

which copies the characters in the string "Thetotalis " to the cout stream. To insert the decimal representation of the value in total, all you need to do is chain on another instance of the << operator like this:

cout << "The total is " << total

This expression has the intended effect because the << operator returns the stream. Thus, the left operand of the second << is simply cout, which means that the value

of total is displayed there. Finally, you can signal the end of an output line by inserting the value endl using yet another instance of the << operator:

cout << "The total is " << total << endl;

If total contains the value 42, the resulting output would look like this on the

console:

Even though you have been using statements like this one since the very beginning, knowing that the << operator propagates the value of cout through the expression as it moves along the chain of insertion operators may help you to appreciate how output works in C++.

Although it seems as if it might be a simple string constant, the endl value used to signal the end of an output line is actually an example of something that C++ calls a manipulator, which is just a fancy name for a special type of value used to control formatting. The C++ libraries export a variety of manipulators that you can use to specify the format for output values, the most common of which appear in Table 4-1. For the most part, these manipulators are automatically available when you include the <iostream> library. The only exceptions are the manipulators that take parameters, such as setw(n), setprecision(digits), and setfill(ch). To use these manipulators, you need to include <iomanip> as well.

Manipulators typically have the effect of setting properties of the output stream in a way that changes the formatting of subsequent output. As the individual entries in Table 4-1 make clear, some manipulators are transient, which means that they affect only the next data value that appears. Most, however, are persistent, which means that they take effect for that stream until they are explicitly changed.

One of the most common applications of manipulators involves specifying a field width to support tabular output. Suppose, for example, that you want to

rewrite the PowersOfTwo program from Chapter 1 so that the numbers in the table

are aligned in columns. To do so, all you would need to do is add the appropriate manipulators in the output statement, which will look something like this:

cout << right << setw(2) << i

<< setw(8) << raiseToPower(2, i) << endl;

Total The total is 42

Output manipulator table

T A B L E 4 - 1 Output manipulators

endl Inserts an end-of-line sequence into the output stream and ensures that the

characters in the output are written to the destination stream.

setw(n) Sets the width of the next field to n characters. If the value requires fewer

characters, extra space is added to fill the field. This property is transient,

which means that it affects only the next value inserted into the stream. setprecision(digits) Sets the precision for the stream to digits. The interpretation of the

precision specification depends on other stream settings. If you have set the mode to fixed or scientific, digits specifies the number of digits after the decimal point. If neither of these modes are set, digits indicates the number of significant digits, irrespective of where those digits appear. This property is persistent, which means that it remains in effect for the stream until it is explicitly changed.

setfill(ch) Sets the fill character for the stream to ch. By default, spaces are added to

the output if additional characters are necessary to fill the field width established by setw. Calling setfill makes it possible to change that character. For example, calling setfill('0') means that fields will be filled with zeroes. This property is persistent.

left Specifies that fields should be aligned on the left, which means that any

fill characters are inserted after the value. This property is persistent.

right Specifies that fields should be aligned on the right, which means that any

fill characters are inserted before the value. This property is persistent.

fixed Specifies that subsequent floating-point output should be displayed in full,

without using scientific notation. By default, floating point values are displayed in the most compact form. This property is persistent.

scientific Specifies that subsequent floating-point output should always appear in

scientific notation. This property is persistent. showpoint

noshowpoint

These manipulators control whether a decimal point should appear in floating-point numbers, even if the value is equal to an integer. You can use showpoint to force inclusion of the decimal point and later restore the default behavior with noshowpoint. This property is persistent. showpos

noshowpos

These manipulators control whether a plus sign is printed before positive values. By default, positive values are printed without a sign. This property is persistent.

uppercase nouppercase

These manipulators control the case of any letters generated as part of numeric conversion, such as the E in scientific notation. By default, these characters appear in lower case. This property is persistent.

boolalpha noboolalpha

These manipulators control the format of bool values, which are ordinarily displayed (for historical reasons) using their internal numeric representation. Using the boolalpha manipulator causes them to appear instead as true and false. This property is persistent.

This statement prints the value of i in a field of width 2 and the value of the function raiseToPower(2,i) in a field of width 8. Both fields are justified on the right because the effect of the right manipulator is persistent. If you used this line to display the powers of two between 0 and 16, the output would look like this:

Understanding the use of the setprecision(digits) manipulator is complicated by the fact that the interpretation of the argument depends on other mode settings for the stream. In the absence of any specifications to the contrary, C++ represents floating-point numbers using either decimal or scientific notation, choosing the representation that is more compact. The fact that C++ can choose either of these representations makes sense if all you care about is seeing the value. If, however, you want to control the output more precisely, you need to indicate which of these formats you would like C++ to use. The fixed manipulator specifies that floating-point values should always appear as a string of digits with a decimal point in the appropriate position. Conversely, the scientific manipulator specifies that values should always use the programming form of scientific notation in which the exponent is separated from the value by the letter E. Each of these formats interprets the setprecision manipulator in a slightly different way, which makes it harder to provide a concise description of how setprecision works.

As is often the case in programming, one of the best ways to understand how some highly detailed aspect of a library works is to write simple test programs that

allow you to see what happens on the screen. The PrecisionExample program in

Figure 4-1 shows how three constants—the mathematical constant π, the speed of light in meters per second, and the fine-structure constant that characterizes the strength of electrical interaction—appear using different floating-point modes and precision. The output of the program is shown in Figure 4-2.

PowersOfTwo

This program lists powers of two.

Enter exponent limit: 16

0 1 1 2 2 4 3 8 4 16 5 32 6 64 7 128 8 256 9 512 10 1024 11 2048 12 4096 13 8192 14 16384 15 32768 16 65536

Program listing for PrecisionExample.

F I G U R E 4 - 1 Program to explore the behavior of setprecision /*

* File: PrecisionExample.cpp * ---

* This program demonstrates various options for floating-point output * by displaying three different constants (pi, the speed of light in * meters/second, and the fine-structure constant). These constants * are chosen because they illustrate a range of exponent scales. */ #include <iostream> #include <iomanip> #include <cmath> using namespace std; /* Constants */ const double PI = 3.14159265358979323846; const double SPEED_OF_LIGHT = 2.99792458E+8; const double FINE_STRUCTURE = 7.2573525E-3;

/* Function prototypes */

void printPrecisionTable();

/* Main program */

int main() {

cout << uppercase << right;

cout << "Default format:" << endl << endl; printPrecisionTable();

cout << endl << "Fixed format:" << fixed << endl << endl; printPrecisionTable();

cout << endl << "Scientific format:" << scientific << endl << endl; printPrecisionTable(); return 0; } /* * Function: printPrecisionTable * ---

* Generates a simple precision table for the current cout settings. */

void printPrecisionTable() {

cout << " prec | pi | speed of light | fine-structure" << endl; cout << "---+---+---+---" << endl; for (int prec = 0; prec <= 6; prec += 2) {

cout << setw(4) << prec << " |";

cout << " " << setw(12) << setprecision(prec) << PI << " |";

cout << " " << setw(16) << setprecision(prec) << SPEED_OF_LIGHT << " |"; cout << " " << setw(14) << setprecision(prec) << FINE_STRUCTURE << endl; }

Documento similar