第05章 语句

C++ primer 5th 第5章 语句

=====================================================================

第5章 语句 154~159页    简单语句

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int get_num()
{
	return 0;
}
int main()
{
	int ival = 0;
	ival + 5;//一条没什么用处的表达式语句
	cout<<endl;//一条有用的表达式语句
	//空语句
	;
	int s, sought = 5;
	while (cin>>s&&s!=sought)//循环输入,直到文件末尾或某次输入等于sought
	{
		;//空语句
	}
	//复合语句
	int val = 0, sum = 0;
	while (val<=10)
	{
		sum += val;//把sum+val的值赋给sum
		++val;//把val加1
	}
	//空块,指内部没有任何语言的一对花括号,等价于空语句
	//临时声明函数
	while (int i = get_num())//每次迭代时创建并初始化i
	{
		cout << i << endl;
	}
	//i = 0;//错误:在外循环无法访问i
	vector<int>v(10, 10);
	auto beg = v.begin();
	while (beg!=v.end()&&*beg>=0)
	{
		++beg;
	}
	if (beg == v.end())
		;//此时我们知道v中的所有元素都大于等于0
#ifndef DECLARATION
	条件语句
		if (条件)	如果condition为真,执行说明(statement)1部分, 如果条件为假跳过说明1,从else开始执行
			说明1;
		else	如果condition为假, 执行说明2部分,如果代码较长,要用大括号
			说明2;
#endif
	const vector<string> score = { "F","D","C","B","A","A++" };
	//我们使用if else根据成绩是否合格执行不同操作
	//如果grade小于60,对应字母是F ,否则计算其下标
	int grade = 60;
	string lettergrade;
	if (grade < 60)//判断grade的值是否小于60,根据结果执行是if还是else分支
		lettergrade = score[0];
	else
	{//如果执行else把grade减50,然后执行整除法,得到字母的位置
		lettergrade = score[(grade - 50) / 10]; 
		if (grade!=100)
			if (grade % 10 > 7)
				lettergrade += '+';//末尾是8或9的成绩添加一个加号
			else if (grade % 10 < 3)
				lettergrade += '-';//末尾是0、1、2的成绩添加一个减号
	}//如果没有花括号代码看起来是正确的,但因为值小于60会无条件的在末尾添加减号
	cout<<lettergrade<<endl;
#ifndef DECLARATION
	//错误:实际执行过程并非像缩进那样,else分支匹配的是内层的if语句
	if (grade % 10 >= 3)
		if (grade % 10 > 7)
			lettergrade += '+';//末尾是8或者9的成绩添加一个加号
		else
			lettergrade += '-'; //末尾是3、4、5、6、7 的成绩添加一个减号
			;
	上面那条意思如下
		if (grade % 10 >= 3)
		{
			if (grade % 10 > 7)
				lettergrade += '+';//末尾是8或者9的成绩添加一个加号
			else
				lettergrade += '-';
		}
	所以你必须有花括号强制else与外层匹配
		if (grade % 10 >= 3)
		{
			if (grade % 10 > 7)
				lettergrade += '+';//末尾是8或者9的成绩添加一个加号
		}
		else
			lettergrade += '-';
#endif
	

	system("pause");
	return 0;
}

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
	//练习题5.5编写程序使用if else把字数成绩转换成字母成绩
	const vector<string> svec = { "F","E","D","C","B","A","A++" };
	string buf;
	int grade;
	cin >> grade;
#ifndef DECLARATION
	if (grade > 60)//当大于60时执行下面。否则跳转到else (1)
	{
		buf = svec[(grade - 50) / 10];//把分数分成5个等级。所以减一半,除以10将得到一个个位值
		if (grade != 100)//如果等于100就不执行下面的
		{
			if (grade % 10 >= 6)//当不等于100,再除10得到余数大于6则末尾加“+”
				buf += "+";
			else //当不等于100,再除10得到余数小于6则末尾加“-”
			{
				buf += "-";
			}
		}
	}
	else //else (1)
	{
		buf = svec[0];
	}
	cout<<buf<<endl;
