程序清单6-10演示了如何使用switch 和break来让用户选择简单菜单。该程序使用showmenu()函数显示一组选项,然后使用switch语句,根据用户的反应执行相应的操作。
注意:有些硬件/操作系统组合不会将(程序清单6.10的 case 1 中使用的)转义序列\a解释为振铃。
程序清单switch.cpp
//switch.cpp -- using the switch statement
#include
using namespace std;
void showmenu(); //function prototypes
void report();
void comfort();
int main() {
showmenu();
int choice;
cin >> choice;
while (choice != 5)
{
switch(choice)
{
case 1: cout << "\a\n";
break;
case 2: report();
break;
case 3: cout << "The boss was in all day.\n";
break;
case 4: comfort();
break;
default: cout << "That's not a choice.\n";
}
showmenu();
cin >> choice;
}
cout << "Bye!\n";
return 0;
}
void showmenu()
{
cout << "Please enter 1,2,3,4,or 5:\n"
"1) alarm 2) report\n"
"3) alibe 4) comfort\n"
"5) quit\n";
}
void report()
{
cout << "It's been an excellent week for business.\n"
"Sales are up 120%.Expenses are down 35%.\n";
}
void comfort()
{
cout << "Your employees think you are the finest CEO\n"
"in the industry.The board of directors think\n"
"you are the finest CEO in the industry.\n";
}
下面是程序的运行情况:
Please enter 1,2,3,4,or 5:
1) alarm 2) report
3) alibi 4) comfort
5) quit
4
Your employees think you are the finest CEO
in the industry.The board of directors think
you are the finest CEO in the industry.
Please enter 1,2,3,4,or 5:
1) alarm 2) report
3) alibi 4) comfort
5) quit
2
It's been an excellent week for business.
Sales are up 120%.Expenses are down 35%.
Please enter 1,2,3,4,or 5:
1) alarm 2) report
3) alibi 4) comfort
5) quit
6
That's not a choice.
Please enter 1,2,3,4,or 5:
1) alarm 2) report
3) alibi 4) comfort
5) quit
5
Bye!
当用户输入了5时,while循环结束。输入1到4将执行switch列表中相应的操作,输入6将执行默认语句。
为了让这上程序正确运行,输入必须是整数。例如,如果输入一个字母,输入语句将失效。导致循环不断运行,直到您终止程序。为应对不按指示办事的用户,最好使用字符输入。
如前所述,该程序需要break语句来确保只执行switch语句中的特定部分。为检查情况是否如此,可以删除程序清单6.10中的break语句,然后看看其运行情况。例如,读者将发现,输入2后将执行case 标签为2,3,4 和default中的所有语句。C++之所以这样,是由于这种行为很有用。例如,它使得使用多个标签很简单。例如,假设重新编写程序清单6.10,使用字符(而不是整数)作为菜单选项和switch标签,则可以为大写标签和小写标签提供相同的语句。
while (choice != 'Q' && choice != 'q')
{
switch (choice)
{
case 'a':
case 'A': cout << "\a\n";
break;
case 'r':
case 'R':report();
break;
case 'l':
case 'L':cout << "The boss was in all day.\n";
break;
case 'c':
case 'C':comfort();
break;
default: cout << "That's not a choice.\n";
}
showmenu();
cin >> choice;
由于case 'a' 后面没有break语句,因此程序将接着执行下一行----case 'A' 后面的语句。
程序清单6.11使用enum定义了一组相关的常量,然后在switch语句中使用这些常量。通常,cin无法识别枚举类型(它不知道程序员是如何定义它们的),因此该程序要求用户选择选项时输入一个整数,当switch语句将int值和枚举量标签进行比较是地,将枚举量提升为int。另外,在while循环测试条件中,也会将枚举量提升为int类型。
程序清单6.11 enum.cpp
//enum.cpp --using enum
#include
//create named constants for 0 - 6
enum {red,orange,yellow,green,blue,violet,indigo};
int main()
{
using namespace std;
cout << "Enter color code (0-6): ";
int code;
cin >> code;
while (code >= red && code <= indigo)
{
switch (code)
{
case red : cout << "Her lips were red.\n"; break;
case orange : cout << "Her hair was orange.\n"; break;
case yellow : cout << "Her shoes was yellow.\n"; break;
case green : cout << "Her nails were green.\n"; break;
case blue : cout << " Her sweatsuit was blue.\n"; break;
case violet : cout << "Her eyes were violet.\n"; break;
case indigo : cout << "Her mood was indigo.\n"; break;
}
cout << "Enter color code(0-6):";
cin >> code;
}
cout << "Bye\n";
return 0;
}
下面是程序输出:
Enter color code (0-6): 3
Her nails were green.
Enter color code(0-6):5
Her eyes were violet.
Enter color code(0-6):2
Her shoes was yellow.
Enter color code(0-6):8
Bye
6.6 break 和continue语句
break和continue语句都使程序能够路过部分代码。可以在switch语句或任何循环中使用break语句,使程序跳到switch或循环后面的语句片执行。continue语句用于循环中,让程序跳过循环中余下的代码,并开始新一轮循环。
程序清单6.12演示了这两条语句是如何工作的。该程序让用户输入一行文本。循环将回显每个字符,如果该字符为句点,则使用break结束循环。这表明,要吧在某种条件为true时,使用break来结束循环。
接下来,程序计算空格数,但不计算其他字符。当字符不为空格时,循环使用continue语句跳过计数部分。
//jump.cpp -- using continue and break
#include
const int ArSize = 80;
int main(){
using namespace std;
char line[ArSize];
int spaces = 0;
cout << "Enter a line of text:\n";
cin.get(line,ArSize);
cout << "Complete line:\n" << line << endl;
cout << "Line through first period:\n";
for (int i = 0; line[i] != '\n'; i++)
{
cout << line[i]; //display character
if (line[i] == '.')//quit if it's a perid
{
break;
}
if(line[i] != ' ') //skip rest of loop
continue;
spaces++;
}
cout << "\n" << spaces << " spaces\n";
cout << "Done.\n";
return 0;
}
下在则该程序的运行情况:
Enter a line of text:
Let's do lunch today. you can pay!
Complete line:
Let's do lunch today. you can pay!
Line through first period:
Let's do lunch today.
3 spaces
Done.
程序说明
虽然continue语句导致该程序跳过循环体的剩余部分,但不会跳过循环的更新表达式,在for循环中continue语句使程序直接跳到更新表达式处,然后跳到测试表达式处,然而,对于while循环来说,continue将使程序直接跳到测试表达式处,因此,while循环体中位于contineu之后的更新表达式都将被跳过。在某些情况下,这呆能是一个问题。
该程序可以不使用continue语句,而使用下面的代码:
if (line[i] == ' ')
cpaces++;
然而,当contineu之后有多条语句时,continue语句呆以提高程序的可读性。这样,就不必将所有这些语句放在if语句中。
和C语言一样,C++也有goto语句。下面的语句将跳到使用paris:作为标签的位置:
goto paris;
6.7 读取数字的循环
假设要编写一个将一系列数字读入到数组中的程序,并允许用户在数组填满之前结束输入。一种方法是利用cin。请看下面的代码:
int n;
cin >> n;
如果用户输入一个单词,而不是一个数字,情况将如何呢?发生这种类型不匹配的情况时,将发生4种情况:
方法返回false意味着可以用非数字输入来结束读取数字的循环。非数字输入设置错误标记意味着必须重置该标记,程序才能继续读取输入。clear()方法重置错误输入标记,同是也重置文件尾(EOF条件,参见第5单)。输入错误和EOF都将导致cin返回false。
假设要编写一个程序,来计算平均每天捕获的鱼的重量。这里假设每天最多捕获5条鱼,因此一个包含5个元素的数组将足以存储所有的数据,但也可能没有捕获这么多鱼。在程序清单6.13中,如果数组被填满或者输入了非数字输入,循环将结束。
程序清单6.13 cinfish.cpp
//cinfish.cpp -- non-numeric input terminates loop
#include
const int Max = 5;
int main(){
using namespace std;
//get data
double fish[Max];
cout << "Please enter the weights of your fish.\n";
cout << "You may enter up to " << Max
<< " fish > fish[i]){
if(++i < Max)
cout << "fish #" << i+1 << ":";
}
//calculate average
double total = 0.0;
for (int j= 0; j < i; j++)
total += fish[j];
//report results
if(i == 0)
cout << "No fish\n";
else
cout << total / i << " = average weight of "
<< i << " fish\n";
cout << "Done.\n";
return 0;
}
程序清单6.13中的表达式cin >> fish[i]实际上是一个cin方法函数调用,该函数返回cin。如果cin位于测试条件中,则将被转换为bool类型。如果输入成功,则转换后的值为true,否则为false。如果表达式的值为false,则循环结束。下面是该程序的运行情况:
Please enter the weights of your fish.
You may enter up to 5 fish fish #1: 30
fish #2:35
fish #3:25
fish #4:40
fish #5:q
32.5 = average weight of 4 fish
Done.
前面讲过,如果逻辑AND表达式的左侧为false,则C++将不会判断右侧的表达式。在这里,对右侧的表达式进行判断意味着用cin将输入放到数组中。如果i等于Max,则循环将结束,而不会将一个值读入到数组后面的位置中。
当用户输入的不是数字是,该程序将不再读取输入。下面来看一下继续读取的例子。假设程序要求用户提供5个高尔失得分,以计算平均成绩。如果用户输入非数字输入,程序将拒绝,并要求用户继续输入数字。可以看到,可以使用cin输入表达式的值来检测输入是不是数字。程序发现用户输入了错误内容时,应采取3个步骤。
1.重置cin以接受新的输入。
2.删除错误输入。
3.提示用户再输入。
清注意,程序必须先重置cin,然后才能删除错误输入。程序清单6.14演示了如何完成这些工作。
//cingolf.cpp -- non-numeric input skipped
#include
const int Max = 5;
int main()
{
using namespace std;
//get data
int golf[Max];
cout << "Please enter your golf score.\n";
cout << "You must enter " << Max << " rounds.\n";
int i;
for ( i = 0; i < Max; i++)
{
cout << "round #" << i+1 << ": ";
while (!(cin >> golf[i])){
cin.clear(); //reset input
while (cin.get() != '\n')
continue;
cout << "Please enter a number: ";
}
}
//calculate average
double total = 0.0;
for (i = 0; i < Max; i++)
total +=golf[i];
//report results
cout << total / Max << " = average score "
<< Max << " rounds\n";
return 0;
}
如果用户输入88,则cin表达式将为true,因此将一个值放到数组中;而表达试(cin >>golf[i])为false,因此结束内部循环。然而,如果用户输入must i ? ,则cin表达试将为false,因此不会将任何值放到数组中。而表达式!(cin >> golf[i])将为true,因此进入内部的while循环。该循环的第一条语句使用clear()方法重置输入,如果省略这条语句,程序将拒绝继续读取输入。接下来,程序在while循环中使用cin.get()来读取行尾之所有输入,从而删除这一行中的错误输入。
使用文件输出的主要步骤如下。
1,包含头文件fstream。
2,创建一个ofstream对象。
3,将该ofstream对象同一信文件关联起来。
4,就像使用cout那样使用该 ofstream对象。
程序清单6.15中的程序演示了这种方法。它要求用户输入信息,然后将信息显示到屏幕上,再将这些信息写入到文件中。
//outfile.cpp --write to a file
#include
#include //for file I/O
int main ()
{
using namespace std;
char automobile[50];
int year;
double a_price;
double b_price;
ofstream outFile; // create object for output
outFile.open("carinfo.txt"); //associate with a file
cout << "Enter the make and model of automobile: ";
cin.getline(automobile,50);
cout << "Enter the model year: ";
cin >> year;
cout << "Enter the original asking price: ";
cin >>a_price;
b_price = 0.913 * a_price;
//display informatin on screen with cout
cout << fixed;
cout.precision(2);
cout.setf(ios_base::showpoint);
cout << "Make and nodel" << automobile << endl;
cout << "Year " << year <
程序输出:
Enter the make and model of automobile: Flitz Perky
Enter the model year: 2009
Enter the original asking price: 13500
Make and nodelFlitz Perky
Year 2009
Was asking $13500.00
Now asking $12325.50
在这里,该程序运行之前,文件carinfo.txt并不存在。在这种情况下,方法open()将新建一个名为carinfo.txt文件。如果在此运行该程序,文件carinfo.txt将存在,此时情况将如何呢?默认情况下,open()将首先截断该文件,即将其长度截短到零------丢其原有的内容,然后将新的输出加入到该文件中。
读取文本文件
如果试图打开一个不存在的文件用于输入,情况将如何呢?这种错误将导致后面使用ifstream对象进行输入时失败。检查文件是否被成功打开的首先方法是使用方法is_open(),为此,可以使用类似于下面的代码:
ifFile.open("bowling.txt");
if(!inFile.is_open())
{
exit(EXIT_FAILURE);
}
如果文件被成功打开,方法is_open()将返回true;因此如果文件没有被打开,表达式!inFile.is_open()将为true.函数exit()的原型是在头文件cstdlib中定义的,在该头文件中,还定义了一人用于同操作系统通信的参数值EXIT_FAILURE。函数exit()终止程序。
程序清单6.16中的程序打开用户指定的文件,读取其中的数字,然后指出文件中包含多少个值以及它们的和与平均值。正确地设计输入循环至关重要。
//sumafile.cpp -- functions with an array argument
#include
#include
#include // support for exit()
const int SIZE = 60;
int main()
{
using namespace std;
char filename[SIZE];
ifstream inFile; //object for handling file input
cout << "Enter name of data file: ";
cin.getline(filename,SIZE);
inFile.open(filename); // associate inFile with a file
if(!inFile.is_open()) //failed to open file
{
cout << "Could not open the file " << filename << endl;
cout << "Program terminating.\n";
exit(EXIT_FAILURE);
}
double value;
double sum = 0.0;
int count = 0 ; //number of iterms read
inFile >> value; //get first value
while(inFile.good()) //while input good and not at EOF
{
++count;
sum += value;
inFile >>value; //get next value
}
if(inFile.eof())
cout << "End of file reached.\n";
else if (inFile.fail())
cout << "Input terminated by data mismatch.\n";
else
cout << "Input terminated for unknow reason.\n";
if (count == 0 )
cout << "NO data proceesed.\n";
else
{
cout << "Items read " << count << endl;
cout << "Sum: " << sum <
scores.txt内容
18 19 18.5 13.5 14
16 19.5 20 18 12 18.5
17.5
程序运行结果
Enter name of data file: scores.txt
End of file reached.
Items read 12
Sum: 204.5
Average:17.0417
这里需要特别注意文件读取循环的正确设计:
方法eof():如果最后一次读取数据时遇到EOF,方法eof()将返回true。
方法fail():如果最后一次读取操作中发生了类型不匹配的情况,方法fail()将返回true。
方法good():该方法在没有发生任何错误时返回true。
方法gook()指出最后一次读取输入的操作是否成功,这一点至关重要。这一点至关重要。 这意味着就该在执行读取输入的操作后,立刻应用这种测试。为此,一种标准方法是:在循环之前(首次执行循环测试前)放置一条输入语句,关在循环的末尾(下次执行循环测试之前)放置另一条输入语句:
对循环输入语句进行精简:表达式inFile >> value 的结果为inFile,而现在需要一个bool值的情况下,inFile的结果为inFile.good(),即true或false。
while(inFile >> value) //read and test for success
{
++count;
sum += value;
}