C++ Primer Plus 学习记录(第五章节-包含练习题答案)

  • 5.1 for循环
    • 5.1.1 for循环的组成部分
      • 1、for循环的组成部分所完成的步骤
      • 2、赋值表达式有值
      • 3、cout中显示布尔值
      • 4、C++中允许在for的初始化部分声明变量
    • 5.1.2 回到for循环
    • 5.1.3 修改步长
    • 5.1.4 使用for循环访问字符串
    • 5.1.5 递增运算符(++)和递减运算符(--)前缀和后缀
    • 5.1.6 副作用和顺序点(C++ 11不再使用顺序点概念)
    • 5.1.7 前缀格式和后缀格式区别,前缀效率高
    • 5.1.8 递增/递减运算符和指针
      • 1、同时使用*和++于指针:何时解除引用和递增(前缀比后缀优先级高)
    • 5.1.9 组合赋值运算符
      • 1、+=运算符
    • 5.1.10 复合语句(语句块)
      • 1、在语句块声明的变量
      • 2、在语句块内外同时声明一个变量
    • 5.1.11 其他语法技巧--逗号运算符
      • 1、逗号运算符使用例子
      • 2、逗号运算符(计算顺序,运行结果,优先级)
    • 5.1.12 关系表达式
    • 5.1.13 赋值、比较和可能犯的错误
    • 5.1.14 C-风格字符串的比较
      • 1、数组类型word == "mate"判断数组内容(word数组名)?解决方案
      • 2、显示字符串方式
      • 3、使用strcmp()检测相等或排列顺序
    • 5.1.15 比较string类字符串
  • 5.2 while循环
    • 5.2.1 for与while
      • 1、for循环和while循环之间存在三个差别:
      • 2、在设计循环时的指导原则
    • 5.2.2 等待一段时间:编写延时循环
      • 1、早期方法--循环计数延时
      • 2、如今方法--ctime系统计时
      • 3、使用clock()和ctime创建延时循环例子
      • 4、类型别名
  • 5.3 do while循环
  • 5.4 基于范围的for循环(C++11)
    • 1、对数组(或容器类,如vector和array)的每个元素执行相同的操作。for (double x : prices)
  • 5.5 循环和文本输入
    • 5.5.1 使用原始的cin进行输入
    • 5.5.2 使用cin.get(char)进行补救
    • 5.5.3 使用哪一个cin.get()
    • 5.5.4 文件尾条件(检测文件尾(EOF))
      • 1、EOF结束输入
      • 2、常见的字符输入做法
    • 5.5.5 另一个cin.get()版本
  • 5.6 嵌套循环和二维数组
    • 5.6.1 初始化二维数组
    • 5.6.5 使用二维数组
  • 5.7 总结
  • 5.8 复习题

5.1 for循环

5.1.1 for循环的组成部分

例子

#include <iostream>
int main()
{using namespace std;int i;for (i = 0; i < 5; i++)cout << "C++ knows loops.\n";cout << "C++ knows when to stop.\n";return 0;
}

1、for循环的组成部分所完成的步骤

1、设置初始值
2、执行测试,看看循环是否应当继续进行
3、执行循环操作
4、更新用于测试的值

2、赋值表达式有值

x = 20;//这个表达式的值为20
madis = (cooks = 4) + 3;//madis的值为7
x = y = z = 0;//允许存在,快速地将若干个变量设置成相同的值,赋值运算符从右向左结合。

注意:
<<运算符的优先级比表达式中使用的运算符高,因此代码使用括号获得正确的运算顺序。

3、cout中显示布尔值

使用cout.setf(ios_base::boolalpha)设置输出格式

#include <iostream>
int main()
{using namespace std;int x;cout << (x = 100) << endl;cout << (x < 3) << endl;cout.setf(ios_base::boolalpha);cout << (x < 3) << endl;return 0;
}

上述程序的输出为:

100
0
false

注意:C++表达式是值或值与运算符的组合,每个C++表达式都有值

4、C++中允许在for的初始化部分声明变量

for (int i = 0; i < 5; i++)cout << "C++ know loops.\n";
cout << i << endl;//不可以

声明的变量只存在于for语句中,也就是说,当程序离开循环后,这种变量将消失。

5.1.2 回到for循环

与数组协同使用中,应是表达式i < Size或者i <= Size - 1