#endif
	//练习题5.5 更改上面程序用条件运算符
	cout<<(grade>60?buf=svec[(grade-50)/10]+
		(grade%10>6?"+":"-"):
		buf=svec[0])<<endl;
	
#ifndef DECLARATION
	练习题5.7:改正下列代码中的错误

	if (ival != ival2)
		ival = ival2;

	if (ival < minval)
		minval = ival;
	occurs = 1;

	if (int ival=get_value())
		cout<<"ival = "<<ival<<endl;

	if (ival = 0)
		ival = get_value();
#endif
	int ival = 0, ival2 = 2, minval = 3, occurs = 0;
	if (ival != ival2)
		ival = ival2;

	if (ival < minval)
	{
		minval = ival;
		occurs = 1;
	}
	int get_value();//声明临时函数
	if (int ival = get_value())
		cout << "ival = " << ival << endl;

	if (ival == 0)
		ival = get_value();
	//练习题5.8什么是悬垂else
	//就是一个if语句嵌套在另一个if语句内部,使得if分支多于else分支,c++规定else与离它最近的尚未匹配的if匹配
	system("pause");
	return 0;
}
int get_value()
{
	return 0;
}

=====================================================================

第5章 语句 160页    switch语句

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
	unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
	char ch='a';
	while (cin >> ch)
	{
		switch (ch)
		{
			//如果ch是元音字母,将其应的计数加1
		case 'a':
			++aCnt;
			break;///如果不加break,将跳到下一个case
		case 'e':
			++eCnt;
			break;
		case 'i':
			++iCnt;
			break;
		case 'o':
			++oCnt;
			break;
		case 'u':
			++uCnt;
			break;
		}
	}
	cout<<"Number of vowel a: \t"<<aCnt<<'\n'
		<<"Number of vowel e: \t"<<eCnt<<"\n"
		<<"Number of vowel i: \t"<<iCnt<<'\n'
		<<"Number of vowel o: \t"<<oCnt<<'\n'
		<<"Number of vowel u : \t"<<uCnt<<endl;
	unsigned vowelCnt = 0;
	switch (ch)
	{//如果出现a、e、i、o、u的任意一个都会将vowelCnt的值加1
	case 'a':
	case 'e':
	case 'i':
	case 'o':
	case 'u':
		++vowelCnt;//只要ch是元音字母,不管到底是五个的哪一个都执行相同操作
		break;
	}
	//另一种写法
	switch (ch)
	{
	case 'a':case 'e':case 'i':case 'o':case 'u':
		++vowelCnt;
		break;
	}

	//如果没有任何一个case标签能匹配switch,程序紧跟着default
	int otherCnt = 0;
	switch (ch)
	{
	case 'a':case 'e':case 'i':case 'o':case 'u':
		++vowelCnt;
		break;
	default:
		++otherCnt;
		break;
	}
	int next_num();
	bool condition = 0;
#ifndef DECLARATION
	switch (condition)
	{
	case true:
		string file_name;//错误。控制流绕过一个隐式初始化的变量 
		int ival = 0;//错误:控制流绕过一个显式的初始化变量
		int jval;
		break;
	case false://一旦控制流直接跳到false,同时也就略过了变量file_name和ival的初始化过程
		jval = next_num();//在尚未初始化时使用它们,这显然行不通
		if (file_name.empty()) { ; }//file_name在作用域内。但没被初始化
		break;
	}
#endif
	string get_file_name();
	switch (condition)
	{
	case true:
	{
		string file_name = get_file_name();//正确:声明位于语句块内部
	}
	break;
	case false:
#ifndef DECLARATION
		if (file_name.empty()) { ; }//错误:file_name不在作用域内;
#endif
		;
		break;
	}
	system("pause");
	return 0;
}
int next_num()
{
	return 0;
}
string get_file_name()
{
	return "abc";
}

=====================================================================

第5章 语句 164页    练习

=====================================================================

