三、基本数据类型和计算(二)
三、基本数据类型和计算(二)
1、字符
#include <iostream>
int main()
{
std::cout << 65 << std::endl; //65是一个int类型的整数
std::cout << (char)65 << std::endl; //将其转化为1个字节的char类型字符,编码的正向操作
std::cout << (int)'A' << std::endl; //编码的逆向操作,将字符转化为数字
}
1)字符数据原理
内存数据 | 编码规范 | 显示 |
---|---|---|
65 | ASCII | A |
原理:在内存中最终存储的数据都是数字,字符本质上还是数字,显示什么样的形式,取决于编码规范的实现,上述代码中编码规范的实现是由std::cout类决定的。
ANSI
2)字符数据类型
类型 | 内存占用 | 说明 |
---|---|---|
char | 1 | ascii字符 |
wchar_t | 2/4 | 宽字节字符,使用L来说明变量 |
char16_t | 2 | utf_16字符,使用一个u来说明变量 |
char32_t | 4 | utf_32字符,使用一个U来说明变量 |
①chat类型
#include <iostream>
int main()
{
char charA{ 'A' }; //使用字符初始化字符,编译器会将字符强制转化为数字
std::cout << charA << std::endl;
char charB{ 66 };
std::cout << charB << std::endl; //使用数字的方式初始化字符串
charB++;
std::cout << charB << std::endl; //因字符本质为数字,所以可以进行计算
}
②wchar_t类型
该类型占用两个字节(无论是汉字、数字、字符),因编译器不同,占用的字节数不同(2字节或4字节),定义字符时要通过L来说明字符是一个宽字节字符
#include <iostream> //
#include <locale> //设置本地,显示中文需要包含该头文件
int main()
{
setlocale(LC_ALL, "chs");
wchar_t wcharA{ L'A' }; //定义时使用L进行说明
wchar_t wcharB{ L'我' };
std::wcout << wcharA << std::endl; //std::cout没有实现对宽字节的编码
std::wcout << wcharB << std::endl;
std::cout << "wchar_t的内存大小为:"<< sizeof(wcharA) << std::endl;
}
④char32_t、char16_t
为实现跨平台的应用,引入了char32_t、char16_t,因为wchar_t因平台不同占用的内存不同
#include <iostream> //
#include <locale> //设置本地,显示中文需要包含该头文件
int main()
{
char16_t char16{ u'a' };
std::cout << char16 << std::endl; //std::cout和std::wcout都没有实现对char16_t的编码,因此只能输出数字
char32_t char32{ u'a' };
std::cout << char32 << std::endl; //std::cout和std::wcout都没有实现对char32_t的编码,因此只能输出数字
}
3)ASCII编码表
换行可以使用char(10)表示
//换行
#include <iostream>
int main()
{
std::cout << "Hello World!!" << char(10);
}
4)练习:用户输入一个小写字母,转化为大写字母后输出
//用户输入一个小写字母,转化为大写字母后输出
#include <iostream>
int main()
{
char userIn;
std::cout << "请输入一个小写字母:";
std::cin >> userIn;
userIn -= 32;
std::cout << "转化后的大写字母为:" << userIn << std::endl;
}
2、推断类型
即不告诉编译器使用什么数据类型
1)auto类型
类型定义语法 | 示例 |
---|---|
auto 变量名 {初始值}; | auto a {200}; |
注:auto类型的变量必须初始化,负责编译器无法判断是什么类型的变量
2)查看变量的类型
变量类型查看函数 | |
---|---|
typeid(变量).name |
#include <iostream>
int main()
{
auto num{ 100 };
auto charUser{ U'a' }; //auto类型的变量必须初始化
auto chat_z{ u'A' };
std::cout << "num的类型为" << typeid(num).name() << (char)10;
std::cout << "charUser的类型为" << typeid(charUser).name() << (char)10;
std::cout << "chat_z的类型为" << typeid(chat_z).name() << (char)10;
}
注:日常不推荐使用auto类型,因为代码阅读性不好
3、格式化输出流及转义
1)格式化输出流操作
作用:使用文字输出更美化
注:加粗内容需要使用头文件<iomanip>
格式化输出流 | 含义 | 示例 |
---|---|---|
std::fixed | 以小数点模式输出浮点数 | 3.1415926 |
std::scientific | 以科学计数法输出小数 | 3E100 |
std::defaultfloat | 恢复默认的小数输出,即将上述2个设置取消 | |
std::setprecision(int) | 设置小数精度 | std::setprecision(2),输出3.14 |
std::dec | 以后输出的数字采用十进制输出 | 999 |
std::hex | 以后输出的数字采用十六进制输出 | FFF |
set::oct | 以后输出的数字采用八进制输出 | 777 |
std::showbase | 十六进制和八进制显示前缀 | 0xFF |
std::shownobase | 关闭十六进制和八进制显示前缀 | |
std::setw(int) | 把输出内容设置宽度,每次都需设置 | std::setw(10)输出 999 |
std::setfill(char) | 当显示宽度超过字符快宽度时,用指定字符串填充剩余内容 | **************999 |
std::left | 设置字符对其模式为左对齐 | |
std::right | 设置字符对其模式为右对齐 |
//格式化输出及转义
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::fixed; //以小数点计数
std::cout << 3.1415926 << (char)10;
std::cout << std::scientific;//以科学计数法技术
std::cout << 3.1415926 << char(10);
std::cout << std::setprecision(2); //设置小数精度
std::cout << 3.1415926 << std::endl;
std::cout << std::hex; //以16进制输出
std::cout << 100 << std::endl;
std::cout << std::oct; //以8进制输出
std::cout << 100 << std::endl;
std::cout << std::dec; //以10进制输出
std::cout << 100 << char(10);
std::cout<<std::setw(10) << 2222 << std::endl; //设置输出宽度
//当显示宽度超过字符宽度时,剩余部分使用特定字符填充
std::cout << std::setfill('*') << std::setw(10) << 999 << std::endl; //
std::cout << std::right; //右对齐
std::cout << "helloworld" << std::endl;
}
//输出内容
2)转义
转义序列 | 作用 |
---|---|
\n | 换行 |
\\ | \ |
' | ' |
\t | 制表符 |
" | " |
? | ? |
\b | 退格 |
\a | 警告声 |
4、运算优先级
1)运算优先表
注:下表运算符从上到下依次优先运算
运算符 | 关联性 |
---|---|
:: | 左(从左往右计算) |
() [] -> . 后缀++ 前缀-- typeid const_cast dynamic_cast static_cast reinterpret_cast | 左(从左往右计算) |
! ~ 一元+ 一元- 前缀++ 前缀-- & * (类型)sizeof new new[] delete delete[] | 右(从右往左计算) |
.* ->* | 左(从左往右计算) |
* / % | 左(从左往右计算) |
+ - | 左(从左往右计算) |
<< >> | 左(从左往右计算) |
< <= > >= | 左(从左往右计算) |
== != | 左(从左往右计算) |
& | 左(从左往右计算) |
^ | 左(从左往右计算) |
| | 左(从左往右计算) |
&& | 左(从左往右计算) |
|| | 左(从左往右计算) |
? : op= | 右(从右往左计算) |
throw | 右(从右往左计算) |
. | 左(从左往右计算) |
2)a++和++a的反汇编
#include <iostream>
int main()
{
int a{ 10 };
a++;
++a;
int b{ 5 };
int c{};
c = b + a++; //c=b+a;a=a+1 //后缀优先
c = b + ++a; //a=a+1;c=b+a
c = 3 * -b++ + a; //正负在前,乘除、加减在后
std::cout << c << std::endl;
c = 2 * -b-- - a;
std::cout << c << std::endl;
}
①查看汇编的方法:先设置断点,调试->窗口->反汇编
②a++和++a反汇编代码
结论:++a和a++在不执行其他操作的时候,一样
③c = b + a++和c = b + ++a汇编区别