5.1.3 修改步长

更新表达式可以是任何有效的表达式
检测不等通常比检测相等好,这是因为相等情况可能不会出现,那么此时循环就会一直进行下去,陷入死循环。

5.1.4 使用for循环访问字符串

#include <iostream>
#include <string>
int main()
{using namespace std;cout << "Enter a word: ";string word;cin >> word;for (int  i = word.size() - 1; i >= 0; i-- )//size()获得字符串中字符数,循环在初始化表达式中使用这个值,将i设置为字符串中最后一个字符的索引(不考虑空值字符)。//反向计数,递减运算符(--)cout << word[i];cout << "\nBye.\n";return 0;
}

5.1.5 递增运算符(++)和递减运算符(–)前缀和后缀

前缀(prefix)版本位于操作数前面,如++x
后缀(postfix)版本位于操作数后面,如x++

int a = 5,b = 0;
b = a++;//b = 5, a = 6
b = ++a;//b = 6, a = 6

5.1.6 副作用和顺序点(C++ 11不再使用顺序点概念)

副作用(side effect)指的是在计算表达式时对某些东西(如存储在变量中的值)进行了修改。
顺序点(sequence point)是程序执行过程中的一个点。

任何完整的表达式末尾都是一个顺序点。

    int a = 4 ,y;cout << (4 + a++) + (6 + a++);

结果是19

5.1.7 前缀格式和后缀格式区别,前缀效率高

在执行速度上两种格式有些细微的差别,用户定义模式不同:
前缀函数(++x)是将值加1,然后返回结果;
后缀函数(x++)是首先复制一个副本,将其加1,然后将复制的副本返回。
因此,对与类而言,前缀版本的效率要比后缀版本高。

5.1.8 递增/递减运算符和指针

将递增/递减运算符用于指针,指针的值增加其指向的数据类型占用的字节数

double arr[5] = {1, 2, 3, 5, 5};
double *pt = arr;  //pt指向arr[0] = 1
++pt;             //pt指向arr[1] = 2

1、同时使用*和++于指针:何时解除引用和递增(前缀比后缀优先级高)

这取决于运算符的位置和优先级
前缀递增、前缀递减和解除引用运算符的优先级相同,以从右到左的方式进行结合。
后缀递增和后缀递减的优先级相同,但比**前缀运算符的优先级高**,这两个运算符以从左到右的方式进行结合。
 double x = *++pt;//x = arr[2]值为3++*pt; //意味着先取得pt指向的值,然后这个值加1,即3 + 1 = 4,在这种情况下,pt仍指向arr[2](*pt)++;//首先括号对指针解除引用,得到4,然后将这个值递增为5.pt仍指向arr[2]x = *pt++;//x = arr[2]为5.但是该语句执行完毕后,pt的值将为arr[3]的地址

5.1.9 组合赋值运算符

1、+=运算符

i += by;//i = i + by;
int k = 5;
k += 3;               //k为8
int *pa = new int[10]; //pa指向pa[0]
pa[4] = 12;
pa[4] += 6;               //pa[4]设置为18
*(pa + 4) += 7;          //pa[4]设置为25
pa += 2;              //pa指向pa[2]
34 += 10;             //错误

5.1.10 复合语句(语句块)

1、在语句块声明的变量

在语句块中定义一个新的变量,则仅当程序执行该语句块中的语句时,该变量才存在。执行完该语句块后,变量将被释放,这表明此变量仅在该语句块中才是可用的:

#include <iostream>
int main()
{using namespace std;int x = 20;{int y = 100;cout << x << endl;cout << y << endl;}cout << x << endl;cout << y << endl;//不行,无法编译
}

在外部语句块中定义的变量在内部语句块中也是被定义了的。

2、在语句块内外同时声明一个变量

如果一个语句块中声明一个变量,而外部语句块中也有一个这种名称的变量,情况如何?
在声明位置到内部语句块结束的范围之内,新变量将隐藏就变量;然后旧变量再次可见:

#include <iostream>
int main()
{using std::cout;using std::endl;int x = 20;               //旧x{                       //语句块开始cout << x << endl;   //调用旧xint x = 100;     //定义新xcout << x << endl;    //调用新x}                     //语句块结束cout << x << endl;       //使用旧xreturn 0;
}

5.1.11 其他语法技巧–逗号运算符