#include <iostream>
#include <cctype>
#include <string>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
	//练习题5.9编写程序,使用一系列的if语句统计从cin读入的文本中有多少个元音字母
	char ch;
	unsigned quantity = 0;
	while (cin >> ch&&!isdigit(ch))
	{
		if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
			++quantity;
	}
	//练习题5.10修改元音程序,使其能统计大小写的元音

	cout<<"元音数量"<<quantity<<endl;
	int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
	while (cin >> ch && !isdigit(ch))
	{
		ch = tolower(ch);
		if (ch == 'a')
			aCnt++;
		if (ch == 'e')
			eCnt++;
		if (ch == 'i')
			iCnt++;
		if (ch == 'o')
			oCnt++;
		if (ch == 'u')
			uCnt++;
	}
	cout << "Number of vowel a: \t" << aCnt << '\n'
		<< "Number of vowel e: \t" << eCnt << "\n"
		<< "Number of vowel i: \t" << iCnt << '\n'
		<< "Number of vowel o: \t" << oCnt << '\n'
		<< "Number of vowel u : \t" << uCnt << endl;
	//练习题5.11修改元音程序,使其能统计空格,制表符和换行符的数量
	quantity = 0;
	cin >> ch;
	switch (ch)
	{
	case 'a':      case 'A':      case 'e':      case 'E':      case 'i':      case 'I':      case 'o':
	case 'O':      case 'u':      case 'U':      case ' ':      case '\t':     case '\n':
		++quantity;
	}
	//练习5.12修改统计元音字母的程序,使其能统计含以下两个字符的字符序列的数量: ff、fl和fi。
	string s;
	quantity = 0;
	while (cin>>s && s!="end")
	{
		if (s=="ff"||s=="fl"||s=="fi")
			++quantity;
	}
	cout<<quantity<<endl;
#ifndef DECLARATION
	练习5.13:下面显示的每个程序都含有一个常见的编码错误,指出错误在哪里,然后修改它们。
		;
	//(a) 
	unsigned aCnt = 0, eCnt = 0, iouCnt = 0;
	char ch = next_text();
	switch (ch)
	{
	case 'a': aCnt++;//每个都少了break
	case 'e': eCnt++;
	default: iouCnt++;
	}

	//(b) 
	unsigned index = some_value();
	switch (index)
	{
	case 1:
		int ix = get_value();
		ivec[ix] = index;
		break;
	default:
		ix = ivec.size() - 1;//执行这条时标签未定义
		ivec[ix] = index;
	}

	//(c) 
	unsigned evenCnt = 0, oddCnt = 0;
	int digit = get_num() % 10;
	switch (digit)
	{
	case 1, 3, 5, 7, 9://标签错误两个都要写完整case 1:case 3:case 5:case 7:case 9:
		oddcnt++;//变量名错误
		break;
	case 2, 4, 6, 8, 10:
		evencnt++;
		break;
	}

	(d) unsigned ival = 512, jval = 1024, kval = 4096;//要改成整型常量表达式。
	unsigned bufsize;
	unsigned swt = get_bufCnt();
	//声明一个函数return 0;就可以用
	switch (swt)
	{
	case ival://标签必须是整型常量表达式。
		bufsize = ival * sizeof(int);
		break;
	case jval:
		bufsize = jval * sizeof(int);
		break;
	case kval:
		bufsize = kval * sizeof(int);
		break;
	}

#endif
	
	system("pause");
	return 0;
}

=====================================================================

第5章 语句 165页    迭代语句

=====================================================================

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
#ifndef DECLARATION
	//只要ccondition 结果为真就一直执行statement,condition不能为空,
	//	如果第一次执行为false,则一次循环都不会执行
	while (condition)
	{
		statement;
	}
