循环和关系表达式
5.1、for循环
例子
// forloop.cpp -- introducing the for loop
#include <iostream>
int main()
{
using namespace std;
int i; // create a counter
// initialize; test ; update
for (i = 0; i < 5; i++)
cout << "C++ knows loops.\n";
cout << "C++ knows when to stop.\n";
// cin.get();
return 0;
}
提示:
C++常用的方式是,在for和括号之间加上一个空格,而省略函数名与括号之间的空格。
关于一些运算符的
// express.cpp -- values of expressions
#include <iostream>
int main()
{
using namespace std;
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); //a newer C++ feature
cout << "The expression x < 3 has the value ";
cout << (x < 3) << endl;
cout << "The expression x > 3 has the value ";
cout << (x > 3) << endl;
/// cin.get();
return 0;
}
/*
The expression x = 100 has the value 100
Now x = 100
The expression x < 3 has the value 0
The expression x > 3 has the value 1
The expression x < 3 has the value false
The expression x > 3 has the value true
*/
通常,cout显示bool值之前将它们转换为int,但cout.setf(ios_base:boolalpha)函数调用设置了一个标记,该标记命令cout显示true和false,而不是1和0。
C++表达式是值或值与运算符的组合,每个C++表达式都有值。
age=100 //表达式
age=100; //一条语句
- 例子1
// formore.cpp -- more looping with for
#include <iostream>
const int ArSize = 16; // example of external declaration
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;
// std::cin.get();
return 0;
}
- 例子2
改步长;使用了using的声明,而不是using编译指令
// bigstep.cpp -- count as directed
#include <iostream>
int main()
{
using std::cout; // a using declaration
using std::cin;
using std::endl;;
cout << "Enter an integer: ";
int by;
cin >> by;
cout << "Counting by " << by << "s:\n";
for (int i = 0; i < 100; i = i + by)
cout << i << endl;
// cin.get();
// cin.get();
return 0;
}
- 例子3
依次访问字符串中每个字符的方式
// forstr1.cpp -- using for with a string
#include <iostream>
#include <string>
int main() {
using namespace std;
cout << "Enter a word: ";
string word;
cin >> word;
// display letters in reverse order
for (int i = word.size() - 1; i >= 0; i--)
cout << word[i];
cout << "\nBye.\n";
// cin.get();
// cin.get();
return 0;
}
/*
Enter a word: animal
lamina
Bye.
*/
- 递增/减运算符和指针
double arr[5]={21.1, 32.8, 23.4, 45.2, 37.4};
double *pt=arr; //pt point arr[0]
++pt; //pt point arr[1]
double x=*++pt; //increment pointer,take the value,arr[2]---23.4
++*pt; //先取值,后将这个值加1.---23.4+1=24.4
(*pt)++; //先取值,后将这个值加1.---24.4+1=25.4
x=*pt++; //++运算级高于解除引用运算符,以为着将运算符用于pt,而不是*pt
//*pt++的值为arr[2],为25.4;执行完该语句后,pt的值将为arr[3]的地址
注意:不要在在同一条语句对同一个值递增或递减多次。
注意
指针递增和递减循环指针算术规则。因此,如果pt指向某个数组的第一个元素,++pt将修改pt,使之指向第二个元素。
- 组合运算符
组合的运算符,如下图所示
- 组合语句(语句块)
// block.cpp -- use a block statement
#include <iostream>
int main() {
using namespace std;
cout << "The Amazing Accounto will sum and average ";
cout << "five numbers for you.\n";
cout << "Please enter five values:\n";
double number;
double sum = 0.0;
for (int i = 1; i <= 5; i++) {
// block starts here
cout << "Value " << i << ": ";
cin >> number;
sum += number;
} // block ends here
cout << "Five exquisite choices indeed! ";
cout << "They sum to " << sum << endl;
cout << "and average to " << sum / 5 << ".\n";
cout << "The Amazing Accounto bids you adieu!\n";
// cin.get();
// cin.get();
return 0;
}
/*
The Amazing Accounto will sum and average five numbers for you.
Please enter five values:
Value 1: 1942
Value 2: 1948
Value 3: 1957
Value 4: 1974
Value 5: 1980
Five exquisite choices indeed! They sum to 9801
and average to 1960.2.
The Amazing Accounto bids you adieu!
*/
如果在语句块中定义新变量,那么新变量的作用范围仅在于语句块内。
运算符
- 逗号运算符
语句块允许把两条或更多的语句放到一个地方。
逗号运算符对表达式完成同样的任务,允许将两个表达式放到C++语法只允许放一个表达式的地方。
// forstr2.cpp -- reversing an array
#include <iostream>
#include <string>
int main() {
using namespace std;
cout << "Enter a word: ";
string word;
cin >> word;
// physically modify string object
char temp;
int i, j;
for (j = 0, i = word.size() - 1; j < i; --i, ++j) {
// start block
temp = word[i];
word[i] = word[j];
word[j] = temp;
} // end block
cout << word << "\nDone\n";
// cin.get();
// cin.get();
return 0;
}
/*
Enter a word: qwertyuio
oiuytrewq
Done
*/
逗号运算符的2个特性
首先,它确保先计算第一个表达式,然后计算第二个表达式
i=20,j=2*i; //i set to 20,then j set to 40
其次,逗号运算符的优先级是最低的
cats=17,240; //(cats=17),240 cats will set to 17
cats=(17,240); //cats set to 240, 逗号右侧的表达式值
- 关系表达式
由于字符用其ASCII码表示,因此也可以将这些运算符用于字符。不能将它们用于C风格字符串,但可用于string类对象。对于所有的关系表达式,如果比较结果为真,则其值为true,否则为false,因此可将其用作循环测试表达式。
由于关系运算符的优先级比算术运算符
x+3>y-2;
(x+3)>(y-2); //两者等价
- 赋值、比较
musican==4; //比较
musican=4; //赋值
比较字符串
- C风格字符串的比较
C++将C风格字符串视为地址,因此如果使用关系运算符来比较它们,将无法得到满意的结果。
在C风格字符串是通过结尾的空值字符定义的,而不是由其所在数组的长度定义的。这意味着两个字符串即使被存储在长度不同的数组中,也可能是相同的。
char big[80]="Daffy";
char little[6]="Daffy";
虽然不能用关系运算符来比较字符串,但可以用它们来比较字符,因为字符实际上是整型的。
// compstr1.cpp -- comparing strings using arrays
#include <iostream>
#include <cstring> // prototype for strcmp()
int main() {
using namespace std;
char word[5] = "?ate";
for (char ch = 'a'; strcmp(word, "mate"); ch++) {
cout << word << endl;
word[0] = ch;
}
cout << "After loop ends, word is " << word << endl;
// cin.get();
return 0;
}
/*
?ate
aate
bate
cate
date
eate
fate
gate
hate
iate
jate
kate
late
After loop ends, word is mate
*/
strcmp(word, “mate”)。如果字符串不相等,则它的值为非零(true);如果字符串相等,则它的值为零(false)。
检测相等或排序
如果str1和str2相等,则下面的表达式为true:
strcmp(str1,str2)==0
如果str1和str2不相等,则下面表达式为true:
strcmp(str1,str2)!=0
strcmp(str1,str2)
如果str1在str2前面,则下面的表达式为true:
strcmp(str1,str2)<0
如果str1在str2后面,则下面的表达式为true:
strcmp(str1,str2)>0
- 比较string类字符串
int main() {
using namespace std;
string word = "?ate";
for (char ch = 'a'; word != "mate"; ch++) {
cout << word << endl;
word[0] = ch;
}
cout << "After loop ends, word is " << word << endl;
// cin.get();
return 0;
}
/*
?ate
aate
bate
cate
date
eate
fate
gate
hate
iate
jate
kate
late
After loop ends, word is mate
*/
测试条件中用了一个关系运算符,运算符左边是一个string对象,右边是一个C风格字符串
word!="mate";
string类重载运算符!=可以在下述条件下使用:至少有一个操作数为string对象,另一个操作数可以为string对象,也可以是C风格字符串
5.2、while循环
while的示意图
例子
// while.cpp -- introducing the while loop
#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; // start at beginning of string
while (name[i] != '\0') { // process to end of string while(name[i])
cout << name[i] << ": " << int(name[i]) << endl;
i++; // don't forget this step
}
// cin.get();
// cin.get();
return 0;
}
/*
Your first name, please: Butty
Here is your name, verticalized and ASCIIized:
B: 66
u: 117
t: 116
t: 116
y: 121
*/
for与while
for循环和while循环几乎等效。它们之间存在3个差别
- 在for循环中省略测试条件,将认为条件为true
- 在for循环中,可在初始化语句声明一个局部变量,但是while循环中不能这样做
- 如果循环体中包括continue语句,情况稍微不同
一般来说,使用for循环来计数。在无法知道循环将要执行的次数时,使用while循环
延时
头文件ctime中,定义了一个符号常量——CLOCKS_PER_SEC,该常量等于每秒种包含的系统时间单位数。
ctime将clock_t作为clock()返回类型的别名。
// waiting.cpp -- using clock() in a time-delay loop
#include <iostream>
#include <ctime> // describes clock() function, clock_t type
int main() {
using namespace std;
cout << "Enter the delay time, in seconds: ";
float secs;
cin >> secs;
clock_t delay = secs * CLOCKS_PER_SEC; // convert to clock ticks
cout << "starting\a\n";
clock_t start = clock();
while (clock() - start < delay ) // wait until time elapses
; // note the semicolon
cout << "done \a\n";
// cin.get();
// cin.get();
return 0;
}
/*
Enter the delay time, in seconds: 10
starting
done
*/
类型别名
方法1:使用预处理器
#define BYTE char //编译时用char替换所有的BYTE,从而使BYTE称为char的别名
方法2:使用关键字typedef来创建别名
typedef char byte; //将byte作为char的别名
//通用格式
typedef typeName aliasName;
typedef char* byte_pointer; //将byte_pointer声明为char指针
define在声明一系列变量时,不使用
#define FLOAT_POINTER float*
FLOAT_POINTER *pa,pb; //pa为float型指针,pb just a float
5.3、do while循环
程序流程
例子
// dowhile.cpp -- exit-condition loop
#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; // execute body
} while (n != 7); // then test
cout << "Yes, 7 is my favorite.\n" ;
// cin.get();
// cin.get();
return 0;
}
几个循环的对比
int I=0;
for(; ;)
{
I++;
//do something
if(I>=30) break;
}
//可以等价于下面的
int I=0;
do{
I++;
//do something
}while(I<30);
下面的
int I=0;
for(; ;I++)
{
if(I>=30) break;
//do something
}
while(I<30)
{
//do something
I++;
}
5.4、基于范围的for循环
类似于迭代器
循环显示
double prices[5]={4.99, 4.32, 1.23, 12.23, 8.49};
for(double x:prices)
cout<<x<<std::endl;
还可以修改数组的元素
for(double &x:prices)
x=x*0.80;
还可以使用基于范围的for循环和初始化列表
for(int x:{3,5,2,8,6})
cout<<x<<" ";
cout<<'\n';
5.5、循环和文本输入
cin对象支持3种不同模式的单字符输入。
例子1
// textin1.cpp -- reading chars with a while loop
#include <iostream>
int main() {
using namespace std;
char ch;
int count = 0; // use basic input
cout << "Enter characters; enter # to quit:\n";
cin >> ch; // get a character
while (ch != '#') { // test the character
cout << ch; // echo the character
++count; // count the character
cin >> ch; // get the next character
}
cout << endl << count << " characters read\n";
// get rid of rest of line
// while (cin.get() != '\n')
// ;
//cin.get();
return 0;
}
/*
Enter characters; enter # to quit:
seekenrun#
seekenrun
9 characters read
*/
上面的例子。由于cin忽略空格和换行符,因此在输入中的空格没有被回显。
发送给cin的输入被缓冲。意味着只有在用户按下回车健后,他输入的内容才会被发送给程序。按下回车键后,整个字符序列将被发送给程序,但程序在遇到#字符后将结束对输入的处理。
例子2
使用cin.get(ch)
// textin1.cpp -- reading chars with a while loop
#include <iostream>
/*
int main() {
using namespace std;
char ch;
int count = 0; // use basic input
cout << "Enter characters; enter # to quit:\n";
cin >> ch; // get a character
while (ch != '#') { // test the character
cout << ch; // echo the character
++count; // count the character
cin >> ch; // get the next character
}
cout << endl << count << " characters read\n";
// get rid of rest of line
// while (cin.get() != '\n')
// ;
//cin.get();
return 0;
}
*/
// textin2.cpp -- using cin.get(char)
#include <iostream>
int main() {
using namespace std;
char ch;
int count = 0;
cout << "Enter characters; enter # to quit:\n";
cin.get(ch); // use the cin.get(ch) function
while (ch != '#') {
cout << ch;
++count;
cin.get(ch); // use it again
}
cout << endl << count << " characters read\n";
// get rid of rest of line
// while (cin.get() != '\n')
// ;
//cin.get();
return 0;
}
/*
Enter characters; enter # to quit:
Did you use a#2 pencil
Did you use a
13 characters read
*/
在C语言中,要修改变量的值,必须将变量的地址传递给函数。但程序中调用cin.get()时,传递的是ch,而不是&ch。在C语言中,这样的代码是无效的。
在C++中,iostream将cin.get(ch)的参数声明为引用类型,因此该函数可以修改其参数的值。
cin.get()
char name[Size];
....
cout<<"Enter your name:\n";
cin.get(name,Size).get();
//最后一行相当于两个连续的函数调用
cin.get(name,Size);
cin.get();
cin.get()的一个版本接受两个参数:数组名(字符串(char*类型)的地址)和Size(int类型的整数)
注:数组名是第一个元素的地址,因此字符数组名的类型为char*。
char ch;
cin.get();
这里cin.get接受一个char参数。
在C++中,因为该语言支持函数重载的OOP特性。函数重载允许创建多个同名函数,条件是它们的参数列表不同。
文件尾条件
Windows中有一个名为gofish.exe的可执行程序和一个名为fishtable的文本文件
gofish<fishtable
键盘的模拟EOF
//EOF
<CTRL>+<z>+<ENTER> [可能有ENTER]
code
#include <iostream>
int main() {
using namespace std;
char ch;
int count = 0;
cin.get(ch); // attempt to read a char
while (cin.fail() == false) { // test for EOF
cout << ch; // echo character
++count;
cin.get(ch); // attempt to read another char
}
cout << endl << count << " characters read\n";
return 0;
}
/*
THe green ertyui
THe green ertyui
Yes,but the crow
Yes,but the crow
^Z^Z
34 characters read
*/
cin.clear():清楚EOF标记
CTRL+Z实际上将结束输入和输出,而cin.clear()将无法恢复输入和输出。
常见的字符输入的做法
每次读取一个字符,知道遇到EOF的输入循环
cin.get(ch); // attempt to read a char
while (cin.fail() == false) { // test for EOF 也可以while(!cin.fail())
cout << ch; // echo character
++count;
cin.get(ch); // attempt to read another char
}
get()&put()
iostream
ch=cin.get();
cout.put();
一般情况
char ch;
int count = 0;
cin.get(ch); // attempt to read a char
while (cin.fail() == false) { // test for EOF
cout << ch; // echo character
++count;
cin.get(ch); // attempt to read another char
}
可以使用int ch,并用cin.get()代替cin.get(char),用cout.put()代替cout,用EOF测试代替cin.fail()测试
int ch;
int count = 0;
ch=cin.get();
while (ch!=EOF) { // test for EOF
cout.put(ch); // echo character
++count;
ch=cin.get(); // attempt to read another char
}
code
// textin4.cpp -- reading chars with cin.get()
#include <iostream>
int main(void)
{
using namespace std;
int ch; // should be int, not char
int count = 0;
while ((ch = cin.get()) != EOF) // test for end-of-file
{
cout.put(char(ch));
++count;
}
cout << endl << count << " characters read\n";
return 0;
}
两个函数的对比
//价格输入中的下一个字符读入到ch1中,并将下一个字符符入到ch2
cin.get(ch1).get(ch2);
头文件iostream代替stdio.h
5.6、循环嵌套和二维数组
int maxtemps[4][5]
例子
// nested.cpp -- nested loops and 2-D array
#include <iostream>
const int Cities = 5;
const int Years = 4;
int main() {
using namespace std;
const char *cities[Cities] = { // array of pointers
// to 5 strings
"Gribble City",
"Gribbletown",
"New Gribble",
"San Gribble",
"Gribble Vista"
};
int maxtemps[Years][Cities] = { // 2-D array
{96, 100, 87, 101, 105}, // values for maxtemps[0]
{96, 98, 91, 107, 104}, // values for maxtemps[1]
{97, 101, 93, 108, 107}, // values for maxtemps[2]
{98, 103, 95, 109, 108} // values for maxtemps[3]
};
cout << "Maximum temperatures 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;
}
// cin.get();
return 0;
}
/*
Maximum temperatures for 2008 - 2011
Gribble City: 96 96 97 98
Gribbletown: 100 98 101 103
New Gribble: 87 91 93 95
San Gribble: 101 107 108 109
Gribble Vista: 105 104 107 108
*/
几种不同的方法的对比
//方法1:char指针数组
const char *cities[Cities] = {....};
//方法2:char数组的数组
char cities[cities][25]={.....};
//方法3:string对象数组
char string cities[cities]={....};
5.7、总结
如果ch是一个char变量,则下面的语句将输入中的下一个字符读入到ch中
cin>>ch;
然而,它将忽略空格、换行符和指标符。下面的成员函数调用读取输入中的下一个字符。(而不用管该字符是什么),并将其存储到ch中
cin.get(ch);
成员函数调用cin.get()返回下一个输入字符——包括空格、换行符和制表符。
ch=cin.get();
cin.get(char)成员函数调用通过返回转换为false的bool值来指出已达到EOF
而cin.get( )成员函数调用通过返回EOF值来指出已到达EOF