开发范式
输入和输出
程序员的另一部分时间是用在获取需求输入上
基本上普通开发者都是业务逻辑翻译员,
传统开发的最重要的事情就是要理解客户的需求,把需求翻译成计算机系统的流程和逻辑
AI 开发是基于大模型的开
在 AI 时代从翻译业务逻辑的程序员转变为能调教大模型的工程师
应用开发、微调开发、专有模型开发
从大模型知识到能力的跃迁,提高竞争力
这个阶段遇到的主要问题是「需求模糊」或者「需求理解不一致」。
C++ 应用
对象-内存-二进制数据-序列化-反序列化
内存中对象转换为二进制数据
二进制数据转换为内存中的对
memcpy() 从源头指向的内存块拷贝固定字节数的数据到目标指向的内存块.
与strcpy()函数不同的是,该函数不会检查任何终止字符(如'\0'),而总是精确的拷贝参数传入的字节数
memcpy()函数拷贝结构体数据
用循环的方式将字节内容逐一拷贝,直到达到要求的字节数为止.
-B <path> 或 --build <path>:
指定构建目录,也就是生成的 Makefile 或其他构建系统文件将被放置的地方,
以及最终二进制文件将被编译到的位置。
如果指定的目录不存在,CMake 会创建它。
C++ 编程起始
int main(int argc,char* argv[]) 也可以写成 int main(int argc,char** argv)
int main(int argc,char* argv[]) 也可以写成 int main(int argc,char** argv)。
argc 表示程序运行时发送给main函数的命令行参数的个数(包括可执行程序以及传参)。
argv[]是字符指针数组,它的每个元素都是字符指针,指向命令行中每个参数的第一个字符。
argv[0]指向可执行程序。
argv[1]指向可执行程序后的第一个字符串。
argv[2]指向可执行程序后的第二个字符串 。
argv[3]指向可执行程序后的第三个字符串 。
argv[argc]为NULL。
--表现形式和内容本质
char* argv[]和char** argv的声明差异,从声明、内存管理和文件作用域
声明差异-语法
char* argv[]声明一个数组argv,该数组保存多个指向char类型的指针
char **argv声明 argv为指向(指向 char 类型的指针)的指针
换句话说,一个是数组类型的声明,一个是指针类型的声明
从内存管理的角度分析
在声明数组的时候,会在内存中分配连续的数组空间
在分配指针的时候,不会分配上述空间
从函数传参
对于函数传参,这两种方式的运行结果是相同的
指针数组:用于存储指针的数组
char* argv[]来说,首先结合的时argv[]数组,这个数组中的数据类项是 char*, 因此是指针数组
char (*p)[5]首先结合的是(*p),这是个指针,指向的是个数组,因此是数组指针
*argv 是数组中第一个元素相当于line[0],argv[n]就相当于line[n],即地址一个指针,
**argv 是数组中存储的指针所指向的元素,即具体的字符。
C++内存模型
全局/静态存储区:全局变量、静态变量分配在这里。
常量存储区:存储常量字符串
堆内存:动态分配的内存 。 std::shared_ptr 自动管理内存 / 在堆上动态分配对象
栈内存:用于局部变量、函数参数等,通过栈指针自动管理。
静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。
static 被引入以告知编译器,将变量存储在程序的静态存储区而非栈上空间,
静态数据成员按定义出现的先后顺序依次初始化 -静态成员变量一定要在类外进行初始化
函数
c++实现字符串分割split()函数: stringstream类是<sstream>头文件中定义的流之
用非空白符做分割, getline()函数
getline()是 C++标准库中的一个函数,用于从输入流中读取一行文本,并将其存储为字符串 直到遇到换行符 ('\n') 为止
is 是输入流对象(通常是 std::cin)。str 是用于存储读取内容的字符串对象。
getline 还有一个变体,可以指定自定义的分隔符:
getline(istream &__is, string &__str, *char* __delim)
// 例2.将字符串"hello,world,!,My,name,is,C++"按','分割。(非空白符)
std::string str_dat = "hello,world,!,My,name,is,C++";
std::string t;
stringstream ss(str_dat);
vector<string> res;
while (ss.good()){
getline(ss, t, ',');
res.push_back(t);
}
for (auto i : res)
cout << i << endl;
因为stringstream继承自iostream,所以所有支持<<和>>操作的类型(包括自定义的类)都可以利用stringstream进行转换
优化容器操作:
在容器(如 std::vector、std::list 等)中,使用 std::move 可以优化元素的插入和赋值操作。
例如,当向 std::vector 插入一个大型对象时,使用移动构造函数可以避免不必要的复制
emplace_back 函数用于在容器的末尾就地构造一个新元素。它避免了额外的复制或移动操作,因为它直接在容器的内存中构造元素。
emplace_back 可以接受任意数量和类型的参数,这些参数将被转发给新元素的构造函数
getline(ss,t,",");
res.emplace_back(std::move(t));
2.分割符为多个字符时
创建文件夹
1.命令行的方式 方法一: system 函数 方法二: popen 函数
示例
std::string cmd("mkdir -p /data/example");
int ret = system(cmd.c_str());)
语法解释:
0.int system( const char *command )
01.std::string scmd("Initial string"); //根据已有字符串构造新的string实例
std::string s1; //构造一个默认为空的string
std::string s2 (s0); //通过复制一个string构造一个新的string
std::string s3 (s0, 8, 3); //通过复制一个string的一部分来构造一个新的string。8为起始位置,3为偏移量。
std::string s7 (s0.begin(), s0.begin()+7); //通过迭代器来指定复制s0的一部分,来创建s7
02.c_str() 函数可以将 const string* 类型 转化为 const char* 类型
头文件:#include<cstring>
在c语言中没有string类型,故必须通过string类对象的成员函数c_str()把string 对象转换成c中的字符串样式。
C++ 中 c_str()就是将C++的string转化为C的字符串数组,
c_str()生成一个const char *指针,指向字符串的首地址
2.
在C++中(c++17 以上),
<filesystem> 头文件中的std::filesystem::exists() 函数来检查文件是否存在
01. std::experimental::filesystem::exists() 查找文件是否存在
02. std::experimental::filesystem::is_directory() 判断是否是一个目录
03. std::experimental::filesystem::create_directory() 单层级目录创建
0 std::experimental::filesystem::create_directories 多层级目录创建
早期 C++ 版本中的std::experimental::filesystem是在 C++17 之前的一个技术规范
std::filesystem C++17的技术规范
读取配置文件
fstream又细分了两个分支,分别是处理输入文件流的ifstream和处理输出文件流的ofstream。
ifstream负责将文件从硬盘读取至内存中。
ofstream负责将文件从内存写入硬盘中。
// 以二进制模式打开文件
std::ifstream file("example.bin", std::ios::binary | std::ios::ate);
// std::ios::ate 定位到文件末尾,便于获取文件大小
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::string line;
std::ifstream file("example.txt"); // 打开文本文件
if (file.is_open()) {
while (getline(file, line)) { // 按行读取
std::cout << line << '\n';
}
file.close();
} else {
std::cout << "Unable to open file";
}
return 0;
}
读取配置文件
json
yaml
1.读取json
#include<jsoncpp/json/json.h>
Json::Reader reader;
Json::Value cfg_value;
std::ifstream input_file(cfg_path.c_str()); // 打开文本文件
if (input_file.is_open()) { exit(-1)}
input_file >> cfg_value;
input_file.close();
//当json对象里有多个子对象,想要取出其子对象时可用函数getMemberNames(),
//其返回值是Json::Value::Members类型,其实是一个标准的std::vector<string>类型:
for(const auto &key:cfg_value.getMemberNames() ){
std::string name = cfg_value[key].asString();
}
Json::Value::Members members = cfg_value["role"].getMemberNames()
// 解析完成,开始访问JSON对象
std::string name = cfg_value["name"].asString();
/////.jsoncpp写json
Json::Value root; //根节点
//编写root
root["project"] = "classify";
root["base_params"]["height"] = 480;
// 创建json 文件
fstream f;
f.open ("test.json", ios::out);
if( !f.is_open() ){
cout<< "Open file error!" <<endl;
}
f << root.toStyledString(); //转换为json格式并存到文件流
f.close();
读取yaml
#include "yaml-cpp/yaml.h"
// 加载YAML文件
YAML::Node params = YAML::LoadFile(cfg_path.c_str());
// 获取对应的值
std::string file_nm = params["file_nm"].as<std::string>();
基础示例
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World!";
size_t pos1 = 1;
size_t pos2 = 10;
// 手动交换字符
char temp = str[pos1];
str[pos1] = str[pos2];
str[pos2] = temp;
// 展示结果
std::cout << str << std::endl; // 输出: Hello, dlroW!
return 0;
}
参考
c++实现字符串分割split()函数(实用,详细)https://zhuanlan.zhihu.com/p/660791531
标签:std,string,配置文件,argv,char,C++,str,内存
From: https://www.cnblogs.com/ytwang/p/18435160