四. 循环和关系表达式
4.1 for循环
forloop.cpp
#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;
}
4.1.1 for循环的组成部分
· 设置初始值;
· 执行测试,判断循环是否应当继续进行;
· 执行循环操作;
· 更新循环变量。
for (initialization; test-expression; update-expression)
body;
num_test.cpp
#include <iostream>
int main()
{
using namespace std;
cout << "Enter the starting countdown value: ";
int limit;
cin >> limit;
int i;
for (i = limit; i; i--)
cout << "i = " << i << "\n";
cout << "Done now that i = " << i << "\n";
return 0;
}
C++允许在for循环中声明变量:
for (int i = 0; i < 5; i++)
4.1.2 for循环完成阶乘
formore.cpp
#include <iostream>
const int Arsize = 16;
int main()
{
long long factorials[Arsize];
factorials[1] = factorials[0] = 1LL;
for (int i = 2; i < Arsize; i++)
factorials[i] = i * factorials[i - 1];
for (int i = 0; i < Arsize; i++)
std::cout << i << "! = " << factorials[i] << std::endl;
return 0;
}
4.1.3 修改步长
可以通过修改更新表达式来修改步长。
4.1.4 使用for循环访问字符串
forstr.cpp
#include <iostream>
#include <cstring>
int main()
{
using namespace std;
cout << "Enter a word: ";
string word;
cin >> word;
for (int i = word.size() - 1; i >= 0; i -- )
cout << word[i];
cout << "\nBye.\n";
return 0;
}
4.1.5 递增运算符(++)和递减运算符(--)
int x = 5;
int y = ++X; //y = 6, x = 5
int z = 5;
int y = z++; //y = 5, z = 6
4.1.6 递增/递减运算符和指针
可以将递增运算符用于指针和基本变量。
double arr[5] = {21.1, 32.8, 45.2, 37.4};
double *pt = arr;
++pt;
也可以结合使用这些运算符和*运算符来修改指针指向的值。将*和++同时用于指针时提出了这样的问题:将什么解除引用,将什么递增。这取决于运算符的位置和优先级。前缀递增、前缀递减和解除引用运算符的优先级相同,以从右到左的方式进行结合。后缀递增和后缀递减的优先级相同,但比前缀运算符的优先级高,这两个运算符以从左到右的方式进行结合。
4.1.7 组合赋值运算符
4.1.8 关系表达式
4.2 while循环
while循环是没有初始化和更新部分的for循环,它只有测试条件和循环体:
while (test-condition)
body
while.cpp
#include <iostream>
const int Arsize = 20;
int main()
{
using namespace std;
char name[Arsize];
cout << "Your first name,please: ";
cin >> name;
cout << "Here is your name, verticalized and ASCIIized: \n";
int i = 0;
while (name[i] != '\0')
{
cout << name[i] << ": " << int(name[i]) << endl;
i++;
}
return 0;
}
4.2.1 for和while
通常使用for循环来为循环计数,因为for循环格式允许将所有相关的信息——初始值、终止值和更新计数器的方法放在同一个地方。在无法预先知道循环将执行的次数时,常使用while循环。
设计循环时,有下面几条指导原则:
· 指定循环终止的条件。
· 在首次测试之前初始化条件。
· 在条件被再次测试之前更新条件。
4.2.2 等待一段时间:编写延时循环
使用clock()和头文件ctime来创建延时循环。
wating.cpp
#include <iostream>
#include <ctime>
int main()
{
using namespace std;
cout << "Enter the delay time, in seconds: ";
float secs;
cin >> secs;
clock_t delay = secs * CLOCKS_PER_SEC;
cout << "starting\a\n";
clock_t start = clock();
while (clock() - start < delay)
;
cout << "done \a\n";
return 0;
}
头文件ctime定义了一个符号常量CLOCKS_PER_SEC,该常量等于每秒钟包含的系统时间单位数。因此,将系统时间除以这个值可以得到秒数。或者将秒数乘以CLOCK_PER_SEC,可以得到以系统时间单位为单位的时间。其次,ctime将cock_t作为clock(),这意味着可以将变量声为clock_t类型,编译器将把它转换为long、unsignedint或适合系统的其他类型。
类型别名
C++为类型建立别名的方式有两种。一种是使用预处理器:
#define BYTE char //使BYTE成为char的别名
第二种方法是使用C++的关键字typedef来创建别名:
typedef char byte; //使BYTE成为char的别名
typedef char byte_pointer; //使BYTE成为char指针的别名
4.3 do while循环
do while循环不同于for循环和while循环,它是出口条件循环,即首先执行循环体,然后再判定测试表达式,决定是否继续执行循环。
dowhile.cpp
#include <iostream>
int main()
{
using namespace std;
int n;
cout << "Enter numbers in the range 1-10 to find ";
cout << "my favorite number\n";
do
{
cin >> n;
} while (n != 7);
cout << "Yes, 7 is my facorite number.\n";
return 0;
}
4.4 基于范围的for循环(C++11)
C++11 新增了一种循环基于范围(range-based)的 for 循环。这简化了一种常见的循环任务:对数组(或容器类,如vector和array)的每个元素执行相同的操作,如下例所示:
double prices[5] = {4.99, 10.99, 6.87, 7.99, 8.49};
for (double x: prices)
cout << x << std::endl;
4.5 循环和文本输入
4.5.1 使用原始的cin进行输入
textin.cpp
#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;
}
上面的做法忽略了空格、制符表和换行符。
4.5.2 使用cin.get(char)输入
textin.cpp
#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;
}
4.6 嵌套循环和二维数组
可以用两个for循环来遍历数组所有的元素,一个for用来遍历行,另一个用来遍历列。
4.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},
};
4.6.2 使用二维数组
nested.cpp
#include <iostream>
const int Cities = 5;
const int Years = 4;
int main()
{
using namespace std;
const char* cities[Cities] =
{
"Gribble City",
"Gribbletown",
"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 << "Maximum temperature for 2008 - 2011\n\n";
for (int city = 0; city < Cities; ++city)
{
cout << cities[city] << ":\t";
for (int year = 0; year < Years; ++year)
cout << maxtemps[year][city] << "\t";
cout << endl;
}
return 0;
}
4.7 总结
C++提供了3种循环:for 循环、while 循环和do while 循环。如果循环测试条件为true 或非零,则循环将重复执行一组指令;如果测试条件为 false 或0则结循环。for循环和while 循环都是入口条件循环,这意味着程序将在执行循环体中的语句之前检查测试条件。do while 循环是出口条件循环,这意味着其将在执行循环体中的语句之后检查条件。
每种循环的句法都要求循环体由一条语句组成。然而,这条语句可以是复合语句,也可以是语句块(由花括号括起的多条语句)。
关系表达式对两个值进行比较,常被用作循环测试条件。关系表达式是通过使用6种关系运算符之一构成的:<、<=、==、>=、>或!=。关系表达式的结果为 bool类型,值为 true 或false。
许多程序都逐字节地读取文本输入或文本文件,istream 类提供了多种可完成这种工作的方法。如果ch是一个char变量,则下面的语句将输入中的下一个字符读入到ch中:
cin >> ch;
然而,它将忽略空格、换行符和制表符。下面的成员函数调用读取输入中的下一个字符(而不管该字符是什么)并将其存储到ch 中:
cin.get(ch):
成员函数调用cinget()返回下一个输入字符一包括空格、换行符和制表符,因此,可以这样使用它
ch = cin,get():
cin.get (char)成员函数调用通过返回转换为 false 的 bool值来指出已到达EOF,而cinget()成员函数调用则通过返回EOF值来指出已到达EOF,EOF是在文件iostream 中定义的
嵌套循环是循环中的循环,适合用于处理二维数组。