13 cout << \
14 << \15
16 for ( int year = 1; year <= 10; year++ ) {
17 amount = principal * pow{ 1.0 + rate, year ); 10 cout << setw( 4 ) << year
19 << setiosflags( ios::fixed I ios::showpoint ) 20 << setw( 21 ) << setprecision( 2 ) 21 << amount << endl; 22 } 23 24 25 }
输出结果:
Year Amount on deposic 1 1050.00 2 1102.50 3 1157.62 4 1215.51 5 1276.28 6 1340.10 7 1407.10 8 1477.46 9 1551.33 10 1628.89
图 6.21 用for结构计算复利
这个程序必须包括math.h才能编译。函数pow要求两个double参数,注意year是个整数。math.h文件中的信息告诉编译器将year值转换为临时double类型之后再调用函数。这些信息放在pow的函数原型(function prototype)中。第3章将介绍函数原型并总结pow函数和其他数学库函数。
程序中将变量amount、principal和rate声明为double类型,这是为了简单起见,因为我们要涉及存款数额的小数部分,要采用数值中允许小数的类型。但是,这可能造成麻烦,下面简单介绍用float和double表示数值时可能出现的问题(假设打印时用setprecision(2)):机器中存放的两个float类型的值可能是14.234(打印14.23)和18.673(打印18.67)。这两个值相加时,内部和为32.907,打印32.91。结果输出如下:
14.23 + 18.67 ----------- 32.91
但这个加式的和应为32.90。
-96-
输出语句:
cout< 用参数化流操纵算于setw、setiosflags和setprecision指定的格式打印变量year和amount的值。调用selw(4)指定下一个值的输出域宽(field width)为4,即至少用4个字符位置打印这个值。如果输出的值宽度少于4个字符位,则该值默认在输出域中右对齐(ishljustl^ed),如果输出的值宽度大于4个字符,则该值将输出域宽扩大到能放下这个值为止。调用setiosflag(ios::left)可以指定输出的值为左对齐(1eft justified)。 上述输出中的其余格式表示变量amount打印成带小数点的定点值(用setiosflags(ios::fixed | ios::showpoint)指定),在输出域的21个字符位中右对齐(用setw(21)指定),小数点后面为两位(用setprecision(2)指定)。 注意计算1.0+rate作为pow函数的参数,包含在for语句体中。事实上,这个计算产生的结果在每次循环时相同,因此是重复计算(是一种浪费)。 6.15 switch多项选择结构 前面介绍了if单项选择结构和if/else双项选择结构。有时算法中包含一系列判断,用一个变量或表达式测试每个可能的常量值,并相应采取不同操作。C++提供的switch多项选择结构可以进行这种判断。 switch结构包括一系列case标记和一个可选default情况。图6.22中的程序用switch计算学生考试的每一级人数。 1 // Fig. 2.22:fig02 22.cpp 2 // Counting letter grades 3 #include 5 int main() 6 { 7 int grade, // one grade 8 aCount = 0, // number of A's 9 bCount = 0, // number of B's 10 cCount = O, // number of C's 11 dCount = 0, // number of D's 12 fCount = 0; // number of F's 13 14 cout << \ 15 << \16 17 while ( ( grade = cin.get() ) != EOF ) { -97- 18 19 switch ( grade ) { // switch nested in while 20 21 case 'A': // grade was uppercase a 22 case 'a': // or lowercase a 23 ++aCount; 24 break; // necessary to exit switch 25 26 case 'B': // grade was uppercase B 27 case 'b': // or lowercase b 28 ++bCount; 29 break; 30 31 case 'C': // grade was uppercase C 32 case 'c': // or lowercase c 33 ++cCount; 34 break; 35 36 case 'D': // grade was uppercase D 37 case 'd': // or lowercase d 38 ++dCount; 39 break; 40 41 case 'F': // grade was uppercase F 42 case 'f': // or lowercase f 43 ++fCount; 44 break; 45 46 case '\\n': // ignore newlines, 47 case '\\t': // tabs, 48 case ' ': // and spaces in input 49 break; 50 51 default: // catch all other characters 52 cout << \53 54 << \55 break; // optional 56 } 57 } 58 cout << \59 \ 60 << \61 << \ -98- 62 << \ 63 << \64 65 return 0; 66 } 输出结果: Enter the letter grades. Enter the EOF character to end input. A B C C A D F C E Incorrect letter grade entered. Enter a new grade. D A B Totals for each letter grade are: A: 3 B: 2 C: 3 D: 2 F: 1 图 6.22 使用switch举例 程序中,用户输入一个班代表成绩的字母。在while首部中: while( (grade=cin.get()) !=EOF) 首先执行参数化赋值(grade=cin.get())。cin.get()函数从键盘读取一个字符,并将这个字符存放在整型变量grade中。cin.get()中使用的圆点符号将在第6章中介绍。字符通常存放在char类型的变量中,但是,C++的一个重要特性是可以用任何整数数据类型存放字符,因为它们在计算机中表示为1个字节的整数。这样,我们根据使用情况,可以把把字符当作整数或字符。例如,下列语句: cout << \ character(\ has the value \ << static_cast -99- The character (a) has the value 97 整数97是计算机中该字符的数字表示。如今许多计算机都使用ASCII(AmericanStandardCodefor lnformationInterehange,美国标准信息交换码)字符集(character set),其中97表示小写字母“a”。附录中列出了ASCII字符及其十进制值的列表。 赋值语句的整个值为等号左边变量指定的值。这样,赋值语句grade=cin.get()的值等于cin.get()返回的值,赋给变量grade。赋值语句可以用于同时初始化多个变量。例如: a = b = c = 0; 首先进行赋值c=o(因为:运算符从右向左结合),然后将c=0的值赋给变量b(为0),最后将b=(c=0)的值赋给变量a(也是0)。程序中,赋值语句grade=cin.get()的值与EOF值(表示文件结束的符号)比较。我们用EOF(通常取值为-1)作为标记值。用户输入一个系统识别的组合键,表示文件结束,没有更多要输入的数据。EOF是 用户通过键盘输入成绩。按Enter(或Return)键时,cin.get()函数一次读取一个字符。如果输入的字符不是文件结束符,则进入switch结构。关键字switch后面是括号中的变量名grade,称为控制表达式(controlling expression)。控制表达式的值与每个case标记比较。假设用户输入成绩c,则c自动与switch中的每个case比较。如果找到匹配的(case'C:'),则执行该case语句。对于字母C的case语句中.cCount加1,并用break语句立即退出switch结构。注意,与其他控制结构不同的是,有多个语句的case不必放在花括号中。 break语句使程序控制转到switch结构后面的第一条语句。break语句使switch结构中的其他case不会一起运行。如果switch结构中不用break语句,则每次结构中发现匹配时,执行所有余下case中的语句(这个特性在几个case要完成相同操作时有用,见图2.22的程序)。如果找不到匹配,则执行default case并打印一个错误消息。 每个case有一个或几个操作。switch结构与其他结构不同,多个语句的case不必放在花括号中。图6.23显示了一般的swish多项选择结构(每个case用一个break语句)的流程图。 从流程图中可以看出,case末尾的每个break语句使控制立即退出switch结构。注意,流程图(除了小圆框和流程之外)也只能包含矩形框和菱形框。这是我们强调的操作/判断编程模型。程序员的任务就是根据算法需要用堆栈和嵌套两种方法组合其他几种控制结构,然后填入算法所要的操作和判断,从而生成程序。嵌套控制结构很常见,但程序中很少出现嵌套swilch结构。 在图6.22中的switch结构中,第46到第49行: case '\\n': case '\\t': case ' ' : break; 使程序跳过换行符、制表符和空白字符。一次读取一个字符可能造成一些问题。要让程序读取字符,就要按键盘上的Enter键将字符发送到计算机中,在要处理的字符后面输入换行符。这个换行符通常需要特殊处理,才能使程序正确工作。通过在switch结构中包含case语句,可以防止在每次输入中遇到换行符、制表符或空格时default case打印错误消息。 注意几个标号列在一起时(如图6.22中的case'D':case 'd':)表示每case发生一组相同的操 -100-