跳到主要内容C++ 精学笔记:基础类型与语法实践 | 极客日志C++
C++ 精学笔记:基础类型与语法实践
记录了 C++ 基础数据类型及常用语法的实践笔记。涵盖 bool 类型的逻辑与位运算符区别、string 类型的存储机制(SSO)及常用函数(size, substr 等)、枚举类型定义、main 函数参数传递方式以及 switch 分支判断的高效使用。通过代码示例展示了字符串拼接、查找替换及命令行参数处理,旨在巩固 C++ 编程基础。
AiEngineer5 浏览 1.bool 类型:
bool 类型数据在使用时,需要考虑到内存空间的使用情况,目前的 bool 官方限定是 1 个字节,但也可以给 bool 类型数据赋多个字节。bool 值非零就是 true,否则为 false。
**转化为 bool 表达式:都遵循 bool 值非零就是 true,否则为 false。
1.逻辑运算符
2.位运算符
3.比较运算符**
1.1 逻辑运算符
操作数规则:无论操作数是数值还是表达式,都会转为布尔值
运算规则:基于'整体真假'判断,返回值是 bool 类型
核心特性:&&和||有短路求值(按需计算,提升效率 / 避免错误)
| 运算符 | 名称 | 规则 | 短路特性 | 示例(a=5,b=0) |
|---|
| && | 逻辑与 | 全为真才返回 true,否则 false | 左假则右不执行 | a&&b → true&&false → false |
| | | 逻辑或 | 有一个真就返回 true,否则 false |
| ! | 逻辑非 | 真→假,假→真(单目运算符) | 无 | !a → !true → false |
1.逻辑与 (&& == and)
| 操作数 A | 操作数 B | A && B | 说明 |
|---|
| false | false | false | 两边都为真,结果才为真 |
| false | true | false | 短路:A 为假,直接返回假 |
| true | false | false | 短路:B 为假,直接返回假 |
| true | true | true | 两边都为真,返回真 |
2.逻辑或 (|| == or)
| 操作数 A | 操作数 B | A || B | 说明 |
| --- | --- | --- | --- |
| false | false | false | 两边都为假,结果才为假 |
| false | true | true | 短路:B 为真,直接返回真 |
| true | false | true | 短路:A 为真,直接返回真 |
| true | true | true | 两边都为真,返回真 |
3.逻辑非 (! == not)
| 操作数 A | !A | 说明 |
|---|
| false | true | 取反,假变真 |
| true | false | 取反,真变假 |
1.2 位运算符
- 操作数规则:仅支持整数类型(char/int/long 等,本质是),不支持浮点数;
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online
二进制序列
运算规则:对操作数的每一位二进制位逐一计算,返回值是整数类型(运算后的数值);核心特性:无短路,所有操作数都会被计算。| 运算符 | 名称 | 规则(逐位计算) | 短路特性 | 示例(a=6=0000 0110,b=3=0000 0011) |
|---|
| & | 按位与 | 对应位都为 1 则 1,否则 0 | 无 | a&b → 0000 0010 → 数值 2 |
| | | 按位或 | 对应位有 1 则 1,否则 0 | 无 | `a |
| ~ | 按位取反 | 每一位取反(0→1,1→0,单目) | 无 | ~a → 1111 1001(32 位 int)→ 数值 -7 |
#include <iostream>
#include <bitset>
using namespace std;
int main() {
char a = 0b10000001;
char b = 0b00000001;
cout << "a:\t" << bitset<8>(a) << endl;
cout << "b:\t" << bitset<8>(b) << endl;
cout << "~a:\t" << bitset<8>(~a) << endl;
cout << "~b:\t" << bitset<8>(~b) << endl;
cout << "a&b:\t" << bitset<8>(a & b) << endl;
cout << "a|b:\t" << bitset<8>(a | b) << endl;
}
1.3 逻辑运算符和位运算符的区别
| 运算符类型 | 返回值类型 | 示例(a=5,b=0) |
|---|
| 逻辑运算符 | 强制 bool 类型 | a&&b → false(bool) |
| 位运算符 | 整数类型(与操作数一致) | a&b → 0(int),`a |
实际开发过程中也会合理的运用短路来进行条件判断中进行操作,能有效的提升运算速度
2.string 类型
本质:c++ 中,string 类型数据在存储字符串的本质存储,符合下述存储逻辑。
2.1 字符串的存储
-
字符串长度 ≤ SSO 缓冲区大小(GCC 为 15),字符直接存储在 std::string 对象的栈空间。
-
长字符串 (超过 SSO 阈值,长度>15)
例:std::string str1 = "a long string more than 15 chars"; (长度 20)
┌──────────────────────────────── 栈空间(函数栈帧) ────────────────────────────────┐
│ ┌───────────────────────── std::string 对象 str1 ──────────────────────────┐
│ │ │ _M_size: 20
│ │ │ _M_capacity: 31
│ │ │ _M_ptr: 0x7fxxxx1234
│ │ └─────────────────────────────────────────────────────────────────────────┘ │
│ └───────────────────────────────────────────────────────────────────────────────────┘
┌───────────────────────────── 堆空间(地址:0x7fxxxx1234) ──────────────────────────────┐
│ 'a',' ','l','o','n','g',' ','s','t','r','i','n','g',' ','m','o','r','e',' ','t'
│ '\0'
│ (剩余 11 字节:未使用,直到容量 31) │
└──────────────────────────────────────────────────────────────────────────────────────────
2.2 字符串常用函数
包括:size,capacity,substr,empty,to_string,stoi,+
#include <iostream>
#include <string>
using namespace std;
int main(){
string str1{ "test string 001" };
cout << "str1 = " << str1 << endl;
str1 = "test string 002";
cout << "str1 = " << str1 << endl;
string str2{ str1 };
cout << "str2 = " << str2 << endl;
string str3;
str3 = str2;
cout << "str3 = " << str3 << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main(){
string str4{ "1234567890" };
cout << "str4.size = " << str4.size() << endl;
cout << "str4.length = " << str4.length() << endl;
}
#include <iostream>
#include <string>
using namespace std;
int main(){
string str4{ "1234567890" };
str4.capacity = 15
cout << "str4.capacity = " << str4.capacity() << endl;
}
#include <iostream>
#include <string>
using namespace std;
int main(){
string strif;
if (strif.empty()) {
cout << "strif empty empty()" << endl;
}
if (strif.length() == 0) {
cout << "strif empty length()" << endl;
}
if (strif.size() == 0) {
cout << "strif empty size()" << endl;
}
if (strif=="") {
cout << "strif empty "" " << endl;
}
}
stoi/stod/stoll:字符串转整形数字/浮点数/长整型
#include <iostream>
#include <string>
using namespace std;
int main(){
auto i1 = stoi("1234");
++i1;
cout << "i1 = " << i1 << endl;
string d1 = "123.5";
double d2 = stod(d1);
cout << "d1 = " << d1 << endl;
auto f1 = stof("33.1f");
cout << "f1 = " << f1 << endl;
auto f2 = stof("33.1");
cout << "f2 = " << f2 << endl;
cout << stoll("1213214432") << endl;
}
#include <iostream>
#include <string>
using namespace std;
int main(){
auto pistr = to_string(3.1415926);
cout << "pistr = " << pistr << endl;
cout << to_string(-199888)<< endl;
}
string + to_string(int/double):
字符串的拼接,注意整形和浮点类型在字符串中拼接要先转为 string 类型
#include <iostream>
#include <string>
using namespace std;
int main(){
string log;
string txt = "login success!";
string user = "wjj";
int thread_id = 10;
log = "[debug] " + user + ":" + txt + ":" + to_string(thread_id);
cout << "log :" << log << endl;
}
2.3 字符串的截取/索引/替换
包括:substr()/strfind.find()/strfind.replace()
substr():截断字符串 (开始索引,获取长度)
#include <iostream>
#include <string>
using namespace std;
int main(){
string str4{ "1234567890" };
cout << str4.substr(3) << endl;
cout << str4.substr(1, 3) << endl;
}
strfind.find():查找字符串 (string),返回值为索引的开始位置
需要通过如下 string::nXX 进行判断有无查询到,查到了返回索引位置,没查到无返回值
#include <iostream>
#include <string>
using namespace std;
int main(){
string strfind = "test for find [user] test";
string suser = "[wjj]";
auto pos = strfind.find("[test]");
if (pos == string::npos) {
cout << "[test] not find" << endl;
}
string key = "[user]";
pos = strfind.find(key);
cout << "pos = " << pos << endl;
cout << "pos = " << strfind.substr(pos) << endl;
}
strfind.replace():(替换开始的位置,替换多少 size 大小,代替的内容)
注意:替换会改变原字符串,需提前留备份,常与查找组合使用
#include <iostream>
#include <string>
using namespace std;
int main(){
string strfind = "test for find [user] test";
string suser = "[wjj]";
auto pos = strfind.find("[test]");
if (pos == string::npos) {
cout << "[test] not find" << endl;
}
string key = "[user]";
pos = strfind.find(key);
cout << "pos = " << pos << endl;
cout << "pos = " << strfind.substr(pos) << endl;
if (pos != string::npos) {
cout << strfind.substr(pos) << endl;
auto bak = strfind;
auto result1 = strfind.replace(pos,
key.size(),
suser);
cout << bak << endl;
cout << result1 << endl;
}
}
3.枚举类型
简要说明:我们这里使用的是 c++11 之后的枚举方式,相比于 c++11 之前后者的好处
1.避免了不同枚举类型定义中相同枚举值产生冲突的情况。
2.枚举对象不能直接转为整数型参与对比获取,增强了其使用的安全性和防混性。
枚举的定义:c++11 之后定义多了个 class
调用的方式从 c++11 之前的直接获取内容对比,转变为另一种形式
完整代码如下:
4.main 函数的参数传递
4.1 参数说明
main 函数中有三种参数传递:
注意:
1.argc 默认值是 1,例传入 3 个参数 argc = 4
2.argv[索引值]来获取其存储的内容,索引从 0 开始,默认 argv[0]存储的是执行程序的全局路径,例:argv[0] =000001C13F39D6C0
3.env[0],存放的是环境变量。
4.2 参数实践
1.解决方案资源管理器->项目->属性->调试->命令参数
2.项目右键->文件资源管理器中打开->x64->Debug->右键终端打开 进行配置
3.win+R ->cmd ->进入当前目录->进行操作即可
main 中的参数详细说明:
int main(int argc,char *argv[])argc(argument count)是参数个数(整数),不是'存储值的地方';argv(argument vector)是字符串数组(更准确地说,是 char* argv[] 或 char** argv),存储的是每个命令行参数的字符串首地址;argv 的最后一个元素(argv [argc])标准规定为 NULL,这是为了遍历的时候也可以不用 argc,靠判断是否为 NULL 终止。
5.switch 高效的分支判断
switch 很简单,需要注意几点
1.switch 仅支持整形和枚举类型
2.case 执行后要 break;不然后续的都会执行。
#include <iostream>
using namespace std;
enum class Status { PLAY, STOP, ERROR };
int main() {
int x{ 0 };
cin >> x;
switch (x) {
case 0: cout << "cose 0\n"; break;
case 1: cout << "cose 1\n"; break;
case 2: cout << "cose 2\n"; break;
default: cout << "default = " << x << endl;
}
Status status{ Status::PLAY };
switch (status) {
case Status::PLAY: cout << "PLAY" << endl; break;
case Status::STOP: cout << "STOP" << endl; break;
case Status::ERROR: cout << "ERROR" << endl; break;
default: cout << "未知输入" << endl;
}
}
6.实践案例
1.简单日志信息的打出说明
基于上述代码进行进一步实践优化,添加了两个宏和其相应的日志宏[LOG]: