C++ Primer Plus 学习记录(第五章节-包含练习题答案)
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 学习记录(第五章节-包含练习题答案)相关推荐
- 《SysML精粹》学习记录--第五章
<SysML精粹>学习记录 第五章:用例图(Use Case Diagram) 用例图简介 用例图外框 小结 第五章:用例图(Use Case Diagram) 用例图简介 用例图可以 ...
- java学习记录十五:集合二Collections、Set、Map
java学习记录十五:集合二 一.Collections工具类 一.解释 二.常用方法 1.打乱集合顺序 2.按照默认规则排序 3.按指定规则排序 4.批量添加元素 二.可变参数 一.解释 二.写法 ...
- C++ primer (中文版-第五版 )练习题答案
C++ primer (中文版-第五版 ) 练习题答案 第1章 开始 1.4控制流 1.4.1节 while语句练习 1.4.2节 for语句练习 1.4.3节 读取数量不定的输入数据练习 1.4.4 ...
- 【C语言进阶深度学习记录】五 C语言中变量的属性
上一篇文章学习了C语言中的类型转换,点击链接查看:[C语言进阶深度学习记录]四 C语言中的类型转换. 文章目录 1 C语言的变量属性 1.1 auto关键字 1.2 register关键字 1.3 s ...
- 【哈佛大学:计算生物学 生物信息学】学习记录(五)
为什么没有(四)? (四)主要说的就是SAM格式,网上一搜就有,就没必要了 (五)就草草地记录了Chapter 4.1: RNA-Seq Applications - Chapter 5.2 Diff ...
- GAN学习记录(五)——循环生成对抗网络CycleGan
循环生成对抗网络CycleGan实现风格迁移 dataset https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets/vang ...
- Android Camera 流程学习记录(五)—— Camera.takePicture() 流程解析
简介 在前面的几篇笔记中,我已经把 Camera 控制流的部分梳理得比较清楚了.在 Camera 流程中,还有一个重要的部分,即数据流. Camera API 1 中,数据流主要是通过函数回调的方式, ...
- 【高斯和拉普拉斯为什么分别对应L2和L1?】差分隐私系统学习记录(五)
The Algorithmic Foundations of Differential Privacy (五) 写在前面的话 Laplace versus Gauss 什么是先验分布?后验分布?似然估 ...
- 恒星结构和演化-学习记录6-第五章-恒星核合成
第五章:恒星核合成 原子核结构基本图像 原子由核和电子构成,其中电子轨道的尺度为10−8cm10^{-8}cm10−8cm,核的尺度为10−13cm10^{-13}cm10−13cm.原子核由质子 ...
最新文章
- CUDA硬件架构知识
- tomcat升级后报错: Invalid character found in the request target.
- 通过Java字节码发现有趣的内幕之String篇(上)(转)
- jstat_使用jstat报告自定义JVM指标集
- wxWidgets:wxPen类用法
- 北航 2012 秋季 现代软件工程 团队项目要求
- 马斯克火箭 SpaceX-API、程序员优雅赚钱项目……GitHub 热点速览
- 利用 TypeConverter,转换字符串和各种类型只需写一个函数
- 麦本本从u盘启动计算机,麦本本怎么设计u盘启动顺序
- win7下maven安装
- 计算机电源24针,ATX电源20针和24针接口定义
- wilcoxon秩和检验--学习笔记
- GUTI,Globally Unique Temporary UE Identity,全球唯一临时UE标识。
- Python判断大小写和数字和常用方法
- 整理一篇很全面的iOS面试题
- ffmpeg 截取视频片段 - python
- 用c语言求元素移动的次数T(n),悬赏!求C语言大神帮忙,写一个数字推盘游戏的程序(N-puzzle) 具体的要求看图片...
- 发动机曲轴加工工艺与专用机床夹具设计(论文+CAD图纸+工序卡+过程卡+开题报告+任务书+翻译……)
- 北京AFC系统存在重大安全隐患
- 漫画:什么是红黑树?(整合版)