#endif
	;
	vector<int> v;
	int i;
	while (cin >> i&&i!=-1)
		v.push_back(i);
	//寻找第一个元素
	auto beg = v.begin();
	while (beg != v.end() && *beg >= 0)
	{
		++beg;
	}
	if (beg == v.end())
		;//此时我们知道v中的所有元素都大于等于0

	/*练习5.14:编写一段程序,从标准输入中读取若干string对象并查找连续重复出现的
	单词。所谓连续重复出现的意思是:一个单词后面紧跟着这个单词本身。要求记录连续
	重复出现的最大次数以及对应的单词。如果这样的单词存在,输出重复出现的最大次数;
	如果不存在,输出一条信息说明任何单词都没有连续出现过。
	例如:如果输入是:
		how now now now brown cow cow
	那么输出应该表明单词now连续出现了3次。*/
	cout<<"---"<<endl;
	string buf, sought;
	int Cnt ;
	if (cin>>sought)
	{
		Cnt = 1;
		while (cin >> buf && buf != "end")
			if (buf == sought)
				Cnt++;
			else
			{
				cout << sought << " " << Cnt << endl;
				sought = buf;
				Cnt = 1;
			}
		cout<<sought<<" "<<Cnt<<endl;
	}
#ifndef DECLARATION
	传统的for语句
		for (init - statemen; condition; expression)
			statement;
	关键字for及括号里的部分称作for语句头
		init-statement 必须是以下三种形式中的一种:声明语句,表达式语句或者空语句,
		因为这些语句都以分号作为结束,所以for语句的语法形式也可以看做
		for (initializer; condition; expression)
			statement;
	init - statement负责初始化一个值, 这个值将随着循环的进行而改变.
		condition作为循环控制的条件, 只要为真, 就执行一次statement, 如果condition的第一次
		求值结果就是false, 则statement一次也不会执行.expression负责修改init - statement初始化的
		变量, 这个变量正好就是condition检查的对象, 修改发生在每次循环迭代之后, statement可以是一条
		复合语句;

#endif	
	string s("abcdefg");
	//重复处理s中的字符串直至结束
	for (decltype(s.size()) index = 0;
		index != s.size() && !isspace(s[index]); ++index)
		s[index] = toupper(s[index]);//将当前字符改成大写形式
	/*循环开始时, 先判断一次init - staement.此例中定义index并初始化为0;
	接下来判断condition.如果index不等于s.size()而且在 s[index]位置的字符
	不是空白,则执行for循环举杯 的内容.否则终止.如果第一次迭代时条件为假
	,for循环一次也不会执行.
	如果条件为真,执行循环体,此例中,for循环体将s[index]位置的字符改写成大写形式
	最后执行expression.此例中,将index加1*/
	//多重声明,记录下v的大小,当到达原来的一个元素后结束循环
	for (decltype(v.size()) i = 0, sz = v.size(); i != sz; ++i)
		v.push_back(v[i]);
	//如果无须初始化,则我们可以使用一条空语句作为init-statement,例如,对于在vector对象中寻找第一个
	//负数的程序,完全能用for循环改写
	auto pbeg = v.begin();
	for (/*空语句*/; pbeg != v.end() && *beg >= 0; ++beg)
		;//什么也不做
	//或者
	for (int i=0;/*条件为空*/;++i)
	{
		/*对i进行处理,循环内部的代码必须负责终止迭代过程*/
	}
	vector<int> ivec;
	cout<<"---"<<endl;
	for (int i; cin >> i&&i!=-1;/*表达式为空*/)
		v.push_back(i);//因为部分条件能改变i的值,所以这个循环无须表达式部分,其中,条件部分
	//不断检查输入流的内容,只要读取所有的输入或者遇到一个输入错误就终止循环

	system("pause");
	return 0;
}

=====================================================================

#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <cstddef>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
#ifndef DECLARATION
	//练习5.15:说明下列循环的含义并改正其中的错误。
	(a) for (int ix = 0; ix != sz; ++ix) { /* ... */ }
	if (ix != sz)
		// . . .;
	(b) int ix;
	for (ix != sz; ++ix) { /* ... */ }
	(c) for (int ix = 0; ix != sz; ++ix, ++sz) { /*...*/ }
	解答a
	vector<int > ivec{ 1,2,3 };
	int sz = ivec.size(),ix=0;//这里应该定义ix变量,if部分才能访问
	for (int ix = 0; ix != sz; ++ix) { /* ... */ }
	if (ix != sz)
		;
	解答b
	int ix;
	for (ix != sz; ++ix) { /* ... */ }
	//for循环中缺少一个init-statement的分号,就算是空语句也要分号
	解答c
		for (int ix = 0; ix != sz; ++ix, ++sz) { /*...*/ }
	//sz自增的话,将会无限循环下去,因为ix永远也不会与sz相等就达不到终止循环的条件

