《C++ Primer》笔记(05)

第 5 章 语句

简单语句

  1. 空语句,用于某些语法需要的位置,如while循环体为空。
while (cin >> s && s != sought)
    ; // 空语句
  1. 使用花括号{}框起来的语句为复合语句/块,也可空。

语句作用域

控制结构内定义的变量仅在结构内可见。

条件语句

if语句

嵌套if循环中常有if分支数大于else分支数,导致匹配不明确的问题,称为“悬垂else”。为此规定else分支会与最近的if分支匹配,也可使用花括号{}将语句限制成块控制执行路线。

switch语句

  1. case标签必须是整型常量表达式。
  2. case分支会在匹配标签后顺序执行所有执行语句(无视之后标签的匹配与否),要中断switch控制流需要使用break语句。
  3. 标签不能单独出现,必须跟上标签/语句(包括default标签)。
  4. 不允许跨过变量的初始化语句直接跳转到该变量作用域内的另一个位置。如需要在case分支中定义并初始化变量,需要将其定义在块内,确保后续分支都在该变量的作用域外。
case true: // 可能跳过该部分的初始化语句
	string file_name; // 错误:隐式初始化被跳过
	int ival = 0; // 错误:显示初始化被跳过
	int jval; // 正确:未初始化
	break;
case false: // 当跳过true标签的分支时,jval和file_name都未初始化。
	jval = next_num(); // 正确:给jval赋值
	if (file_name.empty()) {
        ...
    }

迭代语句

while语句

不确定循环次数,或循环后需要访问控制变量时使用。

传统for语句

  1. 语句头中的声明语句只能有一条,多变量其基础类型必须相同。
  2. 允许使用空语句,但不能省略分号。

范围for语句

不能在范围for语句中修改容器元素的个数。

do while 语句

与while语句区别在于先执行循环体,后判断条件,故至少会执行一次循环体。

跳转语句

break语句

用于中止最近的迭代语句和switch语句下的case标签(而非中止switch语句)。

continue语句

用于中止最近的迭代语句的当前循环并直接进行下一次循环(即跳过continue语句的后续循环体)。

goto语句

无条件跳转到指定标签的位置,与switch语句类似,不允许从作用域外跳转到作用域内(会产生未初始化、未定义等问题),但允许从定义和初始化后跳转到之前。

begin:
	int sz = get_size();
	if (sz <= 0) {
        goto begin;
    }

goto语句在这里销毁了变量sz,将其重新创建。

try语句块和异常处理

throw表达式

抛出异常状态,表达式一般为抛出的异常类型。

throw 异常类型("异常说明");

try语句块

处理异常。

try {
    ... // 正常执行的语句,包含throw表达式
}
catch (ErrType err) {
    cout << err.what() << endl; // 输出异常说明
    ... // 发生异常时执行的语句
}

what函数返回一个C风格字符串,其内容由异常类型和编译器决定。

练习代码

#include <iostream>
#include <vector>
#include <string>
#include <cctype>

using namespace std;