1、逗号运算符使用例子

下述程序将一个string类对象的内容反转

#include <iostream>
#include <string>
int main()
{using namespace std;string word;cin >> word;char temp;int i, j;for (j = 0, i = word.size() - 1; j < i; --i, ++j)//使用了两个逗号运算符,在这里,逗号是一个运算符{temp = word[i];word[i] = word[j];word[j] = temp;}cout << word << "\nDone\n";return 0;
}

运行结果:

stressed//输入desserts
Done

也可以使用

int j = 0, i = word.size() - 1;//但是这样看起来乱,在这里,逗号只是一个列表分隔符,而不是逗号运算符

2、逗号运算符(计算顺序,运行结果,优先级)

首先,它确保先计算第一个表达式,然后计算第二个表达式:

i = 20, j = 2 * i;//首先设置i为20,然后j为40

然后,逗号表达式的值是第二部分的值,上述表达式的值为40

在所有的运算符中,逗号运算符的优先级是最低的,如

cats = 17, 240;

被解释为:

(cats = 17), 240;//cats设置为17,240不起作用,但是该表达式的值为240

5.1.12 关系表达式

<
<=
==
>
>=
!=

关系运算符的优先级比算术运算符低。即

x + 3 > y - 2;

等价于

(x + 3) > (y - 2)

5.1.13 赋值、比较和可能犯的错误

不要混淆等于运算符(==)和赋值运算符(=)
可以将任何有效的C++表达式用作for循环的测试条件

不要使用=来比较两个量是否相等,而要使用==

可以设计一种保护数组来防止这种错误,第13章提供这样的一个例子

循环需要测试数组的值和索引的值,第6章介绍如何使用逻辑运算符将两个这样的测试合并为一个条件

5.1.14 C-风格字符串的比较

1、数组类型word == "mate"判断数组内容(word数组名)?解决方案

假设要知道字符数组中的字符串是不是mate,如果word是数组名:

word == "mate"

数组名是地址,用引号括起的字符串常量也是其地址。
因此,上面的关系表达式不是判断两个字符串是否相同,而是查看它们是否存储在相同的地址上。
那么两个字符串的地址是否相同?答案是否定的,虽然它们包含相同的字符

解决方案
使用C-风格字符串库中的strcmp()函数来比较。要包含头文件cstring
该函数接受两个字符串地址作为参数。这意味着可以是指针、字符串常量或字符数组名。
如果两个字符串相同,该函数将返回零
如果第一个字符串按字母顺序排在第二个字符串之前,则strcmp()返回一个负数值;
如果第一个字符串按字母顺序排在第二个字符串之后,则strcmp()返回一个正数值。
“按系统排列顺序”比“按字母顺序”更准确,是按照系统编码来的,大写字母都比小写字母小,所以大写字母位于前,大小写也是不同的。
例如:“Zoo”在“aviary”之前

2、显示字符串方式

for (ch = 'a'; ch <= 'z'; ch++)cout << ch;

3、使用strcmp()检测相等或排列顺序

如果str1和str2相等,则下面的表达式为true:

strcmp(str1, str2) == 0;

如果str1和str2不相等,则下面两个表达式都为true

strcmp(str1, str2) != 0;
strcmp(str1, str2);

如果str1在str2的前面,则下面表达式为true

strcmp(str1, str2) < 0;

如果str1在str2的后面,则下面表达式为true

strcmp(str1, str2) > 0;

5.1.15 比较string类字符串

类函数重载(重新定义)了这些运算符

word != "mate";//word是string格式

至少有一个操作数是string对象,另一个操作数可以是string对象,也可以是C-风格字符串
可以把string对象看作一个数组使用
一般对于非计数循环,使用while多一点

5.2 while循环

while循环是没有初始化和更新部分的for循环,他只有测试条件和循环体:

while (test-condition)body

5.2.1 for与while

在C++中,for与while循环本质上是相同的。

1、for循环和while循环之间存在三个差别:

a、在for循环中省略了测试条件时,将认为条件为true
b、在for循环中,可使用初始化语句声明一个局部变量,但在while循环中不能这样做
c、如果循环体中包括continue语句,情况将稍有不同(第6章节讨论)
d、使用for循环来为循环计数,因为for循环格式允许将所有相关的信息-初始值、终止值和更新计数器的方法-----放在同一个地方。
e、在无法预先直到循环将执行的次数时,常使用while循环