#endif
	/*练习5.17:假设有两个包含整数的vector对象,编写一段程序,检验其中一个vector
	对象是否是另一个的前缀。为了实现这一目标,对于两个不等长的vector对象,只需
	挑出长度较短的那个,把它的所有元素和另一个vector对象比较即可。例如,如果两
	个vector对象的元素分别是0、1、1、2 和 0、1、1、2、3、5、8,则程序的返回
	结果为真。*/
	vector<int> ivec1{ 1,2,1,4 }, ivec2{ 1,2,1,2,1,4,4 };
	size_t j;//用来计数
	for (size_t i = 0; i < ivec2.size(); ++i)
	{
		j = 0;
		size_t  t = i;//用来到临时递增地址
		while (j<ivec1.size()&&ivec1[j]==ivec2[t])
		{
			j++;//当相同又小于ivec1.size()时加加
			t++;//临时下标地址递增
		}
		if (j==ivec1.size())//当j自增到长度相同表示,前面一样
			break;
	}
	cout<<(bool)j<<endl;//输出一个转换成bool类型的,不是0就是1
	system("pause");
	return 0;
}

=====================================================================

第5章 语句 165页    范围for语句

=====================================================================

 

//QQ108201645编写
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <cstddef>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
	//vector<int> v{0,1,2,3,4,5,6,7,8,9};
	//范围变量必须是引用类型,这样才能对元素执行写操作
	//for(auto &r:v)
	vector<int> v(10, 2);
	for (auto beg = v.begin(), end = v.end(); beg != end; ++beg)
	{//在范围for循环中预存了end(),一旦在序列中添加或删除, end函数的值就可以变的无效
		auto &r = *beg;
		r *= 2;//将v 中的每个值翻倍
	}
	//do while语句
#ifndef DECLARATION
	do
		statement
		while (condition);
	在do语句中, 求condition的值之前首先执行一次statement, condition不能为空.
	如果condition的值为空, 循环终止; 否则重复循环过程.condition使用的变量定义
		在循环体之外;
#endif
		//不断可以使用do while循环(不断地)执行加法运算
	string rsp;//作为循环的条件,不能定义在do内部
	do 
	{
		cout << "please enter tow values: ";
		int val1 = 0, val2 = 0;
		cin >> val1 >> val2;
		cout << "The sum of " << val1 << " and " << val2
			<< " = " << val1 << +val2 << "\n\n"
			<< " more ? Enter yes or no:";
			cin >> rsp;
	} while (!rsp.empty()&&rsp[0]!='n');
	//当是空时返回1不是空返回0,用逻辑求反,让它在0时返回1结果为真,右侧则rsp首位不是n则继续循环,否则退出循环
	//定义变量
/*
	do 
	{//
		numble(foo);
	} while (int foo=get_foo);//错误,将变量声明在了do的条件部分
	如果允许在条件部分定义变量,则变量的使用出现在定义之前这显然不合理*/
#ifndef DECLARATION
	练习5.18说明下列循环的含义并改正其中的错误。

	(a) do
		int v1, v2;
	cout << "Please enter two numbers to sum:";
	if (cin >> v1 >> v2)
		cout << "Sum is: " << v1 + v2 << endl;
	while (cin);

	(b) do {
		// . . .
	} while (ival = get_response());
	(c) do {
		ival = get_response();
	} while (ival);

	(a)语法错误,do后面,while前面的语句应该用花括号括起来
	(b) 语法错误,do while条件使用的表达式规定必须是在循环前定义!
	(c) 语法错误,do while条件使用的表达式规定必须是在循环前定义!;
