C++学习笔记(四)

一、转义字符

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不懂编程的大学生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值