C++学习笔记(五)
循环和关系表达式
for循环:
for(int i = 0; i < 5; i++){
cout << “for循环: ” << i << endl;
}
int i = 0;是循环的初始化部分,将整数i设置为0,循环测试部分判断i是否小于5;如果小于5程序将会执行循环体(cout << “for循环: ” << i << endl;);执行完后将使用循环更新部分:i++(自加运算符)。当i大于等于5的时候跳出循环。
2. for循环格式:for(initialization; test-expression; update-expression){ body }
1).设置初始值。(只执行一次)
2).执行测试,判断循环是否应当继续执行。
3).执行循环操作。
4).更新用于测试的值。
test-expression(测试表达式)决定循环体是否被执行。通常是关系表达式,对两个值进行比较,判断结果是否为真。也可以使用任意表达式,C++将把结果强制转换成bool类型(值为0的表达式将会被转换成false,会导致循环结束, 否则表达式的值非零,将会被强转为bool值true,循环将继续进行)。
for循环是入口条件(entry-condition)循环,在每轮循环之前,都将计算测试表达式的值,当测试表达式的值为false时,将不会执行循环体。
update-expression(更新表达式)在每轮循环结束时执行,此时循环体已经执行完毕。通常用来对跟踪循环轮次的变量的值进行增减(也可以时任何有效的C++表达式,或者其他控制表达式)。
3. 关系表达式输出的值类型转换:
int a = 1;cout << (a < 3) << endl;
此时会输出1。 在声明a变量之前加上cout.setf(ios::boolalpha);
将会输出true。setf()函数调用后将命令cout显示true和fasle,而不是1和0。
4. 表达式和语句:x = 100是一个表达式;x = 100;是一个语句(或者说是一个赋值语句)。
从表达式转换成语句只需加一个分号即可。所有表达式都可以成为语句,但不一定有编程意义。例:a + 1;
反过来是不成立的,从语句中删除分号,并不一定能转换为表达式。例:int num;是一个语句,int count = int num * 1000;int num不是表达式,因为它没有值,所以代码是非法的。
5. for循环可以修改步长:
using std::cout;
using std::cin;
int k;
cin >> k;
for (int i = 0; i < 100; i += k) {
cout << i <<endl;
}
注:此处使用了using声明,而不是using编译指令。
- for循环实现访问字符串的每一个字符:
char arr[10] = “123456789”;
for (int i = 0; i < strlen(arr); i ++) {
cout << arr[i] <<endl;
}
- 自增(递增)运算符(++)和自减(递减)运算符(–):这两个运算符执行两种常见的循环操作:将循环计数加1或者减1。此外这两个运算符都有两种变体:①运算符位于操作数前面,例:++x。②运算符位于操作数后面,例:x–。这两种变体的区别:当运算符位于操作数前面时,操作数会先自增(自减),然后再进行计算或者赋值;当运算符位于操作数后面时,操作数会先进行计算或者赋值,然后再执行自增(自减)。
例:int i = 0;int j = ++i;cout<< “i: ” << i << “, j: ” << j << endl;
会输出:i: 1,j: 1。
int i = 0;int j = i++;cout<< “i: ” << i << “, j: ” << j << endl;
会输出:i: 1,j: 0。
注:不要再同一条语句中多次使用自增运算符或自减运算符。 - 自增(自减)运算符的副作用和顺序点:副作用指的是在计算表达式时对某些东西(如存储在变量中的值)进行了修改;顺序点是程序执行过程中的一个点,在这里,进入下一步之前将确保对所有的副作用都进行了评估。在C++中,语句中的分号就是一个顺序点,这意味着程序处理下一条语句之前,赋值运算符、递增运算符和递减运算符执行的所有修改都必须完成。
- 前缀格式与后缀格式:如果变量被用于某些目的(如用作函数参数或给变量赋值),使用前缀格式和后缀格式的结果将不同。如果递增表达式的值没有被使用,结果将会相同。
- 递增/递减运算符和指针:
double arr[5] = {21.1, 32.8, 23.4, 45.2, 37.4};
double* pt = arr;
++pt;//此时pt将会指向arr[1];
double x = *++pt;//此时pt将会指向arr[2],并且取出arr[2]的值赋给x
++*pt;//此时pt指向的还是arr[2],取出arr[2]的值后自加
x = *pt++;//语句执行完后pt将会指向arr[3] - 指针递增和递减遵循指针算术规则。因此,如果pt指向某个数组的第一个元素,++pt将修改pt,使之指向第二个元素。
- 组合赋值运算符:
L为左操作数,R为右操作数
+= //将L + R赋给L
-= //将L – R赋给L
*= //将L * R赋给L
/= //将L / R赋给L
%= //将L % R赋给L - 逗号运算符:语句允许把两条或更多条语句放到按C+++语法只能放一条语句的地方。逗号运算符对表达式完成同样的任务,允许将两个表达式放到C++句法只允许放一个表达式的地方。
例:int i = 0, j = 0;//分割变量
++j, --i;//将两个表达式合并成一个 - 在所有运算符中逗号运算符优先级是最低的。
- 关系运算符:<、<=、==、>、>=、!=。关系运算符的优先级比算术运算符低。
例:x + 3 > y – 2;等效于:(x + 3) > (y - 2) - C中使用strcmp()函数比较两个字符串是否相同。如果两个字符串相同,则函数将返回零;如果第一个字符串按字母顺序排在第二个字符串之前,则strcmp()将返回一个负数值;如果第一个字符串按字母顺序排在第二个字符串之后,则strcmp()将返回一个正数值。
- string类型字符串比较:可以使用关系运算符进行比较。例:
string a = “123456”;
string b = “123456”;
cout.setf(ios::boolalpha);//允许控制台打印布尔类型
cout << (a == b) << endl;
while循环:
- while循环也是入口条件循环。while循环是没有初始化和更新部分的for循环,它只有测试条件和循环体:
while(test-condition)
body
首先程序会计算括号内的测试条件(test-condition)表达式,如果表达式为true,将会执行循环体中的语句。与for循环一样,循环体可以有一条语句或两个花括号定义的语句块组成。执行完循环体后,程序返回测试条件,重新判断表达式,直至表达式为false,循环结束。
char test[30];
cin >> test;
int i = 0;
char a = 90;
cout << a << endl;
while (test[i])//循环打印字符串直至遇到字符’\0’或者test[i]不存在循环终止
{
cout << static_cast<int>(test[i++]) << endl;
//强制类型转换static_cast<type>(value)或者(type)value或者type(value)
}
- for循环与while循环转换:
1).
for(init-expression;test-expression;update-expression){
statement(s)
}
可以转换成:
while(test-expression){
statement(s)
update-expression;
}
2).
while(test-expression){
body
}
可以转换成:
for( ;test-expression; ){//注意分号是必须的,不能省略
body
}
在无法预知循环的次数时,多使用while循环。
3. 在使用循环时,需要知道一下几点:
1).指定循环终止的条件;
2).在首次测试之前初始化条件;
3).在条件被再次测试之前更新条件。
for循环的一个优点是,其结构提供了一个可实现上述3点的地方。这些也适用于while循环。
4. 延时循环:time.h或者ctime
#include <time.h>
int main(){
using namespace std;
cout << “Enter the delay time. In seconds: ”;
float secs;
cin >> secs;
clock_t delay = secs * CLOCK_PER_SEC;
cout << “staring\a\n”;
clock_t start = clock();
while (clock() – start < delay);
cout << “done \a\n”;
return 0;
}
- 创建类型别名:
1).#define aliasName typeName。例:#define Rank int Rank id = 10;
2).typedef typeName aliasName;。例:typedef int Rank Rank age = 20;注:这种是通用格式。
do while循环:
- do while循环时出口条件(exit condition)循环。也就是这种循环首先执行循环体,然后再判定测试表达式,决定是否 应继续执行循环,如果条件为false,则循环终止;否则进入新一轮的执行和测试。这种循环至少执行一次。do while循环句法:
do
body
while(test-expression);
通常入口条件循环比出口条件循环好,因为入口条件循环再循环开始之前对条件进行检查。
基于范围的for循环:
- C++中简化了一种常见的循环任务:对数组(或容器类:vector、array)的美誉元素执行相同的操作。例:
int idArr[5] = {10, 20, 30, 40, 50};
for(int x : idArr){
cout << x << endl;
}
//修改数组元素(符号&标名j是一个引用变量)
for (int& j : idArr) {
j = j + 1;
cout << j << endl;
}
循环和文本输入:
- 使用原始的cin进行输入:
char ch;
int count = 0;
cin >> ch;
while(ch != ‘#’){
cout << ch;
++count;
cin >> ch;
}//会导致省略掉空格,并且不被计算在内
- 使用cin.get(char):
char ch;
int count = 0;
cin.get(ch);
while(ch != ‘#’){
cout << ch;
++count;
cin >> ch;
}//不会省略空格,会计算在内
- 函数重载:允许对多个相关的函数使用相同的名称。例:cin.get()、cin.get(ch)、cin.get(char*, size)
- 文件尾条件:检测文件尾(EOF)。例:假设再Windows中有一个名为gofish.exe的可执行程序和一个名为fishtale的文本文件,则可以再命令提示符模式下输入下面的命令:gofish <fishtale。这样程序将从fishtale文件(而不是键盘)获取输入。<符号是Windows命令提示符模式的重定向运算符。 再Windows命令提示符模式下,可以在任意位置按Ctrl+Z和Enter,类模拟文件尾条件。
检测到EOF后,cin将两位(eofbit和failbit)都设置为1.可以通过成员函数eof()来查看eofbit是否被设置:如果检测到EOF,则cin.eof()将返回boos值true,否则返回false。同样,如果eofbit或failbit被设置为1,则fail成员函数返回true,否则返回false。注:应将eof()或fail()测试放在读取后,是就近读取。
char ch;
int count = 0;
cin.get(ch);
while(cin.fail() == false){
cout << ch;
++count;
cin.get(ch);
}
- EOF结束输入:当cin方法检测到EOF时,将设置cin对象中一个指示EOF条件的标记。设置这个标记后,cin将不读取输入,再次调用cin也不管用。
- 另一个cin.get()版本:
ch = cin.get();cout.put(ch)
; - cin.get(ch)和cin.get()的区别:
1).传递输入字符的方式:cin.get(ch)是赋给参数ch;ch = cin.get()将函数返回值赋给ch。
2).用于字符输入时函数的返回值:cin.get(ch)返回的是istream对象(执行bool转换后为true);ch = cin.get()返回的是int类型的字符编码。
3).到达EOF时函数的返回值:cin.get(ch) 返回的是istream对象(执行bool转换后为false);ch = cin.get()返回的是EOF。
嵌套循环和二维数组:
- 二维数组:一维数组可以看成是一行数据。二维数组更像是一个表格–既有数据行又有数据列。声明二维数组:int classStudentArr [3][5];该声明表示classStudentArr是一个包含3个元素的数组,其中每个元素都是一个由5个整数组成的数组。可以将classStudentArr数组看作由3行组成,每一行由5个学生。
classStudentArr[0]是数组classStudentArr的第一个元素,classStudentArr[0][0]是classStudentArr[0]的第一个元素。
利用for循环实现数组遍历:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
cout << classStudentArr[i][j] << endl;
}
}
- 初始化二维数组:
int classStudentArr[3][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}
};
- 使用数组:
const char* cities[5] = { "Gribble City", "Gribbletown", "New Gribble", "San Gribble", "Gribble Vista" };//字符串指针数组
for (int city = 0; city < 5; ++city) {
cout << cities[city] << "\t";
}
可替换成:
char cities[5][25] = { "Gribble City", "Gribbletown", "New Gribble", "San Gribble", "Gribble Vista" };//字符串数组
也可以替换成:
const string cities[5] = { "Gribble City", "Gribbletown", "New Gribble", "San Gribble", "Gribble Vista" };//字符串数组
总结:
- C++提供了3中循环:for循环、while循环、do while循环。如果循环条件测试为true或非零,则循环将重复执行,如果测试条件为false或0.循环结束。其中for循环和while循环都是入口条件循环,即程序在执行循环体中的语句之前检查测试条件,do while循环是出口条件循环,意味着将在执行循环体中的语句后检查条件(do while循环至少执行一次)。
- 读取输入字符:
1).cin >> ch;//将会忽略空格、换行符和制表符。
2).cin.get(ch);//读取输入中的下一个字符(而不管该字符是什么)并将其存储到ch中。
3).ch = cin.get();//返回下一个输入字符——包括空格、换行符和制表符。