#endif
	string buf, str;
	cout<<"请输入任意两组字符串"<<endl;
	cin >> buf >> str;
	if (buf.size()>str.size())
		cout<<buf<<" "<<buf.size()<<endl;
	else if (buf.size()==str.size())
		cout<<"两个一样长"<<endl;
	else 
		cout<<str<<" "<<str.size()<<endl;
	system("pause");
	return 0;
}

=====================================================================

第5章 语句 171页    跳转语句

=====================================================================

//QQ108201645编写
#include <iostream>
#include <string>
#include <cstddef>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
	string buf;
	while (cin>>buf&&!buf.empty())
	{
		switch (buf[0])
		{
		case '-':
			//处理第一个空白为止
			for (auto it = buf.begin() + 1; it != buf.end(); ++it)
			{
				if (*it == ' ')
					break;
				//
			}
			//bureak #1将控制权转移到这里
			break;//#2将离开switch
		case '+':
			//
			break;
		}//结束switch
		//结束switch:break #2将控制权转移到这里
	}//结束while

	system("pause");
	return 0;
}

=====================================================================

#include <iostream>
#include <string>
#include <cstddef>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{/*
	练习5.20:编写一段程序,从标准输入中读取string对象的序列直到连续出现两个相
	同的单词或者所有单词都读完为止。使用while循环一次读取一个单词,当一个单词
	连续出现两次时使用break语句终止循环。输出连续重复出现的单词,或者输出一个
	消息说明没有任何单词是连续重复出现的。*/
	string newstr, newbuf;
	if (cin >> newbuf)
	{
		int cnt = 1;
		while (cin >> newstr)
		{
			if (newstr == newbuf)
				cnt++;
			else
			{
				cout << newbuf << " " << cnt << endl;
				newbuf = newstr;
				cnt = 1;
			}
			cout << newbuf << " " << cnt << endl;
		}
	}
	system("pause");
	return 0;
}

=====================================================================

第5章 语句 171页    continue语句

=====================================================================

//QQ108201645编写
#include <iostream>
#include <string>
#include <cctype>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
	string buf;
	while (cin>>buf&& !buf.empty())
	{
		if (buf[0]!=' ')
			continue;//接着读取下一个输入
		//程序执行过程到了这里?说明当前的输入是以下画线开始的;接着处理buf......
	}
	/*练习5.21修改5.5.1节练习题的程序,使其找到的重复单词必须以大写字母开头。*/
	string newstr, newbuf;
	if (cin >> newbuf)
	{
		while (cin >> newstr)
		{
			if (newstr == newbuf&&isupper(newbuf[0]))
			{
				
				cout << newbuf << endl;
			}
			else
			{
				newbuf = newstr;
			}
		}
	}
	system("pause");
	return 0;
}

 

=====================================================================

第5章 语句 172页    goto语句

=====================================================================

//QQ108201645编写
#include <iostream>
#include <string>
#include <cctype>
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
	//goto作用是无条件跳转到同一函数内的另一条语句,不要在程序中使用,会使得程序既难理解又难修改
	//goto label
	int ix = 0;
	goto end;//跳转到标签为end的代码位置
	ix=5;//如果把上面int ix放在这里,程序将出错.会绕过一个带初始化的变量定义
	cout<<ix<<endl;
end:
	ix = 42;
	cout << ix << endl;
	//向后跳过一个已经执行定义的是合法的
	int get_size();
#ifndef DECLARATION
begin:
	int sz = get_size();
	if (sz <= 0)
	{
		goto begin;//跳回begin后会一直循环
	}
	//上面代码goto执行后将销毁sz,因为跳回begin的动作跨过了sz的定义语句,所以sz将重新定义并初始化
#endif
	for (int sz = get_size(); sz <= 0; sz = get_size())
		;//与上述代码功能一样的重写//作业5.22
	system("pause");
	return 0;
}
int get_size()
{
	return 0;
}

=====================================================================

第5章 语句 173页    try语句块和异常处理

=====================================================================

