为节约时间,我把书中一些做了标注的地方按顺序罗列下来。
要点
循环类型:①入口条件循环:for、while;②do-while
-
格式规范:C++中,通常在for和括号之间加一个空格,而省略函数名与括号之间的空格
for (i = 6; i < 10; ++i) //for和括号之间加一个空格 smart_function(i); //函数名与括号之间无空格
-
cout.setf(ios:: boolalpha);
:设置了一个标记,该标记命令cout显示true和false,而不是1和0 -
for (int i = 0; i < 5; ++i)
这种声明语句表达式只有在C++中合法,在C中是非法的(须写成for (i = 0; i < 5; ++i)
) -
有些较老的C++实现遵循以前的规则,对于循环
for (int i = 0; i < 5; ++i)
,将把i视为是在循环之前声明的,因此在循环结束后,i仍可用 -
测试表达式中,检测不等(>、<等等)通常要比检测相等好
-
++与- - : 以下这条语句在不同的系统上将生成不同的结果:
x = 2 * x++ * (3 - ++x);
,对此,C++没有定义正确的行为 -
对于针对类定义的运算符,在循环的更新表达式中,前缀版本
++i
通常会比后缀版本i++
快一些。对于内置类型和当代编译器则基本没啥差别 -
前缀递增、前缀递减和解除引用运算符的优先级相同,以从右到左的方式进行结合。后缀递增和后缀递减的优先级相同,但比前缀运算符的优先级高,这两个运算符以从左到右的方式进行结合
对此我写了一个小程序来探讨这种单目运算符的优先级:#include<iostream> using namespace std; int main(){ int x[5]{ 1,5,8,20,115}; int* pt; pt=x+1; int ans= ++*pt++; //ans= 6 *pt= 8 //int ans= *(++pt)++; //ans= 8 *pt= 20 //int ans = (*++pt)++; //ans= 8 *pt= 9 //int ans = *++pt++; //INVALID int y=5; cout<<"ans= "<<ans<<endl; cout<<"*pt= "<<*pt<<endl; return 0; }
-
逗号的作用:①逗号运算符:合并两个表达式为一个,如
++j, --i;
②逗号分隔:int i, j;
逗号表达式的值为第二部分的值,且作为运算符时优先级最低 -
在循环内声明简单变量通常会比在循环前声明该变量的速度要慢,因为如果在循环内声明,该变量在每轮循环都会被分配和释放
-
for循环的几种写法:①
for (int i=0, j=5; ;)
②int i, j; for (i=0,j=5; ;)
③for (; ;++i, --j)
-
C-风格字符串不能用==判断字符串相等(须用strcmp()进行比较),因为没有相关的运算符重载,但string类型有,如
string word; word != "mate";
表达式要求:至少有一个操作数为string对象,另一个操作数可以是string对象,也可以是C风格字符串 -
for循环中省略测试条件时,将认为条件为true
-
用#define需谨慎,最好用typedef定义类型别名。以下pb是float类型而非float*类型
#define FLOAT_POINTER float * FLOAT_POINTER pa, pb; // not expected FLOAT_POINTER pa, *pb; //typedef float* FLOAT_POINTER; // GREAT MEANS
-
基于范围的for循环(C++11):①
for (double x : prices)
;②for (double &x : prices)
;③for (int x : {4, 3, 9, 6})
; -
cin读取char值时,与读取其他类型一样,会忽视空格与换行符
以下代码中主要讨论几种cin.get()的重载#include<iostream> #include<string> using namespace std; int main(){ const int ArrSize = 20; char name1[ArrSize]; char name2[ArrSize]; char name3[ArrSize]; /* //Method1 correct cin.get(name1,ArrSize).get(); cin.get(name2,ArrSize).get(); cin.get(name3,ArrSize).get(); */ //Method2 with problems cin.get(name1,ArrSize); cin.get(name2,ArrSize); cin.get(name3,ArrSize); cout<<"name1= "<<name1<<endl; cout<<"name2= "<<name2<<endl; cout<<"name3= "<<name3<<endl; return 0; }
-
cin.get(char)
的返回值为cin对象,然而istream类提供了一个可将istream对象(如cin)转换为bool值的函数,如果最后一次读取成功了,则转换得到的bool值为true,否则为false -
文件尾的几种判断:①
while (cin.fail() == false) or while (cin.eof() == false)
fail()和eof()都是事后报告结果②while (cin)
比前者更通用,因为它可以检测到其它失败原因,如磁盘故障;③while (cin.get(ch))
测试表达式中同时实现了三条指导原则(确定结束条件、对条件初始化以及更新条件);④while (ch != EOF)
;⑤while ((ch = cin.get()) != EOF)
,注意括号一个不能少 -
模拟EOF条件:Ctrl+Z和回车(不同系统可能对是否回车要求不同),在有些系统中,Ctrl+Z实际将结束输入输出,而cin.clear()将无法恢复输入和输出
-
cout.put(ch);
由于put()有三种原型,对应参数分别为char
、signed char
和unsigned char
,因此如果传入的参数为int,须进行强制类型转换,如cout.put(char(ch));
-
在有些系统中,char类型是无符号的,因此char变量不可能为EOF值(-1)。出于此原因,如果使用cin.get()并测试EOF,则必须将返回值赋给int型变量,而不是char变量(见第18条序号⑤);另外,如果声明的是int变量而非char变量,需要显示字符时需要进行强制类型转换
-
cin.get()与cin.get(ch)的区别见下表
属 性 | cin.get(ch) | ch = cin.get() |
传递输入字符的方式 | 赋给参数ch | 将函数返回值赋给ch |
用于字符输入时函数的返回值 | istream对象(执行bool转换后返回值为true) | int类型的字符编码 |
到达EOF时函数的返回值 | istream对象(执行bool转换后返回值为true) | EOF |
- 指针数组与二维数组(char*[] 与 char[][]):从存储空间角度来说,指针数组比二维数组更为经济,但如果要修改其中任一字符串,则二维数组是更好的选择
习题
习题参考代码见我的github(上传后会把链接打上)
欢迎各位大佬们于评论区进行批评指正~