循环和关系表达式
for循环
副作用和顺序点(顺序)
副作用指的是在计算表达式时对某些东西(如存储在变量中的值)进行了修改
顺序点事程序执行过程中的一个点,在这里进入下一步之前将确保对所有的副作用进行了评估。C++中语句的分号就是一个顺序点,意味着在程序处理下一条语句前,赋值,自增,自减必须完成。
- while(a++<10)
cout<<a<<endl;
C++确保副作用(a++)在进入cout之前完成 - y = 4 + (x++) + 3+(x++); 只会确保在进入下一条语句前,x自增两次,何时递增不确定。
递增 递减运算符和指针
前缀递增和递减,以及解除引用运算符的优先级相同,以从右到左的方式进行结合。后缀递增和后缀递减的优先级相同,但比前缀的优先级高,以从左到右的方式进行结合。
- *++p。 意味着 *(++p),先递增在取值
- ++*p 先取值在递增
- (*p)++
- pt++ , 后缀优先级高,意味着++将用于pt而不是pt。后缀意味着将对原来的地址(而不是增加后的地址),解除引用。但该语句执行完毕,地址会+1.
int main()
{
double array[5] = { 2.2, 2.5, 5.6, 6.3, 9.9 };
double* pa = array; //pa指向第一个元素
pa++; //pa指向第2个元素
double x = *++pa; // 先+后取值 , pa指向第3个元素,x为5.6
cout << x << endl;
double y = ++*pa; //pa现在指向的第三个元素,取值,加1 为6.6 同时第三个元素array[2]的值也变为6.6
cout << y <<" and "<< array[2]<<endl;
(*pa)++; // //pa现在指向的第三个元素,取值,加1 为7.6 同时第三个元素array[2]的值也变为7.6
cout << array[2] << endl;
double z = *pa++; // 后缀优先级高,意味着++将用于pa而不是*pa。后缀意味着将对原来的地址(而不是增加后的地址)即a[2],解除引用。但该语句执行完毕,地址会+1.
cout << z << endl; //a[2] 7.6
cout << *pa << endl; //此时已经是a【3】了 6.3
}
逗号运算符
c++确保先计算第一个表达式,在计算第二个表达式。(逗号运算符可以理解为一个顺序点)
int a,b = a+1; //安全的
逗号表达式是第二部分的值。
i = 20,j = i*20 该表达式的值为40
- 逗号运算符的在所有运算符中优先级最低。
int a = 12,15; 则a为12
int a = (12,15);则a为15
关系运算符
关系运算符的优先级比算术运算符低
即 x+2>y+5 等价于 (x+2) >(y +5)
C风格字符串比较
char word[] = “mate”;
word == “mate”; //数组名是字符串的首地址,用引号引起来的也是字符串的首地址。因次判断的是两个地址是否相同。(不同)
使用strcmp函数,相同返回0,若第一个字符串的字母顺序排在第二个之前则返回一个负数值。
int main()
{
char a[] = "fool";
char b[] = "Fool";
int c = strcmp(a, b); //返回1
cout << c << endl;
char a1[20] = "fool";
char b1[30] = "fool";
c = strcmp(a1, b1); //返回0,由于是以\0找结束位置的
cout << c << endl;
}
int main()
{
char word[5] = "?ate";
for (char ch = 'a'; strcmp(word, "mate"); ch++) //不相同,返回就是非0,相同为0
{
cout << word << endl;
word[0] = ch;
}
cout << "final is " << word;
}
注意:strcmp(word, “mate”); 只要不等,结果就是true
比较string类字符串
可以用关系运算符进行比较,因为类函数重载了这些关系运算符。
int main()
{
string word = "?ate";
for (char ch = 'a'; word !="mate"); ch++) //不相同,返回就是非0,相同为0
{
cout << word << endl;
word[0] = ch;
}
cout << "final is " << word;
}
while循环
while循环类似于for循环也是入口条件循环
int main()
{
char name[] = "hello";
int i = 0;
while (name[i]!='\0') //while (name[i])
{
cout << name[i] << " : " << (int)name[i] << endl; //转为ascii码显示
i++;
}
}
for与while
for与while本质上是相同的,for的两个;必须在
for(;;) {} //将一直循环下去
设计循环时应该遵循以下原则:
- 指定循环终止条件
- 首次测试之前进行初始化
- 在条件被再次测试前更新条件
编写延时循环,让系统时钟完成
clock函数返回系统开始执行后,所用的系统时间
CLOCKS_PER_SEC 每秒包含的系统单位时间数,将系统时间/这个值得到秒数,将秒数*这个值,得到系统时间
#include <iostream>
#include<ctime>
using namespace std;
int main()
{
clock_t start = clock();
double ys = 4;
clock_t delay = ys * CLOCKS_PER_SEC;
while (clock() - start < delay)
{
cout << "on delay:4\n"; //执行4s
}
cout << "end";
}
类型别名
#define BYTE char
typedef char BYTE;
do while
出口条件循环
通常入口循环比出口好点,因为在循环开始之前会对条件进行检查。
但有时,do while 更合理,比如强求用户输入时,先输入,在测试。
基于范围的for循环(C++11)
对数组或容器的每个元素执行相同的操作
- double a[5] = {2,3,4,5,6};
for (doulbe x:a)
{
cout<<x<<endl;
} - for (doulbe &x:a) //修改元素
{
x *=5;
} - for (doulbe x:{2,3,1,25})
{
cout<<x<<endl;
}
循环和文本输入
cin对象支持3种不同的模式进行单字符输入。
使用原始的cin对象
程序用循环读取来自键盘的输入,则必须有办法知道何时停止读取,一种是使用哨兵字符。
#include <iostream>
using namespace std;
int main()
{
std::cout << "Hello World!\n";
char ch;
int count = 0;
cout<<"Enter characters;Enter # to quit" << endl;
cin >> ch; //先读一个 防止第一个就为#
while (ch != '#')
{
cout<< ch;
count++;
cin >> ch;
}
cout << "\n";
cout << count << " character read" << endl;
}
输出:
Hello World!
Enter characters;Enter # to quit
wth faga fafa#dafda
wthfagafafa
11 character read
说明:输出时省略了空格,是cin读取char时,忽略空格和换行符,因此没有显示,也没有计入字符内。
发给cin的输入被缓冲,即不按回车,将一直留在缓冲当中,并没进入cin,也就是输入# 之后还可以继续输入的原因
使用cin.get(char)进行补救
cin.get(ch)读取输入中的下一个字符,并将其赋给ch, 空格也会读取。
#include <iostream>
#include<vector>
using namespace std;
int main()
{
char ch;
int count = 0;
cout<<"Enter characters;Enter # to quit" << endl;
cin.get(ch); //先读一个 防止第一个就为#
while (ch != '#')
{
cout<< ch;
count++;
cin.get(ch);
}
cout << "\n";
cout << count << " character read" << endl;
}
输出:输出有空格,但是还需要按下换行才会停止输入。
文件尾条件
EOF
在键盘输入中模拟EOF。检测到EOF后,cin将(eofbit和failbit)都设置为1。可以通过成员函数eof()查看eofbit是否被设置;如果检测到EOF,则cin.eof()将返回bool值得true。同样如果eofbit或failbit被设置为1,则fail()成员函数返回true。注意eof()和fail()方法都是报告最近读取结果。(事后报告,而不是事前报告),因此应该将eof()和fail()放在读取后
int main()
{
char ch;
int count = 0;
cin.get(ch);
while (cin.fail()==false)
{
cout<< ch;
count++;
cin.get(ch);
}
cout << "\n";
cout << count << " character read" << endl;
}
``
输出:
wang cjifag dfsh
wang cjifag dfsh
sfdsgsh
sfdsgsh
输入ctrl + Z 模拟EOF停止读取
1. EOF结束输入
cin方法检测到EOF时,会设置标记,设置之后,将不能用cin读取输入。(因为程序不应该读取超出文件尾的内容),然而,对于键盘输入,可能使用模拟EOF结束循环,但稍后,还要读取内容。cin.clear()可能清楚EOF标记,使输入继续进行。(有些系统可能不行)
2. 常见字符输入的做法
cin.get(ch);
while (cin.fail()==false) //可以使用 while(!cin.fail())
{
cout<< ch;
count++;
cin.get(ch);
}
或者while(cin)。因为istream类提供了一个可以将istream对象(如cin)转为bool值得函数,当cin出现在需要bool值得地方,该转换函数将会被调用。如果最后一次读取成功了,则转换后的bool值为true。这比!cin.fail()或!cin。eof()更通用,因为它可以检测到其它的故障原因:如磁盘故障
由于cin.get(ch);返回cin因此可以
while(cin.get(ch)){}
## 另一个cin.get()版本(C版本)
```cpp
int main()
{
int ch;
int count = 0;
while ((ch = cin.get())!=EOF) //要加括号。!=优先级高于 =
{
cout.put((char)ch);
count++;
}
cout << "\n";
cout << count << " character read" << endl;
}
嵌套循环和二维数组
int main()
{
int a[5][6];
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 6; j++)
a[i][j] = i * 6 + j;
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 6; j++)
cout<<a[i][j]<<"\t"; //制表符
cout << "\n";
}
//二维数组初始化
int b[2][3] = { {1,2,3},{4,5,6} };
const char* city[3] = { "china","AU","US" };
string citystr[3] = { "china","AU","US" };
}