//QQ108201645编写
//定义为Sales_item.h头文件
#ifndef SALESITEM_H//未定义SALESITEM_H则继续向下执义
// we're here only if SALESITEM_H has not yet been defined 
#define SALESITEM_H

#include "Version_test.h" 

// Definition of Sales_item class and related functions goes here
#include <iostream>
#include <string>

class Sales_item {
	// these declarations are explained section 7.2.1, p. 270 
	// and in chapter 14, pages 557, 558, 561
	friend std::istream& operator>>(std::istream&, Sales_item&);
	friend std::ostream& operator<<(std::ostream&, const Sales_item&);
	friend bool operator<(const Sales_item&, const Sales_item&);
	friend bool
		operator==(const Sales_item&, const Sales_item&);
public:
	// constructors are explained in section 7.1.4, pages 262 - 265
	// default constructor needed to initialize members of built-in type
#if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS)
	Sales_item() = default;
#else
	Sales_item() : units_sold(0), revenue(0.0) { }
#endif
	Sales_item(const std::string &book) :
		bookNo(book), units_sold(0), revenue(0.0) { }
	Sales_item(std::istream &is) { is >> *this; }
public:
	// operations on Sales_item objects
	// member binary operator: left-hand operand bound to implicit this pointer
	Sales_item& operator+=(const Sales_item&);

	// operations on Sales_item objects
	std::string isbn() const { return bookNo; }
	double avg_price() const;
	// private members as before
private:
	std::string bookNo;      // implicitly initialized to the empty string
#ifdef IN_CLASS_INITS
	unsigned units_sold = 0; // explicitly initialized
	double revenue = 0.0;
#else
	unsigned units_sold;
	double revenue;
#endif
};

// used in chapter 10
inline
bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs)
{
	return lhs.isbn() == rhs.isbn();
}

// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);

inline bool
operator==(const Sales_item &lhs, const Sales_item &rhs)//==运算符重载
{
	// must be made a friend of Sales_item
	return lhs.units_sold == rhs.units_sold &&
		lhs.revenue == rhs.revenue &&
		lhs.isbn() == rhs.isbn();
}

inline bool
operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
	return !(lhs == rhs); // != defined in terms of operator==
}

// assumes that both objects refer to the same ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs)//'+='重载
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}

// assumes that both objects refer to the same ISBN
Sales_item
operator+(const Sales_item& lhs, const Sales_item& rhs)//'+'重载
{
	Sales_item ret(lhs);  // copy (|lhs|) into a local object that we'll return
	ret += rhs;           // add in the contents of (|rhs|) 调用+=重载
	return ret;           // return (|ret|) by value	返回临时对象
}

std::istream&
operator>>(std::istream& in, Sales_item& s)//重载输入运算符
{
	double price;
	in >> s.bookNo >> s.units_sold >> price;//接受书的编号、数量、价格
	// check that the inputs succeeded
	if (in)//输入不等于空、比如输入ctrl+z再回车
		s.revenue = s.units_sold * price;//收入等于数量乘价格
	else
		s = Sales_item();  // input failed: reset object to default state
	//调用构造函数重置为默认。
	return in;
}

std::ostream&
operator<<(std::ostream& out, const Sales_item& s)
{
	out << s.isbn() << " " << s.units_sold << " "
		<< s.revenue << " " << s.avg_price();
	return out;
}

double Sales_item::avg_price() const
{
	if (units_sold)//除数不等于0
		return revenue / units_sold;
	else
		return 0;
}

#endif

―――――――――――――――――――――――――――――――――――――――

//续上面部分保存任意main.cpp
#include <iostream>
#include <string>
#include <cctype>
#include "Sales_item.h"
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
#ifndef DECLARATION
	当程序的某部分检测到一个它无法处理的问题时, 需要用到异常处理;
	throw表达式(throw expression), 异常检测部分使用throw表达式来表示它遇到了无法处理的问题.
		我们说throw引发(raise)了异常;
	try语句块(try block), 异常处理部分使用try语句块处理异常.try语句块以关键字try抛出的异常
		通常会被某个catch子句(catch clause)结束.畎因为catch子句"处理"异常, 所以它们也被称作
		异常处理代码(exception handler);
	一套异常类(exception class), 用于在throw表达式和相关 catch子句之间传递异常的具体信息;