2、在设计循环时的指导原则

a、指定循环终止的条件
b、在首次测试之前初始化条件
c、在条件被再次测试之前更新条件

5.2.2 等待一段时间:编写延时循环

1、早期方法–循环计数延时

long wait = 0;
while (wait < 10000)wait++;

但是这种方法在不同的计算机处理器上,有不同的效果,更好的方法是让系统时钟来完成这种工作。

C++库中有一个函数有助于完成这样的工作。
这个函数名为clock(),返回程序开始执行后所用的系统时间。有两个问题:
a、clcok ()返回时间的单位不一定是秒
b、函数的返回类型在某些系统中是long,有可能是unsigned long或其他类型

2、如今方法–ctime系统计时

头文件ctime(较早的为time.h)提供了这些问题的解决方案。
a、首先,它定义了一个符号常量—CLOCKS_PER_SEC,该常量等于每秒钟包含的系统时间单位数。因此,将系统时间除以这个值,可以得到秒数。或者将秒数乘以CLOCKS_PER_SEC,可以得到以系统时间单位为单位的时间。
b、其次,ctime将clock_t作为clock()返回类型的别名(本章后面介绍“类型别名”),这意味着可以将变量声明为clock_t类型,编译器将把它转换为long、unsingned int或适合系统的其他类型。

3、使用clock()和ctime创建延时循环例子

#include <iostream>
#include <ctime>
int main()
{using namespace std;cout << "Enter the delay time, in seconde: ";float secs;cin >> secs;clock_t delay = secs * CLOCKS_PER_SEC;cout << "starting\a\n";clock_t start = clock();while(clock() - start < delay) ;cout << "dene \a\n";return 0;
}

该程序以系统时间单位为单位(不是秒)计算延时时间,避免了在每轮循环中将系统时间转换为秒。

4、类型别名

C++为类型建立别名的方式有两种。

一种是使用预处理器:

#define BYTE char//这样,预处理器将在编译程序时用char替换所有的BYTE,从而使BYTE成为char的别名。

第二种方法是使用C++(和C)的关键字typedef来创建别名。

typedef char byte;//将byte作为char的别名
typedef char * byte_pointer;//让byte_pointer成为char指针的别名

通用格式是:

typedef typeName aliasName;//将aliasName作为typeName类型的别名

这两者的区别是:对于指针变量的类型别名,虽然也可以使用#define,不过声明一系列变量时,这种方法不适用,如下:

#define FLOAT_POINTER float *
FLOAT_POINTER pa,pb;

预处理器置换将该声明转换为:

float * pa,pb;//pa是一个指向float的指针,pb是一个float变量

但是typedef不会有这样的问题。他能偶处理更复杂的类型别名。所以,typedef更好用。

5.3 do while循环

do while 循环是出口条件(exit condition)循环,这种循环将首先执行循环体,然后再判定测试表达式,决定是否应继续执行循环。如果条件为false,则循环终止;否则,进行新一轮的执行和测试。

这种循环通常至少执行一次,因此其程序流必须经过循环体后才能达到测试条件。

dobody
while (test-expression);

入口条件循环在循环开始之前对条件进行检查;但有时候do while测试更合理,比如,请求用户输入时,程序必须先获得输入,然后对它进行测试。

5.4 基于范围的for循环(C++11)

C++11新增了一种循环:基于范围(range-based)的for循环。简化为:

1、对数组(或容器类,如vector和array)的每个元素执行相同的操作。for (double x : prices)

double prices[5] = {4.99, 10.99, 6.87, 7.99, 8.49};
for (double x : prices)cout << x << std::endl;

其中,x最初表示prices的第一个元素。显示第一个元素后,不断执行循环,而x依次表示数组的其他元素。

要修改数组的元素,需要使用不同的循环变量语法:

for (double &x : prices)x = x * 0.80;

符号&表明x是一个引用变量(第8章讨论),第一种语法不能修改数组的内容。

还可以使用基于范围的for循环和初始化列表

for (int x : {3, 5, 2, 8, 6})cout << x << " ";
cout << '\n';

5.5 循环和文本输入

5.5.1 使用原始的cin进行输入

必须要知道何时停止读取?—一种方法是选择某个特殊字符–有时被称为哨兵字符(sentinel character),将其作为停止标记。

