C++ string(初识)

目录

初识string

初始化:

核心基础(std::string 常用基本操作):

获取字符串长度

访问单个字符

字符串拼接

修改字符串

判断字符串是否为空

注意事项:

string 常用接口

string类的成员函数:

constructior  构造函数:

destructor   析构函数

operator=  赋值

迭代器:

容量:

额外解释reserve::

resize


std::string不是 C++ 内置数据类型,而是标准库提供的模板类(准确说是 std::basic_string<char> 的别名),它封装了字符串的存储和各种操作,无需你手动管理内存(比如扩容、释放),是处理字符串的首选。

使用它的前置条件

  1. 必须包含头文件 <string>
  2. 它位于 std 命名空间中,有两种使用方式:
    • 方式 1:添加 using namespace std;(推荐,简洁)
    • 方式 2:直接写 std::string(工程开发更规范,避免命名冲突)

初始化:

#include <iostream> #include <string> using namespace std; int main() { // 1. 直接赋值(最简洁) string s1 = "Hello C++"; // 2. 构造函数初始化(和方式1效果一致) string s2("Hello C++"); // 3. 初始化空字符串(后续可赋值) string s3; // 空字符串,长度为0 s3 = "Later fill content"; // 4. 用已有字符串的子串初始化(结合你之前的疑问) string s4(s1, 6); // 从s1的第6个字符(下标从0开始)开始,复制到末尾,结果为"C++" // 5. 用指定字符重复n次初始化 string s5(5, 'a'); // 5个字符'a',结果为"aaaaa" // 打印验证 cout << "s1: " << s1 << endl; cout << "s2: " << s2 << endl; cout << "s3: " << s3 << endl; cout << "s4: " << s4 << endl; cout << "s5: " << s5 << endl; return 0; }

核心基础(std::string 常用基本操作):

获取字符串长度

两种方法,效果完全一致,推荐 size(),和其他标准库容器一致

string s = "Hello"; cout << "长度:" << s.size() << endl; // 输出:5 cout << "长度:" << s.length() << endl; // 输出:5

访问单个字符

  • 方式 1:[] 下标访问(不做越界检查,运行速度快,新手注意避免下标越界)
  • 方式 2:at() 方法(做越界检查,越界会抛异常,更安全)
string s = "Hello"; char c1 = s[0]; // 获取第一个字符,结果为'H' char c2 = s.at(4); // 获取最后一个字符,结果为'o' cout << c1 << " " << c2 << endl; // 输出:H o // 错误示例(越界) // s[5]; // 无报错,行为未定义(可能崩溃) // s.at(5); // 抛异常,提示越界

字符串拼接

// 方式1:+ 运算符(支持 string 与 string、string 与常量字符串拼接) string s1 = "Hello"; string s2 = " C++"; string s3 = s1 + s2; // 结果为"Hello C++" // 方式2:append() 方法 string s4 = "Hello"; s4.append(" World"); // 结果为"Hello World" cout << s3 << endl; cout << s4 << endl;

修改字符串

string s = "Hello"; // 1. 整体赋值 s = "Hi"; cout << s << endl; // 输出:Hi // 2. 修改单个字符 s[0] = 'h'; cout << s << endl; // 输出:hi // 3. 清空字符串 s.clear(); cout << "清空后长度:" << s.size() << endl; // 输出:0

判断字符串是否为空

string; string s2 = "Hello"; cout << "s1是否为空:" << (s1.empty() ? "是" : "否") << endl; // 输出:是 cout << "s2是否为空:" << (s2.empty() ? "是" : "否") << endl; // 输出:否

注意事项:

  • 忘记包含 <string> 头文件:使用 std::string 必须包含,否则编译器可能报错。
  • 下标越界:访问字符时,下标不要超过 size()-1,优先用 at() 做安全访问。
#include <iostream> #include <string> using namespace std; int main() { string s = "Hello"; int index = 4; // 要访问的下标(最后一个字符的下标) // 先判断下标有效性 if (index >= 0 && index < s.size()) { char c = s.at(index); // 安全访问 cout << c << endl; // 输出:o } else { cout << "下标越界,无效!" << endl; } return 0; }
  • 修改 c_str() 返回的指针:c_str() 返回的是只读指针,不可修改其指向的内容,否则会触发未定义行为。
#include <iostream> #include <string> #include <cstring> // 包含strcpy函数 using namespace std; int main() { string s = "Hello"; // 做法1:直接修改原std::string对象(推荐,最安全) s[0] = 'h'; cout << s << endl; // 输出:hello // 做法2:复制到独立char[]数组后修改(兼容C风格接口) char arr[100]; // 定义足够大的数组 strcpy(arr, s.c_str()); // 把c_str()的内容复制到arr中 arr[0] = 'H'; cout << arr << endl; // 输出:Hello return 0; }
  • 空字符串访问:空字符串(empty() == true)的 size()0,不可访问 [0]at(0)

string 常用接口

string类的成员函数:

(constructor)

constructior  构造函数:

  

  • string()(重点)                            无参构造空的string类对象,即空字符串
  • string(const char* s) (重点)      带参的常量字符串初始化
  • string(const string&s) (重点)    拷贝构造函数
  • string (const char* s, size_t n)      对一个字符串的前n个初始化
  • string (size_t n, char c)                 用 n 个 c 初始化
  • string (const string& str, size_t pos, size_t len = npos)    从pos位置处取len长度的字符进行拷贝构造
     
void test_string1() { string s1; string s2("hello c++"); string s3(s2); string s4(s2, 1, 5);//拷贝部分内容 const char* s5 = "heihei"; string s6(s5); string s7(s5, 5); string s8(100, '#'); cout << s1 << endl; cout << s2 << endl; cout << s3 << endl; cout << s4 << endl; cout << s6 << endl; cout << s7 << endl; cout << s8 << endl; } int main() { test_string1(); return 0; }

destructor   析构函数

(destructor)  

这里我们无需操作,编译器会默认调用构造函数

operator=  赋值

operator=

迭代器:

void test_string3() { string s1("123456"); const string s2("hello world"); // [begin(), end()) // 2、迭代器 (所有容器主流遍历+修改方式) // s1的的每个字符都-- string::iterator it1 = s1.begin(); while (it1 != s1.end()) { (*it1)--; ++it1; } cout << s1 << endl; string::const_iterator it2 = s2.begin(); while (it2 != s2.end()) { // (*it2)--; 不能修改 ++it2; } cout << s2 << endl; string::reverse_iterator it3 = s1.rbegin(); while (it3 != s1.rend()) { cout << *it3 << " "; ++it3; } cout << endl; string::const_reverse_iterator it4 = s2.rbegin(); while (it4 != s2.rend()) { // 不能修改 // *it4 = 'x'; cout << *it4 << " "; ++it4; } cout << endl; } int main() { test_string3(); return 0; }

容量:

#include<iostream> #include<string> #include<list> #include<vector> #include<algorithm> using namespace std; void test_string4() { string s1("12323456567"); cout << s1.size()<< endl; cout << s1.capacity() << endl; string s2; // 确定知道需要多少空间,提前开好,避免扩容,提高效率 //s2.reserve(100); size_t old = s2.capacity(); cout << "capacity:" << old << endl; for (size_t i = 0; i < 100; i++) { s2.push_back('x'); if (s2.capacity() != old) { cout << "capacity:" << s2.capacity() << endl; old = s2.capacity(); } } cout << s1 << endl; s1.clear(); cout << s1 << endl; // 不会缩容,缩容要重新开空间,代价很大 cout << "size:" << s2.size() << endl; cout << "capacity:" << s2.capacity() << endl; //s2.clear(); for (size_t i = 0; i < 50; i++) { s2.pop_back(); } s2.shrink_to_fit(); cout << "size:" << s2.size() << endl; cout << "capacity:" << s2.capacity() << endl; } int main() { /*test_string1();*/ //test_string2(); //test_string3(); test_string4(); return 0; }
额外解释reserve::

考虑到内存对齐,但一定不会比100少;避免连续扩容,效率高

看编译器:VS编译器下,reserve不缩容

resize
#include<iostream> #include<string> #include<list> #include<vector> #include<algorithm> using namespace std; void test_string6() { string s2("123456"); cout << s2 << endl; cout << "size:" << s2.size() << endl; cout << "capacity:" << s2.capacity() << endl; // 插入数据,让size到n个 // n > capacity > size; s2.resize(20, 'x'); cout << s2 << endl; cout << "size:" << s2.size() << endl; cout << "capacity:" << s2.capacity() << endl; // capacity > n > size; //s2.resize(25, 'x'); s2.resize(25); // 插入的是\0 s2.push_back('y'); cout << s2 << endl; cout << "size:" << s2.size() << endl; cout << "capacity:" << s2.capacity() << endl; // 删除数据 // n < size; s2.resize(5); cout << s2 << endl; cout << "size:" << s2.size() << endl; cout << "capacity:" << s2.capacity() << endl; } int main() { test_string6(); return 0; }

Read more

深挖 DeepSeek 隐藏玩法·智能炼金术2.0版本

深挖 DeepSeek 隐藏玩法·智能炼金术2.0版本

前引:屏幕前的你还在AI智能搜索框这样搜索吗?“这道题怎么写”“苹果为什么红”“怎么不被发现翘课” ,。看到此篇文章的小伙伴们!请准备好你的思维魔杖,开启【霍格沃茨模式】,看我如何更新秘密的【知识炼金术】,我们一起来解锁更加刺激的剧情!友情提醒:《《《前方高能》》》 目录 在哪使用DeepSeek 如何对提需求  隐藏玩法总结 几个高阶提示词 职场打工人 自媒体创作 电商实战 程序员开挂 非适用场地 “服务器繁忙”如何解决 (1)硅基流动平台 (2)Chatbox + API集成方案 (3)各大云平台 搭建个人知识库 前置准备 下载安装AnythingLLM 选择DeepSeek作为AI提供商 创作工作区 导入文档 编辑  编辑 小编寄语 ——————————————————————————————————————————— 在哪使用DeepSeek 我们解锁剧情前,肯定要知道在哪用DeepSeek!咯,为了照顾一些萌新朋友,它的下载方式我放在下面了,拿走不谢!  (1)

By Ne0inhk
【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

目录 一、前言 二、AI视频概述 2.1 什么是AI视频 2.2 AI视频核心特点 2.3 AI视频应用场景 三、通义万相介绍 3.1 通义万相概述 3.1.1 什么是通义万相 3.2 通义万相核心特点 3.3 通义万相技术特点 3.4 通义万相应用场景 四、DeepSeek + 通义万相制作AI视频流程 4.1 DeepSeek + 通义万相制作视频优势 4.1.1 DeepSeek 优势 4.1.2 通义万相视频生成优势 4.2

By Ne0inhk
【DeepSeek微调实践】DeepSeek-R1大模型基于MS-Swift框架部署/推理/微调实践大全

【DeepSeek微调实践】DeepSeek-R1大模型基于MS-Swift框架部署/推理/微调实践大全

系列篇章💥 No.文章01【DeepSeek应用实践】DeepSeek接入Word、WPS方法详解:无需代码,轻松实现智能办公助手功能02【DeepSeek应用实践】通义灵码 + DeepSeek:AI 编程助手的实战指南03【DeepSeek应用实践】Cline集成DeepSeek:开源AI编程助手,终端与Web开发的超强助力04【DeepSeek开发入门】DeepSeek API 开发初体验05【DeepSeek开发入门】DeepSeek API高级开发指南(推理与多轮对话机器人实践)06【DeepSeek开发入门】Function Calling 函数功能应用实战指南07【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:本地部署与API服务快速上手08【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:Web聊天机器人部署指南09【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:基于vLLM 搭建高性能推理服务器10【DeepSeek部署实战】基于Ollama快速部署Dee

By Ne0inhk

DeepSeek各版本说明与优缺点分析_deepseek各版本区别

DeepSeek各版本说明与优缺点分析 DeepSeek是最近人工智能领域备受瞩目的一个语言模型系列,其在不同版本的发布过程中,逐步加强了对多种任务的处理能力。本文将详细介绍DeepSeek的各版本,从版本的发布时间、特点、优势以及不足之处,为广大AI技术爱好者和开发者提供一份参考指南。 1. DeepSeek-V1:起步与编码强劲 DeepSeek-V1是DeepSeek的起步版本,这里不过多赘述,主要分析它的优缺点。 发布时间: 2024年1月 特点: DeepSeek-V1是DeepSeek系列的首个版本,预训练于2TB的标记数据,主打自然语言处理和编码任务。它支持多种编程语言,具有强大的编码能力,适合程序开发人员和技术研究人员使用。 优势: * 强大编码能力:支持多种编程语言,能够理解和生成代码,适合开发者进行自动化代码生成与调试。 * 高上下文窗口:支持高达128K标记的上下文窗口,能够处理较为复杂的文本理解和生成任务。 缺点: * 多模态能力有限:该版本主要集中在文本处理上,缺少对图像、语音等多模态任务的支持。 * 推理能力较弱:尽管在自然语言

By Ne0inhk