#endif //DECLARATION
	//以下代码需要Sales_iter.h头文件,参见第一章
#ifndef DECLARATION
	Sales_item item1, item2;
	cin >> item1 >> item2;
	//首先检查item1和item2是否表达同一本书
	if (item1.isbn() == item2.isbn())
	{//当程序执行到这里表示相同
		cout << item1 + item2 << endl;
	}
	else
	{
		cerr<<"Data must refer to same ISBN "<<endl;
	}
#endif
	/*
	try语句块的通用语法形式是
	try
	{
		program-statements
	}
	catch (exception-declaration)//译:接住(异常-声明)
	{
		program - statements(译:编程-说明)
	}
	catch (exception-declaration)
	{
		program-statements
	}
	catch (exception-declaration)
	{
		program-statements
	}
*/

	
//修改上面这段Sales_item
	Sales_item item1, item2;
	while (cin>>item1>>item2)
	{
		try
		{
			if (item1.isbn() != item2.isbn())//娄不一样时抛出一个异常.跳转到catch去处理异常
				throw runtime_error("Data must refer to same ISBN");
			//throw必须在 try代码块中.后边跟的值决定抛出异常的类型。
			cout<<item1+item2<<endl;
		}
		catch (runtime_error err) 
		{
			//catch 
			//出现在try代码块后,后边跟的数据决定捕获的类型
			//catch (...) 表示捕获所有异常
			cout<<err.what()//err.what是runtime_error类的一个成员函数
				<<"\nTry Again? Enter y or n"<<endl;
			char c;
			cin >> c;
			if (!cin||c=='n')
				break;//跳出while循环

		}
	}
	system("pause");
	return 0;
}
#ifndef DECLARATION
	exception头文件定义了最通用的异常类exception.它只报告异常的发生
		不提供任何额外信息;
	stdexcept头文件定义了几种常用的异类, 详细信息在表5.1中列;
	new头文件定义了bad_alloc异常类型, 这种类型将在12.1.2节第407页中详细介绍;
	type_info头文件定义了bad_cast异常类型,这种在19.2第731页详细介绍
#endif

=====================================================================

//QQ108201645编写
#ifndef DECLARATION

练习5.24:修改你的程序,使得当第二个数是0时抛出异常。先不要设定catch子句,运行程序并真的为除数输入0,看看会发生什么?
程序终止。

练习5.25:修改上一题的程序,使用try语句块去捕获异常。catch子句应该为用户输出一条提示信息,询问其是否输入新数并重新执行try语句块的内容。 
#endif

#include <iostream>
#include <string>
#include <map>
#include "Sales_item.h"
using namespace std;//使用命名空间
#ifndef DECLARATION
#define DECLARATION
//说明部分
//执行已定义声明的话将不再执行
#endif
int main()
{
	int i1, i2;
	while (cin >> i1 >> i2)
	{
		try
		{
			if (i2 == 0)
				throw string("ERROR! Division by zero!");
		}
		catch (string s)
		{
			cout << s << endl;
			cout << "Try again? 'Y' or 'N'";
			char c;
			cin >> c;
			if (!cin || c == 'n')
				break;
			else
				continue;
		}
		cout << i1 / i2 << endl;
	}
	
		
	system("pause");
	return 0;
}

=====================================================================

表5.1: <stdexcept>定义的异常类

exception

最常见的问题

runtime_error

只有在运行时才能检查出的问题

range_error

运行时错误:生成的结果超出了有意义的域值范围

overflow_error

运行时错误:计算上溢

underflow_error

运行时错误:计算下溢

logic_error

程序逻辑错误

domain_error

逻辑错误:参数对应的结果值不存在

invalid_error

逻辑错误:无效参数

length_error

逻辑错误:试图创建一个超出该类型最大长度的对象

out_of_range

逻辑错误:使用一个超出有效范围的值

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值