- for循环
- 表达式和语句
- 递增运算符和递减运算符:++ 和 - -
- 组合赋值运算符
- 复合语句(语句块)
- 逗号运算符
- 关系运算符:>、>=、==、<=、< 和 !=
- while循环
- typedef工具
- do while 循环
- 字符输入方法get()
- 文件尾条件
- 嵌套循环和二维数组
1. for循环
for循环是入口条件循环,这意味着在每次执行循环体之前,都将计算测试表达式的值,当测试表达式的值为false时,将不会执行循环体。
for(cin>>x; x==0; cin >>x) ,输入0,才会继续循环,一旦不输入0,就会退出循环。
C++ 11 新特性:基于范围的 for 循环
double prices[5] = {4.99, 10.99, 6.87, 7.99, 8.49};
for (double x : prices)
cout << x << std::endl;
要修改数组的元素,需要使用不同的循环变量语法:
for (double &x : prices)
x = x * 0.80;
符号&表明x是一个引用变量,这个主题将在第8章讨论。就这里而言,这种声明让接下来的代码能够修改数组的内容,而第一种语法不能。
还可以结合使用基于范围的 for 循环和初始化列表:
for (int x : { 3, 5, 2, 8, 6})
cout << x << " ";
cout << '\n';
2.表达式和语句
x=20
C++将赋值表达式的值定义为左侧成员的值,因此这个表达式的值为20。由于赋值表达式有值,因此可以编写下面这样的语句:
maids = (cooks = 4) + 3;
表达式 cooks=4 的值为4,因此 maids 的值为7。然而,C++虽然允许这样做,但并不意味着应鼓励这种做法。允许存在上述语句的原则也允许编写如下的语句:
x = y = z = 0;
这种方法可以快速地将若干变量设置为相同的值。赋值运算符是从右向左结合的,因此首先将 0 赋给 z,然后将 z=0 赋值给 y,以此类推。
像 x<y
这样的关系表达式将被判定为 bool 值 true 或 false。
cout 在显示bool值之前将它们转换为 int, 但cout.setf(ios_bass::boolalpha) 函数调用设置了一个标记,该标记命令cout显示 true 和 false,而不是 1 和 0;
注意,表达式和语句概念上的差别,从表达式到语句的转变很容易,只要加分号即可。因此
age = 100
是一个表达式,而
age = 100;
是一条语句。
3. 递增运算符 ++ 和递减运算符 - -
前缀版本: ++x, 先加后用
后缀版本: x++, 先用后加
注意:千万不要失去控制,在同一条语句对同一个值递增或者递减多次,例如,下面这条语句在不同的系统上将生成不同的效果:
x = 2 * x++ * (3 - ++ x);
递增递减运算符和指针:
double arr[5] = { 21.1, 32.8, 23.4, 45.2, 37.4};
double *pt = arr;
double x = * ++pt;
先将指向arr[1],再解引用,即x为arr[1]的值;
++ *pt;
先解引用,再递增,即将arr[1]的值加1;
(*pt)++;
将arr[1]的值加1
x = *pt++;
这个要注意,虽然先递增了pt,但是在该表达式中使用pt时,仍然使用pt之前的值,即所谓的先用后加,所以x的值是arr[1]的值,但该语句执行完之后,pt的值将为arr[2]的地址。
4. 组合赋值运算符
+=
-=
*=
/=
%=
5. 复合语句(语句块)
6. 逗号运算符
++j, --i
int i, j;
for (j=0, i = word.size() - 1; j<i; --i, ++j)
7. 关系运算符
<
<=
==
>
>=
!=
关系运算符的优先级比算术运算符低。这意味着表达式:
x + 3 > y - 2
对应于:
(x+3) > (y-2)
而不是:
x + (3>y) -2
由于将bool值提升为int后,表达式(3>y)要么为1, 要么为0,因此第二个和第三个表达式都是有效的。不过C++使第一个表达式等价于第二个表达式。
for 循环的灵活设计让用户很容易出错。如果不小心遗漏了 == 运算符中的一个等号,则 for 循环的测试部分将是一个赋值表达式,而不是关系表达式,此时代码仍然是有效的。这是因为可以将任何有效的C++表达式用作for循环的测试条件。别忘了,非零值为true,零值为false。
C-风格字符串的比较
word == “mate”
这个关系表达式不是判断两个字符串是否相同,而是查看它们是否存储在相同的地址上。
应使用C-风格字符串库中的 strcmp() 函数来比较。该函数接受两个字符串地址作为参数。
虽然不能用关系运算符来比较字符串,但是可以用它们来比较字符,因为字符实际上是整型。
string类能够在下述条件下使用关系运算符:至少有一个操作数为string对象,另一个操作数可以是string对象也可以是c-风格字符串。
但是注意,不同于C-风格字符串,string对象不用空字符来标记字符串末尾,因此不能用空字符来判别是否到达string类字符串的末尾。
8. while 循环
通常,程序员使用for循环来为循环计数,因为 for 循环格式允许将所有相关的信息——初始值、终止值和更新计数器的方法——放在同一个地方。在无法预先知道循环将执行的次数时,程序员通常会选择 while 循环。
while (test-condition)
body
和for循环一样,while循环也是一种入口条件循环,即每次在执行循环体之前计算测试条件表达式。
类型别名
9. typedef 工具
C++ 为类型建立别名的方式有两种。一种是使用预处理器:
#define BYTE char // preprocessor replaces BYTE with char
这样,预处理器将在编译程序时用 char 替换所有的 BYTE ,从而使 BYTE 成为 char 的别名。
第二种方法是 使用 C++ (和 C) 的关键字 typedef 来创建别名。例如,要将 byte 作为 char 的别名,可以这样做:
typedef typeName aliasName;
换句话说,如果要将 aliasName 作为某种类型的别名,可以声明 aliasName,如同将 aliaName 声明为这种类型的变量那样,然后在声明的前面加上关键字 typedef。例如,要让 byte_pointer 成为 char 指针的别名,可将 byte_pointer 声明为 char 指针,然后在前面加上 typedef:
typedef char * byte_pointer;
也可以使用 #define,但在声明用逗号分隔的一系列变量时,这种方法不适用。例如:
#define FLOAT_POINTER float *
FLOAT_POINTER pa, pb;
预处理器置换将该声明转换为这样:
float * pa, pb; // pa a pointer to float, pb just a float
typedef 方法不会有这样的问题。它能够处理更复杂的类型别名,这使得与使用 #define 相比,使用 typedef 是一种更佳的选择——有时候,这也是唯一的选择。
注意,typedef不会创建新的类型,而只是为已有的类型建立一个新名称。如果将 word 作为 int 的别名,则 cout 将把word 类型的值视为 int 类型。
do while 循环
do while 循环不同于 for 循环和 while循环,是一种出口条件循环,即执行循环体在条件判断之前。
for 循环的空测试条件被默认为 true。
10 .字符输入方法 get()
-
cin
cin会忽略空格和换行符
istream对象提供了一个可以将istream对象(如cin) 转换为 bool 值的函数;当cin出现在需要bool值的地方,该转换函数将被调用。如果最后一次读取成功了,则转换为 true,否则为 false。这意味着可以写:
while(cin) 用来作为检测是否读取成功的入口条件 -
cin.get(char);
cin.get(char)可以修补cin的这个问题
如果熟悉C语言,可能会以为这存在严重的错误, cin.get(char)调用将一个值放在 char 变量中,这意味着将修改该变量的值。在C语言中,要修改变量的值,必须将变量的地址传递给函数。但在C++中,只要函数将参数声明为引用即可。 -
ch = cin.get();
11. 文件尾条件
EOF是在文件 iostream 中定义的
判断EOF:
while(cin.fail()==false)
while(cin.eof()==false)
fail()比eof()可用于更多的实现中
或者接改为
while(!cin.fail())
或者直接
while(cin)
while(cin.get(ch))
因为cin和cin.get(ch)都是返回一个istream对象,执行bool转换后变为true(成功读取字符时)或false(到达EOF时)
还可以使用
ch = cin.get()
但是需要注意的是,由于EOF表示的不是有效字符编码,因此可能不与char类型兼容,例如,在有些系统中,char类型是没有符号的,因此char变量不可能为EOF值(-1),由于这种原因,如果使用cin.get()并测试EOF,则必须将返回值赋给int变量,而不是char变量,随之而来的问题就是必须要在显示ch时将其强制转换为char类型。
例如:
int ch;
while( (ch=cin.get())!=EOF){
cout.put(char(ch));
}
cin.get(ch) 与 cin.get() 的比较
属性 | cin.get(ch) | ch=cin.get() |
---|---|---|
传递输入字符的方式 | 赋给参数ch | 将函数返回值赋给ch |
用于字符输入时函数的返回值 | istream对象(执行bool转换后为 true) | int类型的字符编码 |
到达EOF时函数的返回值 | istream对象(执行bool转换后为 false) | EOF |
12. 嵌套循环和二维数组
const int Cities = 5;
char * cities[Cities] = {
“Gribble City”,
“Gribbletown”,
“New Gribble”,
“San Gribble”,
“Gribble Vista”
};
char cities[Cities][25] = {
“Gribble City”,
“Gribbletown”,
“New Gribble”,
“San Gribble”,
“Gribble Vista”
};
string cities[Cities] = {
“Gribble City”,
“Gribbletown”,
“New Gribble”,
“San Gribble”,
“Gribble Vista”
};