【和春笋一起学C++】while语句和类型别名
目录
1. while语句
2. while语句应用实例——延时功能实现
3. 类型别名
(1)使用预处理器创建别名
(2)使用关键字typedef创建别名
1. while语句
前面学习了for语句,其实在C++中,for和while循环本质上是相同的,while循环是没有初始化和更新(循环变量)部分的for循环,它只有测试条件和循环体:
while (test-condition)
body
首先,程序计算圆括号内的测试条件(test-condition)表达式。如果该表达式为true,则执行循环体中的语句。与for循环一样,循环体由一条语句或一个语句块组成。执行完循环体后,程序返回测试条件,对它进行重新判断,如果该条件为非零,则再次执行循环体。测试和执行将一直进行下去,直到测试条件为false为止。和for循环一样,while循环也是一种入口条件循环,即测试条件一开始如果为false,则程序将不会执行循环体。
上篇文章《字符串比较》中输出字符串中每个字符ASCII的实例可以用while语句改写,如下:
#include <iostream>
#include <cstring>
using namespace std;
const int ArSize = 20;
int main()
{
char name[ArSize];
cin >> name;
int i = 0;
while (name[i] != '\0')
{
cout << name[i] << ": " << int(name[i]) << endl;
i++;
}
return 0;
}
说明:(1)while语句中的循环变量需在while语句之前先初始化;(2)循环体中需要对循环变量进行更新,否则循环将一直持续下去,变成一个死循环。
前面文章《for语句和递增操作符》中的for语句如下:
for (initialization; test expression; update-expression)
{
语句1;
语句2;
...
语句n;
}
改写为while语句为:
initialization;
while (test expression)
{
语句1;
语句2;
...
语句n;
update-expression;
}
在使用while语句时需要注意的一点是while圆括号后面不能加分号,加了分号编译不会报错,也能执行,但这个循环很可能是一个死循环,如果上面程序在while括号的后面加了分号,会出现什么情况呢?将导致循环会一直持续,直到手动终止。
while (name[i] != '\0');
{
cout << name[i] << ": " << int(name[i]) << endl;
i++;
}
永远记住,在C++中分号是结束一个语句。分号出现在while括号的后面表示while循环语句已经结束了,程序会认为没有循环体,从而导致后面花括号中的语句块没有被执行。在写while语句时务必要注意这一点。
2. while语句应用实例——延时功能实现
基于while语句的特性,可以用它来实现一个延时功能。比如:
long wait = 0;
while(wait < 10000)
wait++;
说明:上面代码循环了1万次,用在延时器上相当于延时了一万个系统时间单位数。但是会存在一个问题,就是用在不同的处理器上,它延时的时间是不一样的。
头文件ctime提供了解决方案,它定义了一个符号常量——CLOCKS_PER_SEC,该常量等于每秒钟包含的系统时间单位数。因此,将系统时间单位数除以这个数可以得到实际的秒数,或者将秒数乘以CLOCKS_PER_SEC可以得到系统时间单位数。另外,ctime将clock_t作为clock()函数返回类型的别名,这意味着可以将变量声明为clock_t类型,编译器将把它转换为long,unsigned int或适合系统的其他类型。(PS:clock()函数返回的类型在有些系统上是long,在另外一些系统是unsigned long或其他类型)
下面代码通过clock()函数实现了延时功能。
#include <iostream>
#include <cstring>
#include <ctime>
using namespace std;
int main()
{
cout << "Enter the delay time, in second: ";
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;
}
说明:(1)上面程序以系统时间单位为单位计算延迟时间,避免了在每轮循环中将系统时间转换为秒。(2)while后面是空语句,什么都没做。分号可以放在while括号的后面,也可以另起一行只写一个分号,单独一行只有一个分号它也是一条语句,只不过是条空语句,什么都没做。
3. 类型别名
上面的程序中使用了类型别名clock_t,在C++中为类型建立别名有两种方式。
(1)使用预处理器创建别名
#define BYTE char //preprocessor replaces BYTE with char
这样预处理器在编译程序时将用char替换所有的BYTE,从而使BYTE成为char的别名。
(2)使用关键字typedef创建别名
将BYTE作为char的别名如下:
typedef char BYTE; //makes BYTE an alias for char
注意,末尾有分号,表明这是一条语句,可以理解为是一条声明语句,将BYTE声明为char的别名。下面是通用格式:
typedef typeName aliasName;
使用typedef创建别名,如同将aliasName声明为这种类型的变量,然后在声明的前面加上关键字typedef。如将byte_pointer成为char指针的别名,可将byte_pointer声明为char指针,然后在前面加上typedef,如下:
typedef char* type_pointer;
当然也可以使用#define,不过在声明一系列变量时,这种方法会有问题,例如:
#define byte_pointer char*
byte_pointer p1, p2;
我们的本意是创建两个char指针变量p1和p2,但上面的语句实际上是创建了一个char指针变量p1和一个char变量p2,因为程序在编译的时候,预处理器将上面的声明语句解释为:
char* p1,p2;
如果使用了typedef来创建char指针变量的别名,就不会出现上面的问题,所以在创建复杂类型的别名时尽量使用typedef。另外,typedef不会创建新类型,它只是为已有的类型创建了一个新名称。