#include <iostream>
int main()
{using namespace std;char ch;int count = 0;cout << "Enter characters;enter # to quit:\n";cin >> ch;while(ch != '#')//输入在遇到#字符时停止读取输入,计算读取到的字符数,并显示这些字符。{cout << ch;++count;cin >> ch;}cout << endl << count << " characters read\n";return 0;
}

程序的运行结果:

程序说明
a、使用的是入口条件循环,所以要在循环之前读取第一个输入字符,第一个是#可以跳过整个循环
b、遵循了循环的指导原则
c、上述合情合理,但是可以看到输出时为什么省略了空格?-------这是因为cin,读取char时,与读取其他基本类型一样,cin将忽略空格和换行符。因此输入中的空格没有被回显,也没有被包含在计数内。
d、更重要的是,发送给cin的输入被缓冲,只有用户按下回车键,输入的内容才会被发送给程序。这也就是在运行程序时,可以#后面输入字符的原因。

5.5.2 使用cin.get(char)进行补救

istream类(在iostream中定义)中包含一个能偶满足这种要求的成员函数。
成员函数cin.get(ch)读取输入中的下一个字符(即使他是空格),并将其赋给变量ch

#include <iostream>
int main()
{using namespace std;char ch;int count = 0;cout << "Enter characters;enter # to quit:\n";cin.get(ch);while(ch != '#')//输入在遇到#字符时停止读取输入,计算读取到的字符数,并显示这些字符。{cout << ch;++count;cin.get(ch);}cout << endl << count << " characters read\n";return 0;
}

下面是该程序的运行情况:

该程序回显每个字符,并全部字符计算在内,其中包括空格。但是输入仍被缓冲。

5.5.3 使用哪一个cin.get()

cin.get(name, ArSize).get();

相当于两个连续的函数调用:

cin.get(name, ArSize);
cin.get();

cin.get()的一个版本接受两个参数:数组名(字符串(char * 类型)的地址)和ArSize(int类型的整数)。(数组名是其第一个元素的地址,因此字符数组名的类型为char * 。)接下来,程序使用了不接受任何参数的cin.get()。
前面也使用了cin.get():

char ch;
cin.get(ch);

这里的cin.get()接受一个char参数。
之所以可以选择不用数量的参数,因此C++语言支持被称为函数重载的OOP特性。
函数重载允许创建多个同名函数,条件是他们的参数列表不同,第8章讨论。

5.5.4 文件尾条件(检测文件尾(EOF))

a、很多操作系统都支持重定向,允许用文件替换键盘输入。
假设在Windows中有一个名为gofish.exe的可执行程序和一个名为fishtale的文本文件,则可以在命令提示符模式下输入下面的命令:

gofish <fishtale

这样,程序将从fishtale文件(而不是键盘)获取输入。<符号是Unix和Windows命令提示符模式的重定向运算符。

b、检测到EOF后,cin将两位(eofbit和failbit)都设置为1。
c、可以通过成员函数eof()来查看eofbit是否被设置;
d、如果检测到EOF,则cin.eof()将返回bool值true,否则返回false。
e、如果eofbit或failbit被设置为1,则fail()成员函数返回true,否则返回false。
f、eof()和fail()方法报告最近读取的结果;因此应将cin.eof()和cin.fail()测试放在读取后。
g、fail()可用于更多的实现中。
h、可以使用cin.clear()来重置输入流,6和16章介绍

程序例子5.18:

#include <iostream>
int main()
{using namespace std;char ch;int count = 0;cout << "Enter characters;enter # to quit:\n";cin.get(ch);while(cin.fail() == false)//可以写成----while (!cin.fail()){cout << ch;++count;cin.get(ch);}cout << endl << count << " characters rsdead\n";return 0;
}

运行情况:

windows10上,按下Ctrl+Z+Enter来模拟EOF条件。

1、EOF结束输入