int main()
{
	/* 5.5*/
	const vector<string> scores{ "F","D","C","B","A","S" };
	const vector<int> grades{ 77,54,15,87,93,66,100,99 };
	vector<string> letterGrades;
	for (auto g : grades) {
		if (g < 60) {
			letterGrades.push_back(scores[0]);
		}
		else if (g < 70) {
			letterGrades.push_back(scores[1]);
		}
		else if (g < 80) {
			letterGrades.push_back(scores[2]);
		}
		else if (g < 90) {
			letterGrades.push_back(scores[3]);
		}
		else if (g < 100) {
			letterGrades.push_back(scores[4]);
		}
		else {
			letterGrades.push_back(scores[5]);
		}
	}
	letterGrades.push_back("//////////////////////////////////////////////////");
	for (auto g : grades) {
		string letterGrade = (g < 60) ? scores[0] : scores[(g - 50) / 10];
		letterGrades.push_back(letterGrade);
	}
	for (auto l : letterGrades) {
		cout << l << endl;
	}
	cout << "//////////////////////////////////////////////////" << endl;

	/* 5.9-5.10*/
	char word;
	int vowelCnt = 0;
	int spaceCnt = 0;
	int tabCnt = 0;
	int lfCnt = 0;
	// while (static_cast<int>(word = cin.get()) != -1) { // 非终止符时继续输入,存在问题:当终止符在有其他字符的行未换行输入时未生效,要再换行输入终止符并回车才生效。
	while (false) {
		switch (word) {
		case 'a': case 'e': case 'i': case 'o': case 'u': case 'A': case 'E': case 'I': case 'O': case 'U':
			++vowelCnt;
			break;
		case '\x20':
			++spaceCnt;
			break;
		case '\x09':
			++tabCnt;
			break;
		case '\x0a':
			++lfCnt;
			break;
		default:
			break;
		}
	}
	cout << "vowel : " << vowelCnt << "\nspace : " << spaceCnt << "\ntab : " << tabCnt << "\nlf : " << lfCnt << endl;
	cout << "//////////////////////////////////////////////////" << endl;

	/* 5.11*/
	string words;
	int ffCnt = 0, flCnt = 0, fiCnt = 0;
	// while (getline(cin, words)) {
	while (false) {
		if (words.begin() != words.end() && words.begin() != words.end() - 1) {
			for (auto iter = words.begin(); iter != words.end() - 1; ++iter) {
				if ((*iter) == 'f') {
					switch (*(iter + 1)) {
					case 'f':
						++ffCnt;
						break;
					case 'l':
						++flCnt;
						break;
					case 'i':
						++fiCnt;
						break;
					default:
						break;
					}
				}
			}
		}
		else {
			continue;
		}
	}
	cout << "ffCnt : " << ffCnt << "\nflCnt : " << flCnt << "\nfiCnt : " << fiCnt << endl;
	cout << "//////////////////////////////////////////////////" << endl;

	/* 5.17*/
	const vector<int> vA{ 0,1,1,2 };
	const vector<int> vB{ 0,1,1,2,3,5,8 };
	string flag = "Yes.";
	for (auto itA = vA.begin(), itB = vB.begin(); itA != vA.end() && itB != vB.end(); ++itA, ++itB) {
		if (*itA != *itB) {
			flag = "No.";
			break;
		}
	}
	cout << flag << endl;
	cout << "//////////////////////////////////////////////////" << endl;

	/* 5.20-5.21*/
	string newWord;
	string oldWord = "";
	string repeatWord = "";
	// while (cin >> newWord) {
	while (false) {
		if (newWord == oldWord && isupper(newWord[0])) {
			repeatWord = newWord;
			break;
		}
		else {
			oldWord = newWord;
		}
	}
	if (repeatWord != "") {
		cout << "repeatWord : " << repeatWord << endl;
	}
	else {
		cout << "No repeat word." << endl;
	}
	cout << "//////////////////////////////////////////////////" << endl;

	/* 5.22*/
	// 计算num内正数的和
	const vector<int> num{ -5,-1,4,1,-2,9 };
	int sum = 0;
	for (auto n : num) {
		int sz = n;
		if (sz <= 0) {
			continue;
		}
		sum += sz; // 负数就跳过该句
	}
	cout << sum << endl; // 应该为14
	cout << "//////////////////////////////////////////////////" << endl;

	/* 5.23-5.25*/
	int numA, numB;
	cout << "Enter numA and numB:" << endl;
	// while (cin >> numA >> numB) {
	while (false) {
		try {
			if (numB == 0) {
				throw runtime_error("numB can't be 0.");
			}
			cout << "numA / num B = " << numA / numB << endl;
			break;
		}
		catch (runtime_error err) {
			cout << err.what() << "\nTry again ? Enter yes/no." << endl;
			char c;
			cin >> c;
			if (!cin || c == 'n') {
				break;
			}
		}
	}

	return 0;
}
posted @ 2020-11-30 10:53  1Shen  阅读(125)  评论(0)    收藏  举报