循环与关系表达式
5.1 for循环
代码5-1
// forloop.cpp -- introducing the for loop
#include <iostream>
using namespace std;
int main()
{
int i;
for (i = 0; i < 5; i++)
{
cout << "I have " << i << " apple(s)." << endl;
}
cout << "GG Bond konws when to end the loop" << endl;
return 0;
}
for循环组成部分
代码5-2
// num_test.cpp -- use numeric test in for loop
#include <iostream>
using namespace std;
int main()
{
cout << "Enter the starting countdown value: ";
int count;
cin >> count;
int i;
for (i = count; i ; i--)
{
cout << "i = " << i << endl;
}
cout << "Done when i = " << i << endl;
return 0;
}
对以上两部分代码,注意++和–运算符的使用
表达式
代码5-3
// express.cpp -- values of expressions4
#include <iostream>
using namespace std;
int main()
{
int x;
cout << "The expression x = 100 has the value ";
cout << (x=100) << endl;
cout << "Now x = " << x << endl;
cout << "The expression x < 3 has the value ";
cout << (x<3) << endl;
cout << "The expression x > 3 has the value ";
cout << (x>3) << endl;
cout.setf(ios_base::boolalpha);// 设置bool不自动转换为int值输出
cout << "\n\n";
cout << "The expression x < 3 has the value ";
cout << (x<3) << endl;
cout << "The expression x > 3 has the value ";
cout << (x>3) << endl;
return 0;
}
对于在for循环中声明的变量,较老的C++在循环结束后仍可以使用变量,但较新的C++不允许,循环结束后即释放
循环阶乘示例
代码5-4
// formore.cpp -- more looping with for
#include <iostream>
using namespace std;
const int ArSize = 16;
int main()
{
long long factorials[ArSize];
factorials[1] = factorials[0] = 1LL;
for (int i = 2; i < ArSize; i++)
{
factorials[i] = factorials[i-1] * i;
}
for (int i = 0; i < ArSize; i++)
{
cout << i << "! = " << factorials[i] << endl;
}
return 0;
}
修改步长
代码5-5
// bigstep.cpp -- count as directed
#include <iostream>
using namespace std;
int main()
{
cout << "Enter an integer: ";
int by;
cin >> by;
cout << "Counting by: " << by << "s:\n" << endl;
for (int i = 0; i < 100; i+=by)
{
cout << i << endl;
}
return 0;
}
for循环与字符串
代码5-6
// forstr1.cpp -- using for with a string
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter a word: ";
string word;
// cin >> word;
getline(cin, word);// 测试数据 GG Bond
for (int i = word.size()-1; i>=0; i--)
{
cout << word[i] << " ";
}
cout << "\nBye.\n";
return 0;
}
递增与递减运算符
代码5-7
// plus_one.cpp -- the increment operator
#include <iostream>
using namespace std;
int main()
{
int a = 20;
int b = 20;
cout << "a = " << a << "\t\tb = " << b << endl;
cout << "a++ = " << a++ << "\t++b = " << ++b << endl;
cout << "a = " << a << "\t\tb = " << b << endl;
return 0;
}
留意前缀和后缀使用的区别
需要注意
任何完整表达式【最小子表达式】的末尾都是一个顺序点,如下:
#include <iostream>
using namespace std;
int main()
{
int a = 20;
while (a++ < 30)// a++ < 30 是一个完整表达式,所以a并非直接使用20进入cout进行输出,
// 而是完整实现 a++ 以及使用 20 < 30 判断后使用21进入cout进行输出
{
cout<< "a = " << a << endl;
}
return 0;
}
int y = (4 + a++) + (6 + a++);
cout << y << endl;
同时,对于上述 y 的表达式,C++不保证输出结果一定正确,因为不能保证 4 + a++ 【并非完整表达式】中 a 的值使用后立刻增加1
指针与递增/递减运算符
++*p;// 对地址中的值进行递增,指针指向不变
(*p)++;// // 对地址中的值进行递增,指针指向不变
*p++;// 递增运算符优先级更高,意味着先指针的指向递增,再解引用
组合赋值运算符
代码5-8
// block.cpp -- use a block statement
#include <iostream>
using namespace std;
int main()
{
cout << "The Amazing Accounto will sum and average five numbers for you." << endl;
cout << "Please enter five numbers: " << endl;
double number;
double sum = 0.0;
for (int i = 1; i <= 5; i++)
{
cout << "Value: " << i << " : ";
cin >> number;
sum += number;
}
cout << "Five exquisite choices indeed! " << endl;
cout << "They sum to: " << sum << endl;
cout << "They average: " << sum / 5 << endl;
return 0;
}
注意:一个 {} 即代表着一个代码块,代码块中定义的变量,只能在自身的代码块中调用
int y = 0;
{
int x = 0;
cout << y << endl;// 正常输出
}
cout << x << endl;// 无法正常输出
语法技巧
逗号运算符 ,
代码5-9
// forstr2.cpp -- reversing an array
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter a word: ";
string word;
// cin >> word;
getline(cin, word);
char temp;// 如果将temp写在for循环里面,将重复分配和释放,费时更多
int i, j;
for (j = 0, i = word.size()-1; j < i; --i, ++j)// 逗号技巧
{
temp = word[i];
word[i] = word[j];
word[j] = temp;
}
cout << word << "\nDone!" << endl;
return 0;
}
i=20, j=2*i;//正常运行
cats = 17,240;//编译器解释为(cata=17),240
cats = (17,240);// 可以使用括号的优先级最高特性,cats值被设置为240
关系表达式
代码5-10
// equal.cpp -- quality vs assainment
#include <iostream>
using namespace std;
int main()
{
int quizscores[10] = {20, 20, 20, 20, 20, 19, 20, 18, 20, 20};
cout << "Doing it right: " << endl;
int i;
for (i = 0; quizscores[i]==20; i++)
{
cout << "quiz " << i << " is a 20" << endl;
}
// cout << "Doing it dangerously wrong: " << endl;
// for (i = 0; quizscores[i]=20; i++)// 数组末尾不停止,可能导致其他程序崩溃
// {
// cout << "quiz " << i << " is a 20" << endl;
// }
return 0;
}
C风格字符串比较
假设word中储存了mate字符串
word == "mate";// 此句实际为判断它们是否存储在相同地址上
需要判断两个字符串是否相同,可使用
strcmp();// 接受两个字符串地址做参数,相同返回0,如果第一个字符串在第二个之前,返回负数,否则返回正数
代码5-11
// compstr1.cpp -- Comparing strings using arrays
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char word[5] = "?ate";
for (char ch = 'a'; strcmp(word, "mate"); ch++)
{
cout << word << endl;
word[0] = ch;
}
cout << "After loop endds, words is : " << word << endl;
return 0;
}
使用string类字符串
代码5-12
// compstr2.cpp -- Comparing strings using arrays
#include <iostream>
#include <string>
using namespace std;
int main()
{
string word = "?ate";
for (char ch = 'a'; word!="mate"; ch++)
{
cout << word << endl;
word[0] = ch;
}
cout << "After loop endds, words is : " << word << endl;
return 0;
}
5.2 while循环
代码5-13
// while.cpp -- introducing the while loop
#include <iostream>
using namespace std;
const int ArSize = 20;
int main()
{
char name[ArSize];
cout << "Enter your name: ";
cin.getline(name, ArSize);
cout << "Here is your name, verticalized and ASCIIized: " << endl;
int i = 0;
while (name[i] != '\0')// 判断结尾空字符
{
cout << name[i] << " : " << int(name[i]) << endl;
i++;
}
return 0;
}
延时循环
代码5-14
// waiting.cpp -- using clock() in time delay loop
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
cout << "Enter the time delay, in seconds: ";
float seconds;
cin >> seconds;
clock_t delay = seconds * CLOCKS_PER_SEC;// CLOCKS_PER_SEC值为1000,delay计算结果单位为毫秒,即计算机系统单位时间
cout << "Starting time delay\a\n";
clock_t start = clock();// clock_t组为clock()返回类型,是类型别名
//【因为clock()在不同系统的返回类型不一定相同,可能为long 、unsigned long等】
// start是记录进入循环的时间
while (clock() - start < delay);// 一直判断当前时间与记录时间的差值与所需延迟的时间相比,满足进入空循环
cout << "Done!\n";
return 0;
}
C++为类型建立别名:
- 使用预处理器
#define BYTE char
#define f_pointer float*
f_pointer a, b;// 会被编译器解释为 float* a, float b【typedef无此问题】
- 使用关键字typedef
typedef char byte;
typedef char* bytePointer;// 将char指针命别名
bytePointer a, b;// 会被编译器解释为 char* a, char* b
5.3 do while循环
// dowhile.cpp -- exit-condition-loop
#include <iostream>
using namespace std;
int main()
{
int n;
cout << "Enter numbers in the range 1-10 to find ";
cout << "my favorite number. " << endl;
do
{
cin >> n;
} while (n!=7);
cout << "Yes, 7 is my favorite number. " << endl;
return 0;
}
编译器正确,却不建议的写法:
int I = 0;
for (;;)
{
I++;
if (I >= 30) break;
}
for (;;I++)
{
if (I >= 30) break;
}
// 以下为正常写法
do
{
I++;
} while (30 > I);
while(I < 30)
{
I++;
}
5.4 基于范围的for循环
C++11新增,对数组、容器类(vector,array)等可迭代对象中每个元素执行相同的操作
代码示例
#include <iostream>
using namespace std;
int main()
{
double prices[4] = {1.00, 2.00, 3.00, 4.00};
cout << "original data: " << endl;
for (double x : {1.00, 2.00, 3.00, 4.00})
{
cout << x << " ";
}
for (double &x : prices)// &: 引用符,即取地址【*: 解引用符】
// 可将&去除观察区别
{
x = x * 10;// 对每个元素进行修改
}
cout << "\nAfter being fixed: " << endl;
for (double x : prices)
{
cout << x << " ";
}
return 0;
}
5.5 循环和文本输入
通过循环完成逐字符读取文件或键盘文本
即使C与C++中的while看起来一样,但C++的I/O工具不同
cin 对象支持3种不同模式单字符输入
对字符停止标志称为:哨兵字符
代码5-16
使用cin
// textin1.cpp -- reading chars with a while loop
#include <iostream>
using namespace std;
int main()
{
char ch;
int count = 0;
cout << "Enter characters: enter # to quit" << endl;
cin >> ch;// input : GG Bond#
// 一次性将多个字符插入到输入流中,将#看作结束符
// 由于cin自动忽略空格符和换行符,所以不会将其计数
while (ch != '#')// 由于在输入流中,刚才的数据有序排列着,循环读取
{
cout << ch;
++count;
cin >> ch;// 输入#用于结束
}
cout << endl << count << " characters entered" << endl;
return 0;
}
使用cin.get()
代码5-17
// textin2.cpp -- using cin.get(char)
#include <iostream>
using namespace std;
int main()
{
char ch;
int count = 0;
cout << "Enter characters: enter # to quit" << endl;
cin.get(ch);// input : GG Bond# B ond #
// 一次性将多个字符插入到输入流中,将#看作结束符
// cin.get(ch);会记录空格
while (ch != '#')// 由于在输入流中,刚才的数据有序排列着,循环读取
{
cout << ch;
++count;
cin.get(ch);// 输入#用于结束
}
cout << endl << count << " characters entered" << endl;
return 0;
}
若输入来自文件,可以使用检查文件尾(EOF),来判断结束信息
检测到EOF后,cin将eofbit、failbit都设置为1,使用成员函数eof()、fail()查看状态
代码5-18
// textin3.cpp -- reading chars to end of file
#include <iostream>
using namespace std;
int main()
{
char ch;
int count = 0;
cout << "Enter characters: " << endl;
cin.get(ch);
// The green bird sings in the winter.<ENTER>
// Yes,but the crow flies in the dawn.<ENTER>
// <CTRL>+<Z><ENTER>// 模拟EOF条件
while (cin.fail() == false)
{
cout << ch;
++count;
cin.get(ch);
}
cout << endl << count << " characters entered" << endl;
return 0;
}
可以使用cin.clear()来清除EOF标记
C语言中的I/O函数
头文件:<cstdio>
ch = cin.get();// 不接受任何参数,返回输入中的下一个字符
// 与getchar()相似,将字符编码作为int值返回
cin.get(ch);// 返回一个cin对象,并非字符
cout.put(ch);// 显示字符
// 与putchar()相似,参数类型为char
// put()最初只有一个原型,可传递int,将被强制转换为char,
// 后续对于传递的参数通过三个原型:char,signed char,unsigned char【将无法自动将int转换】
当读取文件函数到达EOF时,将无可返回字符,但cin.get()将返回一个特殊值【在iostream中被定义为-1(-1在ASCII码并无定义)】来代表这种状态
由于未定义,所以无法与char字符兼容
如果使用cin.get()【无参数】测试EOF,必须使用int类型来接收返回值
代码5-19
// textin4.cpp -- reading chars with cin.get()
#include <iostream>
using namespace std;
int main()
{
int ch;// 必须为int类型
int count = 0;
// The green bird sings in the winter.<ENTER>
// Yes,but the crow flies in the dawn.<ENTER>
// <CTRL>+<Z><ENTER>// 模拟EOF条件
while ((ch = cin.get()) != EOF)
{
cout.put(char(ch));// 强制转换,对应ASCII码
++count;
}
cout << endl << count << " characters entered" << endl;
return 0;
}
!= 优先级高于 =
所以不能如下所示,省略括号
while (ch = cin.get() != EOF)
区别表
5.6 嵌套循环和二维数组
二维数组:每个元素本身都是数组的数组
int maxtemps[4][5];// 4行5列数组
代码5-20
// nested.cpp -- nested loops and 2-D arrays
#include <iostream>
using namespace std;
const int Cities = 5;
const int Years = 4;
int main()
{
const char* cities[Cities] = // 指针数组初始化为常量,C++常用操作
// 注意区别指针常量和常量指针
{
"Gribble City",
"GribbleTown",
"New York City",
"San Francisco",
"Vista City"
};
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 << "Maximun temperatures for 2008-2011\n\n" << endl;
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;
}