设置EOF后,无法在进行输入,cin.clear(0方法可能清楚EOF标记,但是有些系统按Ctrl+Z实际上将结束输入和输出(比如本机),而cin.clear()将无法恢复输入和输出。

2、常见的字符输入做法

程序5.18中使用的是:

while (cin.fail() == false)

简捷方式如:

while (!cin.fail())

方法cin.get(char)的返回值返回的是一个cin对象。istream类提供了一个可以将istream对象(如cin)转换成bool值的函数;

当cin出现需要bool值得地方时,该转换函数将被调用。如果最后一次读取成功了,则转换得到的bool值为true,否则为false。综上,上述while可以写为:

while (cin)

这比cin.fail()或!cin.eof()更通用,因为它可以检测到其他失败原因,比如磁盘故障。

由于cin.get(char)的返回值为cin,因此可以将循环精简为这种格式:

while (cin.get(ch))
{...//这里不再需要cin.get(ch)
}

这样,cin.get(char)只调用一次,不是两次:循环前一次,循环结束后一次。

为判断循环测试条件,程序必须首先调用cin.get(ch)。如果成功,则将值放入ch中;
然后,程序获得函数调用的返回值,即cin;
下面程序对cin进行bool转换,输入成功,结果为true,否则为false。
实现三条指导原则(确定约束条件、对条件进行初始化以及更新条件)全部放在循环测试条件中。

5.5.5 另一个cin.get()版本

1、不接受任何参数的cin.get()成员函数返回输入中的下一个字符。也可以是可以使用:

ch = cin.get();//将字符编码作为int值返回

2、可以使用cout.put()函数来显示字符:

cout.put();//参数类型为char,而不是int

最初,put()只有一个原型–put(char),可以传递一个int参数给它,该参数将被强制转换为char。

但是有些C++实现提供了3个原型:put(char)、put(signed char)和put(unsigned char)。所以传递一个int参数将导致错误消息,因为转换int的方式不止一种。

可以使用显示强制类型转换的原型(如cin.put(ch))可使用int参数

3、cin.get()如何处理EOF条件

当函数到达EOF时,将没有可返回的字符。

相反,cin.get()将返回一个用符号常量EOF表示的特殊值。该常量是在头文件iostream定义的

EOF值必须不同于任何有效的字符值,以便程序不会将EOF与常规字符混淆。

一般被定义为-1。这是因为ASCⅡ码没有为-1的字符,不需要直到实际的值,只需在程序中使用EOF即可。

程序清单5.18中:

char ch;
cin.get(ch);
while (cin.fail() == false)
{cout << ch;++count;cin.get(ch);
}

可以使用int ch,并用cin.get()代替cin.get(char),用cout.put()代替cout,用EOF测试代替cin.fail()测试:

int ch;
ch = cin.get();
while (ch != EOF)
{cout.put(ch);++count;ch = cin.get();
}

需要知道的是,EOF不表示输入中的字符,而是指出没有字符。

4、注意char的类型
由于EOF表示的不是有效字符编码,因此可能不与char类型兼容。

在有些系统中,char类型是没有符号的,因此char变量不可能为EOF值(-1).

因此,如果使用cin.get()(没有参数)并测试EOF,则必须将返回值赋给int变量,而不是char变量。

如果将ch的类型声明为int,而不是char,则必须在显示ch时将其强制转换为char类型。

#include <iostream>
int main(void)
{using namespace std;int ch;int count = 0;while ((ch = cin.get()) != EOF){cout.put(char(ch));++cout;}cout << endl << count << " characters read\n";return 0;
}

如果使用cin.get()来所著屏幕直到可以阅读它,这将不起作用,因为检测EOF时将禁止进一步读取输入。
可以使用while计时循环留住屏幕,也可以使用第17章的cin.clear()来重置输入流。

5、cin.get()和cin.het(ch)

使用字符参数的版本更符合对象方式,因为其返回值是istream对象。可以将其拼接起来:

cin.get(ch1).get(ch2);//函数调用cin.get(ch1)返回一个cin对象,然后便可以通过该对象调用get(ch2)

6、get()主要用途
get()的主要用途是能偶将stdio.h的getchar()和putchar()函数转换为iostream的cin.get()和cout.get()方法。

记得头文件iostream替换为stdio.h

5.6 嵌套循环和二维数组

例子,存储5个城市在4年间的最高温度

int maxtemps[4][5];//maxtemps是一个包含4个元素的数组,其中每个元素都是一个由5个整数组成的数组。
//可以将maxtemps数组看作是由4行组成,其中每一行有5个温度值。

要打印整个二维数组:

for (int row = 0; row < 4; row++)
{for (int col = 0; col < 5; ++ col)cout << maxtemps[row][col] << "\t";cout  << endl;
}

5.6.1 初始化二维数组

int maxtemps[4][5] =
{{96, 100, 87, 101, 105},{96, 98, 91, 107, 104},{97, 101, 93, 108, 107},{98, 103, 95, 109, 108}
};

每行数据应各占一行,这样阅读起来更容易

5.6.5 使用二维数组

且看程序清单5.20:
初始化了一个二维数组,使用了一个嵌套循环;

循环的顺序相反,将列循环(城市索引)放在了外面,行循环(年份循环)放在内面;

将一个指针数组初始化为一组字符串常量,即将cities声明为一个char指针数组,其中的每个元素(如cities[0])都是一个char指针,可被初始化为一个字符串的地址。

cities[0]初始化为字符串“Gribble City”的地址,该指针数组的行为与字符串数组类似。

程序清单5.20

#include <iostream>
const int Cities = 5;
const int Years = 4;int main()
{using namespace std;const char * cities[Cities] = {"Gribble City","Gribblentown","New Gribble","San Gribble","Gribble Vista"};int maxtemps[Years][Cities] = {{96, 100, 87, 101, 105},{96, 98, 91, 107, 104},{97, 101, 93, 108, 107},{98, 103, 95, 109, 108}};cout << "Maxinum temperatures for 2008 - 2011\n\n";for (int city = 0; city < Cities; ++city){cout << cities[city] << ":\t";for (int year = 0![请添加图片描述](https://img-blog.csdnimg.cn/65929f1126c74d17b4069dd80af8ed70.png)
; year < Years; ++year)cout << maxtemps[year][city] << "\t";cout << endl;}//cin.get();return 0;
}

下面是该程序的输出:

输出中使用制表符比使用空格可使数据排列更有规则。但是制表符设置不相同,输出的外观也会有所不同。17章介绍,更精确的、更复杂的、对输出进行格式化的方法。

可以使用char数组的数组,而不是字符串指针数组,声明如下:

char cities[Cities][25] =
{"Gribble City","Gribblentown","New Gribble","San Gribble","Gribble Vista"
};

上述方法将全部5个字符串的最大长度限制为24个字符。指针数组存储5个字符串的地址,而使用char数组的数组时,将5个字符串分别复制到5个包含25个元素的char数组中。
指针数组更为经济,如果要修改其中的任何一个字符串,二维数组更好。
虽然有所不同,但是这两种方法使用相同的初始化列表,显示字符串的for循环代码相同。

此外,还可以使用string对象数组,声明如下:

const string cities[Cities] =
{"Gribble City","Gribblentown","New Gribble","San Gribble","Gribble Vista"
};

如果希望字符串是可以修改的,省略限定符const即可。初始化列表和用于显示字符串的for循环代码与前两种方法中相同。
在希望字符串可修改的情况下,string类自动调整大小使得其比二维数组更方法。

5.7 总结


5.8 复习题


参考答案:

1、输入条件循环在进入输入循环体之前将评估测试表达式。如果条件最初为false,则循环不会执行其循环体。

退出条件循环在处理循环体之后评估测试表达式。因此,即使 测试表达式最初为false,循环也将执行一次。

for和while循环都是输入条件循环,而do while循环是退出条件循环。

2、

01234

3、

0369
12

4、

6
8

5、

k = 8

6、

for (int i = 1; i <= 64; i *= 2)cout << i << "、";

7、
将语句放在一对大括号中将形成一个符合语句或代码块
8、
第一条语句当然有效。表达式1,024由两个表达式租车—1和024,用逗号运算符连接,值为右侧表达式的值。这是024八进制,十进制为20,因此该声明是将20赋给X。

第二条语句也是有效的,然而,运算符优先级将导致它被判定为这样:

(y = 1),024;

也就是说左侧表达式y设置为1,整个表达式为024,十进制是20。

9、
cin>>ch将跳过空格、换行符和制表符,其他两种格式将读取这些字符。

C++ Primer Plus 学习记录(第五章节-包含练习题答案)相关推荐

  1. 《SysML精粹》学习记录--第五章

    <SysML精粹>学习记录 第五章:用例图(Use Case Diagram) 用例图简介 用例图外框 小结 第五章:用例图(Use Case Diagram) 用例图简介   用例图可以 ...

  2. java学习记录十五:集合二Collections、Set、Map

    java学习记录十五:集合二 一.Collections工具类 一.解释 二.常用方法 1.打乱集合顺序 2.按照默认规则排序 3.按指定规则排序 4.批量添加元素 二.可变参数 一.解释 二.写法 ...

  3. C++ primer (中文版-第五版 )练习题答案

    C++ primer (中文版-第五版 ) 练习题答案 第1章 开始 1.4控制流 1.4.1节 while语句练习 1.4.2节 for语句练习 1.4.3节 读取数量不定的输入数据练习 1.4.4 ...

  4. 【C语言进阶深度学习记录】五 C语言中变量的属性

    上一篇文章学习了C语言中的类型转换,点击链接查看:[C语言进阶深度学习记录]四 C语言中的类型转换. 文章目录 1 C语言的变量属性 1.1 auto关键字 1.2 register关键字 1.3 s ...

  5. 【哈佛大学:计算生物学 生物信息学】学习记录(五)

    为什么没有(四)? (四)主要说的就是SAM格式,网上一搜就有,就没必要了 (五)就草草地记录了Chapter 4.1: RNA-Seq Applications - Chapter 5.2 Diff ...

  6. GAN学习记录(五)——循环生成对抗网络CycleGan

    循环生成对抗网络CycleGan实现风格迁移 dataset https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets/vang ...

  7. Android Camera 流程学习记录(五)—— Camera.takePicture() 流程解析

    简介 在前面的几篇笔记中,我已经把 Camera 控制流的部分梳理得比较清楚了.在 Camera 流程中,还有一个重要的部分,即数据流. Camera API 1 中,数据流主要是通过函数回调的方式, ...

  8. 【高斯和拉普拉斯为什么分别对应L2和L1?】差分隐私系统学习记录(五)

    The Algorithmic Foundations of Differential Privacy (五) 写在前面的话 Laplace versus Gauss 什么是先验分布?后验分布?似然估 ...

  9. 恒星结构和演化-学习记录6-第五章-恒星核合成

    第五章:恒星核合成 原子核结构基本图像   原子由核和电子构成,其中电子轨道的尺度为10−8cm10^{-8}cm10−8cm,核的尺度为10−13cm10^{-13}cm10−13cm.原子核由质子 ...

最新文章

  1. CUDA硬件架构知识
  2. tomcat升级后报错: Invalid character found in the request target.
  3. 通过Java字节码发现有趣的内幕之String篇(上)(转)
  4. jstat_使用jstat报告自定义JVM指标集
  5. wxWidgets:wxPen类用法
  6. 北航 2012 秋季 现代软件工程 团队项目要求
  7. 马斯克火箭 SpaceX-API、程序员优雅赚钱项目……GitHub 热点速览
  8. 利用 TypeConverter,转换字符串和各种类型只需写一个函数
  9. 麦本本从u盘启动计算机,麦本本怎么设计u盘启动顺序
  10. win7下maven安装
  11. 计算机电源24针,ATX电源20针和24针接口定义
  12. wilcoxon秩和检验--学习笔记
  13. GUTI,Globally Unique Temporary UE Identity,全球唯一临时UE标识。
  14. Python判断大小写和数字和常用方法
  15. 整理一篇很全面的iOS面试题
  16. ffmpeg 截取视频片段 - python
  17. 用c语言求元素移动的次数T(n),悬赏!求C语言大神帮忙,写一个数字推盘游戏的程序(N-puzzle) 具体的要求看图片...
  18. 发动机曲轴加工工艺与专用机床夹具设计(论文+CAD图纸+工序卡+过程卡+开题报告+任务书+翻译……)
  19. 北京AFC系统存在重大安全隐患
  20. 漫画:什么是红黑树?(整合版)

热门文章

  1. 合作案例 | 慧通差旅助力中核集团,打造智能化差旅平台
  2. 2022最新知识付费变现小程序+卡密独立版
  3. openfire好友关系解析
  4. 使用telnet检测网络丢包情况
  5. 毫米波雷达DAC1000EVM预备知识自觉(笔者自学笔记)
  6. 公路可视化景观设计解决方案
  7. 华南X79主板刷黑后恢复一例
  8. 如何制作微课?详解:微课视频制作方法之微课制作软件
  9. java1到100的阶乘之和
  10. linux cpu跑分软件,Geekbench 5 5.2.3 硬件性能跑分工具 特别版