C++ Primer学习笔记第6章分支语句和逻辑运算符

程序清单6-10演示了如何使用switch 和break来让用户选择简单菜单。该程序使用showmenu()函数显示一组选项,然后使用switch语句,根据用户的反应执行相应的操作。

注意:有些硬件/操作系统组合不会将(程序清单6.10的 case 1 中使用的)转义序列\a解释为振铃。

程序清单switch.cpp 

//switch.cpp -- using the switch statement
#include <iostream>
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 <iostream>
//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 <iostream>
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种情况:

  • n的值保持不变;
  • 不匹配的输入将被留在输入队列中;
  • cin对象中的一个错误标记被设置;
  • 对cin方法的调用将返回false(如果被转换为bool类型)。

方法返回false意味着可以用非数字输入来结束读取数字的循环。非数字输入设置错误标记意味着必须重置该标记,程序才能继续读取输入。clear()方法重置错误输入标记,同是也重置文件尾(EOF条件,参见第5单)。输入错误和EOF都将导致cin返回false。

假设要编写一个程序,来计算平均每天捕获的鱼的重量。这里假设每天最多捕获5条鱼,因此一个包含5个元素的数组将足以存储所有的数据,但也可能没有捕获这么多鱼。在程序清单6.13中,如果数组被填满或者输入了非数字输入,循环将结束。

程序清单6.13  cinfish.cpp

//cinfish.cpp -- non-numeric input terminates loop
#include <iostream>
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 <q to terminate.\n";
  cout << "fish #1: ";
  int i = 0;
  while (i < Max && cin >> 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 <q to terminate.
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 <iostream>
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 <iostream>
#include <fstream>      //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 <<endl;
  cout << "Was asking $" << a_price << endl;
  cout << "Now asking $" << b_price << endl;

  //now do exact same things using outFile instend of cout


  outFile << fixed;
  outFile.precision(2);
  outFile.setf(ios_base::showpoint);
  outFile << "Make and model: " << automobile <<endl;
  outFile << "Year: " << year <<endl;
  outFile << "was asking $ "  << a_price << endl;
  outFile << "Now asking $ " << b_price <<endl;

  outFile.close();            //done with file
  return 0;
}

程序输出:

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 <iostream>
#include <fstream>
#include <cstdlib>    // 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 <<endl;
    cout << "Average:" << sum / count <<endl;
  }

  inFile.close();     //finished with the file
  return 0;
}

 

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;
  }

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值