一、转义字符
1. \ 和某些字符结合产生新的字符叫做转义字符
'\0' == ASCLL码值为0
'\n' == 换行符
'\t' == tab缩进符
'\r' == 回到行首符号
'\a' == 发出警报
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << "##" << '\0' << "##" << endl; // ## ##
cout << "##" << '\n' << "##" << endl;
/*
##
##
*/
cout << "##" << '\t' << "##" << endl; // ## ##
cout << " &##" << '\r' << "##" << endl; // ##&##
cout << "##" << "\a" << "##" << endl; // ####(发出报警)
return 0;
}
2. 八进制转义
'\ddd' 每个d的范围必须是0-7 3个d表示最多识别3位八进制数据
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << '\123' << endl; // S
// 1*8^2+2*8^1+3*8^0 = 64+16+3 = 83 ASCLL码表 对应的是 S
return 0;
}
3. 十六进制转义
'\xhh' 每个h的范围必须是0-f 2个f表示最多识别2位十六进制数据
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << '\x50' << endl; // P
// 5*16^1+0*16^0 = 80+0+80 = 80 ASCLL码表 对应的是 P
return 0;
}
二、类型转换
数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型转换的问题。
转换的方法有两种:
1. 自动转换:遵循一定的规则,由编译系统自动完成
2. 强制转换:把表达式的运算结果强制转换成所需的数据类型
自动类型转换规则
1. 占用内存字节数少(值域小)的类型,向占用内存字节数多(值域大)的类型转换,以保证精度不降低
2. 转换方向:
char,short ——> signed int ——> unsigned int ——> long ——> double <—— float
无符号数和有符号数参加运算需要将有符号数转换成无符号数
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int data1 = -7;
unsigned int data2 = 6; // 输出不为-1,负数的无符号数是其补码
cout << data1 << '+' << data2 << '=' << data1+data2 << endl;
return 0;
}
int和double参见运算会将int转换成double类型
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int data1 = 0;
double data2 = 0.0;
cout << data1 << '+' << data2 << '=' << data1+data2 << endl;
cout << sizeof(data1+data2) << endl; // 8个字节,运算结果为double类型
return 0;
}
char和short类型只要参加运算都会将自己转换为int类型
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
char ch = 'a';
short sh = 0;
cout << ch << '+' << sh << '=' << ch+sh << endl; // a的ASCLL码值为97,加上0等于97
cout << sizeof(ch+sh) << endl; // 4个字节,运算结果为int类型
return 0;
}
强制类型转换
(类型说明符)(表达式)
功能:把表达式的运算结果强制转换为类型说明符所表示的类型
例如:
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << (int)'a'+1 << endl; // 98
cout << (int)('a'+1) << endl; // 98
return 0;
}
不管是自动类型转换还是强制类型转换都是临时的
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int x = 0;
float f = 3.14f;
x = (int)f;
cout << x << endl; // 3
cout << f << endl; // 3.14,(int)f操作后f本身的值没有改变
return 0;
}
三、运算符
用算术运算符将运算对象(也称操作数)连接起来的,符合C++语法规则的事自,称为C++算数表达式,运算对象包括常量、变量、函数返回值等。
10(运算对象) +(运算符) 20(运算对象)
如果运算符需要一个运算对象就叫单目运算符
如果运算符需要两个运算对象就叫双目运算符
如果运算符需要三个运算对象就叫三目运算符
如果运算符需要多个运算对象就叫多目运算符
1. 算数运算符
+ - * / %
/ 的取整
如果 / 的所有运算对象都是整数,/ 的功能就是取整
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << 5/3 << endl; // 1
cout << 5/2 << endl; // 2
return 0;
}
/ 的除法运算
如果 / 有一个运算对象是实型,/ 的功能就是除法运算
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << 5.0/3 << endl; // 1.66667
cout << 5/2.0 << endl; // 2.5
return 0;
}
% 取余运算符
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << 5 % 3 << endl; // 2
cout << 5 % 2 << endl; // 1
return 0;
}
案例:如果rand函数产生一个随机数>0,请使用rand()产生60-100的随机数
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
for(int i=0;i<10;i++)
{
cout << rand()%41+60 << endl; // 2
}
return 0;
}
2. 符合运算符
+= -= *= /= %=
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a = 5;
int b = 6;
a += b;
cout << "运算后的结果为:" << a << endl; // 11
a -= b;
cout << "运算后的结果为:" << a << endl; // 5
a *= b;
cout << "运算后的结果为:" << a << endl; // 30
a /= c;
cout << "运算后的结果为:" << a << endl; // 5
a %= b;
cout << "运算后的结果为:" << a << endl; // 5
return 0;
}
注意:一定要将=右边看作一个整体
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a = 5;
int b = 6;
int c = 7;
a *= b + c;
cout << "运算后的结果为:" << a << endl; // a=a*(b+c)=65
return 0;
}
3. 关系运算符
< > == <= >= !=
4. 逻辑运算符
&& || !
5. 随机数
产生随机数使用rand() 函数
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << rand() << endl;
return 0;
}
执行多次程序会发现每次产生的随机数相同,这是因为随机数种子固定,默认为1
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << rand() << endl; // 41
srand(0); // 设置随机数种子
cout << rand() << endl; // 38
srand(1);
cout << rand() << endl; // 41
return 0;
}
手动修改随机树种子非常麻烦,我们可以使用当前时间作为随机数种子,需要加入time.h头文件
#include <iostream>
#include <time.h>
using namespace std;
int main(int argc, char *argv[])
{
srand(time(NULL)); // 将时间设置为随机数种子
cout << rand() << endl; // 8236
return 0;
}
6. 位运算符
(1) & 按位与
语法:全1为1,有0为0
特点:和1相与保持不变,与0相与为0
场景:将指定位清0
案例:data为1字节数据,将data的第3,4位清0,其他位保持不变
#include <iostream>
#include <bitset>
using namespace std;
int main(int argc, char *argv[])
{
unsigned int data;
cout << "请输入数字:";
cin >> data;
// data = data & 11100111; 错误,C++会将11100111认作十进制,应改写成C++可以识别的十六进制
cout << data << "的二进制数为:" << bitset<8>(data) << endl;
data = data & 0xe7;
// data &= 0xe7; 复合运算符也可以
cout << "位运算后的数字为:" << bitset<8>(data) << endl;
return 0;
}
(2) | 按位与
语法:有1为1,全0为0
特点:和1相或为1,和0相或保持不变
场景:将指定位置1
案例:data为1字节数据,将data的第3,4位置1,其他位保持不变
#include <iostream>
#include <bitset>
using namespace std;
int main(int argc, char *argv[])
{
unsigned int data;
cout << "请输入数字:";
cin >> data;
// data = data | 00011000; 错误,C++会将00011000认作十进制,应改写成C++可以识别的十六进制
cout << data << "的二进制数为:" << bitset<8>(data) << endl;
data = data | 0x18;
// data |= 0x18; 复合运算符也可以
cout << "位运算后的数字为:" << bitset<8>(data) << endl;
return 0;
}
(3) ~ 按位与
语法:0变1,1变0
(4) ^ 按位异或
语法:相同为0,不同为1
特点:和1异或取反,和0异或保持不变
场景:将指定位发生翻转
案例:data为1字节数据,将data的第3,4位翻转,其他位保持不变
#include <iostream>
#include <bitset>
using namespace std;
int main(int argc, char *argv[])
{
unsigned int data;
cout << "请输入数字:";
cin >> data;
// data = data ^ 00011000; 错误,C++会将00011000认作十进制,应改写成C++可以识别的十六进制
cout << data << "的二进制数为:" << bitset<8>(data) << endl;
data = data ^ 0x18;
// data ^= 0x18; 复合运算符也可以
cout << "位运算后的数字为:" << bitset<8>(data) << endl;
return 0;
}
(5) << 左移
左边丢弃,右边补0,移动的位数不要超过自身的宽度
左移n位就是乘以2的n次幂
#include <iostream>
#include <bitset>
#include <cmath>
using namespace std;
int main(int argc, char *argv[])
{
int num = 10;
// 0000 1010
num <<= 2; // 通过左移符号
cout << "左移后的结果是:" << bitset<8>(num) << endl;
// 左移后的结果是:00101000
num = num * pow(2,2); // 通过乘以2的n次幂
cout << "左移后的结果是:" << bitset<8>(num) << endl;
// 左移后的结果是:10100000
return 0;
}
(6) >> 右移
右边丢弃,左边边补0(补1)
算数右移、逻辑右移都是编译器决定,用户无法确定
无符号数:右边丢弃,左边补0
有符号数:正数:右边丢弃,左边补0
负数:右边丢弃,左边补0(逻辑右移)
左边补1(算数右移)
左移n位就是除以2的n次幂
#include <iostream>
#include <bitset>
#include <cmath>
using namespace std;
int main(int argc, char *argv[])
{
int num = 180;
// 1011 0100
num >>= 2; // 通过右移符号
cout << "右移后的结果是:" << bitset<8>(num) << endl;
// 右移后的结果是:00101101
num = num / pow(2,2); // 通过除以2的n次幂
cout << "右移后的结果是:" << bitset<8>(num) << endl;
// 右移后的结果是:00001011
return 0;
}
位运算的综合应用
某位置零、置一的简单写法
#include <iostream>
#include <bitset>
using namespace std;
int main(int argc, char *argv[])
{
unsigned int data;
cout << "请输入数字:";
cin >> data;
// data的3,4位置零
data &= ~(0x01<<4 | 0x01<<3);
cout << "位运算后的data为:" << bitset<8>(data) << endl;
// data的3,4位置一
data |= (0x01<<4 | 0x01<<3);
cout << "位运算后的data为:" << bitset<8>(data) << endl;
return 0;
}