字符串处理与string解析

Java字符串处理终极指南:从基础到高级,全面解析String、StringBuffer与StringBuilder Java中的String是一个不可变对象,这意味着一旦创建了String对象,其值就不能被更改。任何对String的操作都会导致新String对象的生成。这种设计有利于提高安全性和简化内存管理。在Java中,和是用于处理可变字符串的类。它们允许修改字符串内容而不需要创建新的对象。这在需要频繁修改字符串时非常有用,可以显著提高性能。:线程安全的,适合多线程环境。:非线程安全,但在单线程环境下比更高效。 阅读详情

basic_string为何物

         当编译string相关的代码出错时,常常会报一堆很长的错,其中会出现basic_string,如果你清楚string的定义,就不足为奇了:

template <class _CharT,
         class _Traits = char_traits<_CharT>,
         class _Alloc =__STL_DEFAULT_ALLOCATOR(_CharT) >
class basic_string;
 
typedef basic_string<char>    string;
typedef basic_string<wchar_t>wstring;

string继承于_String_base: classbasic_string : private _String_base<_CharT,_Alloc> {... };

其内存管理与vector类似,也维护了三个指针变量:

  using _Base::_M_start;   //对应于begin

  using _Base::_M_finish;  //对应于end

  using _Base::_M_end_of_storage; //对应于容量尾

这三个成员变量在_String_base中的属性为protected,由于是private继承,要使成员在子类中可见,需要使用using关键字。

以下是个private继承实例:

class Base
{
protected:
       int data;
};
 
class Derived: private Base
{
public:
       void setData(int a)data(a){}
       int getData(){return data;}
protected:
       using base::data;
};

string常用操作

         在c语言中,字符串处理离开不了strlen,strcpy, strcat, strcmp, strstr等函数,string类作为char* 类型的一种封装,提供了自己的一套字符串操作接口:

substr    //对应于用strcpy或strcat拷贝子串

append/insert    //对应于strcat,append只用于尾部插入,insert可以在指定位置插入子串

find/rfind     //对应于strstr, 查找函数有多个,其中rfind为反向查找

关系运算 > < == 或 compare(关系运算)   //对应于strcmp

erase //删除指定区间的字符

c_str()/data()   //从源码看c_str等价于data() 返回const char*字符串,其定义如下:

       const_CharT* c_str() const { return _M_start; }
       const_CharT* data()  const { return _M_start;}

begin()/end()

[]/at   //返回第i个字符元素,[]不提供范围检查,at提供范围检查,其源码如下

 reference at(size_type __n) {
   if (__n >= size())
     _M_throw_out_of_range();
   return *(_M_start + __n);
  }
reference operator[](size_type __n)
{ return*(_M_start + __n); }

assign和=  //赋值操作

swap  //交换两个string

replace //替换string内容

完整的参数及形式可参考:标准C++中的string类的用法总结

sizeof 和string的关系

sizeof(string) = 32;  //相当于一个类的大小

string strArray[] = {"one","two", "three"}; //获取string数组的维数用sizeof(strArray)/ sizeof(string) 或sizeof(strArray) / sizeof(strArray[0])

用于函数的情况:void process(string strArray[]) //这边strArray已经是指针了,故sizeof(strArray) = 4

一些函数的源码及分析:

1)       erase

其源码实现如下(其他形式的erase用法也是调用下面的方法):

 iterator erase(iterator __first, iterator __last) {
   if (__first != __last) {
                               // Themove includes the terminating null.
     _Traits::move(__first, __last, (_M_finish - __last) + 1);
     const iterator __new_finish = _M_finish - (__last - __first);
     destroy(__new_finish + 1, _M_finish + 1);
     _M_finish = __new_finish;
    }
   return __first;
  }

从其中可以看出,调用erase只是析构了对象,并没有销毁空间,故string的size()不变。

replace。

string空间增长状况与vector的空间增长类似,内存管理也类似。

我们可以通过下面的代码了解到:

       string str2;
       for(int i = 0; i < 10; i++)
       {
                str2.append("1");
                cout << "sizeof str2= " << str2.capacity() << endl;
       }

将输出 1,2,4,8,16。

2)       _M_insert_aux

         string内存管理相关函数,想详细了解的话可以看源码,这边不做详细解释了,贴出源码如下(见<string>):

template <class _CharT, class _Traits,class _Alloc>
basic_string<_CharT,_Traits,_Alloc>::iterator
basic_string<_CharT,_Traits,_Alloc>
 ::_M_insert_aux(basic_string<_CharT,_Traits,_Alloc>::iterator __p,
                  _CharT __c)
{
 iterator __new_pos = __p;
  if(_M_finish + 1 < _M_end_of_storage) {
   _M_construct_null(_M_finish + 1);
   _Traits::move(__p + 1, __p, _M_finish - __p);
   _Traits::assign(*__p, __c);
   ++_M_finish;
  }
 else {
   const size_type __old_len = size();
   const size_type __len = __old_len +
                            max(__old_len,static_cast<size_type>(1)) + 1;
   iterator __new_start = _M_allocate(__len);
   iterator __new_finish = __new_start;
   __STL_TRY {
     __new_pos = uninitialized_copy(_M_start, __p, __new_start);
     construct(__new_pos, __c);
     __new_finish = __new_pos + 1;
     __new_finish = uninitialized_copy(__p, _M_finish, __new_finish);
     _M_construct_null(__new_finish);
    }
   __STL_UNWIND((destroy(__new_start,__new_finish),
                 _M_deallocate(__new_start,__len)));
   destroy(_M_start, _M_finish + 1);
   _M_deallocate_block();
   _M_start = __new_start;
   _M_finish = __new_finish;
   _M_end_of_storage = __new_start + __len;
  }
 return __new_pos;
}

3)       关系运算符> < == 及 compare(关系运算)

int compare(const basic_string& __s)const
{ return_M_compare(_M_start, _M_finish, __s._M_start, __s._M_finish); }
//compare进行了重载,有多个版本,以上版本的参数是cont string
 static int _M_compare(const _CharT* __f1, const _CharT* __l1,
                        const _CharT* __f2,const _CharT* __l2) {
   const ptrdiff_t __n1 = __l1 - __f1;   //字符串1长度
   const ptrdiff_t __n2 = __l2 - __f2;   //字符串2长度
   const int cmp = _Traits::compare(__f1, __f2, min(__n1, __n2)); //只取n1 n2 中的较短的比较
   return cmp != 0 ? cmp : (__n1 < __n2 ? -1 : (__n1 > __n2 ? 1 :0));   //最后结果需考虑n1 n2
  }

注: ptrdiff_t定义为typedef ptrdiff_t difference_type;

对于关系运算,本质上都是调用的compare函数完成的,下面以< 为例说明

// Operator< (and also >, <=, and>=).
 
template <class _CharT, class _Traits,class _Alloc>
inline bool
operator<(constbasic_string<_CharT,_Traits,_Alloc>& __x,
         const basic_string<_CharT,_Traits,_Alloc>& __y) {
 return basic_string<_CharT,_Traits,_Alloc>
   ::_M_compare(__x.begin(), __x.end(), __y.begin(), __y.end()) < 0;
}
 
template <class _CharT, class _Traits,class _Alloc>
inline bool
operator<(const _CharT* __s,
         const basic_string<_CharT,_Traits,_Alloc>& __y) {
 size_t __n = _Traits::length(__s);
 return basic_string<_CharT,_Traits,_Alloc>
    ::_M_compare(__s, __s + __n, __y.begin(),__y.end()) < 0;
}
 
template <class _CharT, class _Traits,class _Alloc>
inline bool
operator<(constbasic_string<_CharT,_Traits,_Alloc>& __x,
         const _CharT* __s) {
 size_t __n = _Traits::length(__s);
  returnbasic_string<_CharT,_Traits,_Alloc>
   ::_M_compare(__x.begin(), __x.end(), __s, __s + __n) < 0;
}

         从源码可知,关系运算符可处理string和string,string和char *,char*和string。如果比较char*和char*,请使用strcmp,或将其中一个char*转换成string。

4)       find

template <class _CharT, class _Traits,class _Alloc>
basic_string<_CharT,_Traits,_Alloc>::size_type
basic_string<_CharT,_Traits,_Alloc>
 ::find(const _CharT* __s, size_type __pos, size_type __n) const
{
  if(__pos + __n > size())
   return npos;   //查找失败返回npos
 else {
   const const_iterator __result =
     search(_M_start + __pos, _M_finish,
            __s, __s + __n, _Eq_traits<_Traits>());
   return __result != _M_finish ? __result - begin() : npos;   //查找失败返回npos
  }
}

其中npos是个static变量,定义如下:

static const size_type npos;
 
template <class _CharT, class _Traits,class _Alloc>
constbasic_string<_CharT,_Traits,_Alloc>::size_type
basic_string<_CharT,_Traits,_Alloc>::npos
  =(basic_string<_CharT,_Traits,_Alloc>::size_type) -1;

所以,使用string类的find函数时,请与string::npos比较看是否find成功。

5)       _M_range_initialize

用于构造string对象,其代码实现如下:

 template <class _ForwardIter>
 void _M_range_initialize(_ForwardIter __f, _ForwardIter __l,
                          forward_iterator_tag) {
   difference_type __n = 0;
   distance(__f, __l, __n);
   _M_allocate_block(__n + 1);
   _M_finish = uninitialized_copy(__f, __l, _M_start);
   _M_terminate_string();
  }
 
 void _M_terminate_string() {
   __STL_TRY {
     _M_construct_null(_M_finish);  //finish指针置空
    }
   __STL_UNWIND(destroy(_M_start, _M_finish));
  }
 
 void _M_construct_null(_CharT* __p) {
   construct(__p);
#  ifdef __STL_DEFAULT_CONSTRUCTOR_BUG
   __STL_TRY {
     *__p = (_CharT) 0;
    }
   __STL_UNWIND(destroy(__p));
#  endif
  }

博客链接: http://blog.youkuaiyun.com/codingcs

欢迎转载,转载请注明出处!

Goose开源程序本地机上 AI 代理,能够从头到尾自动执行复杂的开发任务。Goose 不仅可以提供代码建议,还可以自主构建整个项目、编写和执行代码、调试故障、编排工作流程以及与外部 API 交互 Goose开源程序 是您的本机上 AI 代理,能够从头到尾自动执行复杂的开发任务。Goose 不仅可以提供代码建议,还可以自主构建整个项目、编写和执行代码、调试故障、编排工作流程以及与外部 API 交互。无论您是在构建想法原型、优化现有代码,还是管理复杂的工程管道,goose 都能适应您的工作流程并精确执行任务。 阅读详情

相关推荐

微信中调起支付宝支付

微信中调用支付宝支付,首先我们知道微信是不能直接调用支付宝的,所以我们需要使用一个中间页提示用户在浏览器中打开,然后进行网页支付或打开app支付。以下为详细唤起支付宝的步骤、业务代码以及相关页面图。 如有问题欢迎评论留言,看到定回复哦^_^\(^o^)/~ 一、微信中唤起支付宝,有几个步骤: 1、中间页引导用户在浏览器中打开去唤起支付宝。 2、浏览器中打开支付宝或app中打开支付宝。 3...

han_calligrapher的博客 2万+

字符串解析

在几乎每一种计算机程序语言中,解析字符串都是我们不得不面对的问题。有时这些字符串以一种简单的格式出现,有时它们又变得很复杂。我们将利用多种方法把字符串转换成我们需要的东西。下面,我们将讨论正则表达式、扫描器、解析器以及在什么时候使用它们。 正则法 vs. 上下文无关文法(Context-Free Grammars) 首先,介绍一点点背景知识:解析一个字符串,其实就是用特定的语言来描述它

zry754331875的博客 1512

Ubuntu本地部署CodeX编程助手:CLI配置全指南

本地AI编程助手是当前开发者关注的核心技术趋势,指在不依赖云端API、保障代码隐私前提下,于本地环境运行具备代码理解、多语言补全与知识库检索能力的智能辅助工具。其技术原理涉及模型加载、API网关编排、向量数据库集成及系统级资源调度,关键价值在于可控性、低延迟与合规性。典型应用场景包括企业内网DevOps提效、边缘设备嵌入式开发支持,以及敏感代码场景下的离线编程增强。本文聚焦Ubuntu系统下基于CLI的手动配置路径,深入解析Ollama服务注册、Node.js版本锁定、API Key环境隔离及Qwen2.5

weixin_26804345的博客 595

字符串的全面解析

分析字符串的含义及应用。自己的总结也分享一下。希望对大家有所帮助。总结的还算比较全面。嘻嘻。

weixin_67118900的博客 2万+

STM32_DAC

DAC(Digital-to-Analog Converter,数模转换器)是将数字信号转换为模拟信号的外设,广泛应用于音频输出、波形生成、电机控制等场景。STM32F407 系列芯片配备了 2 个 DAC 通道(DAC1 和 DAC2),支持 12 位分辨率,支持多种触发方式,可输出稳定的模拟电压。本文从 DAC 的基本原理出发,详细讲解 STM32F407 DAC 的配置方法、代码实现、波形生成以及实际应用案例,帮助你快速掌握 DAC 的使用技巧。

轩宇的博客 1241

在WPS/Office中免费使用AI,快速提升办公效率!​

《免费解锁WPS/Office AI办公神器教程》摘要: 本教程详解如何通过第三方插件OfficeAI免费实现WPS/Office智能办公,突破官方付费限制。从安全设置到安装配置,手把手教学,涵盖文档生成、PPT美化、Excel图表等核心功能。关键优势包括零成本、全场景支持及云端/本地双模式切换,并附常见问题解决方案。注意需使用WPS 2024+版本,安装时需临时关闭杀毒软件。教程强调工具来源合法性,建议商用购买正版授权。(149字)

杜哥无敌的博客 2304

字符串的详解

串是由零个或多个字符组成的有限序列,在计算机科学中是一种重要的数据类型。字符可以是字母、数字、符号等,对应于计算机中的编码。串可以用来表示文本、图像、音频等数据char* data;int max;int len;}sstring;/*初始化串*//*字符拷贝*//*模式匹配*///串比较//串长//串的联接。

qq_54938554的博客 1万+

Python+ArcGIS实战:5步搞定土壤类型预测(附随机森林模型配置技巧)

本文详细介绍了如何结合Python与ArcGIS,利用随机森林模型进行土壤类型预测。通过5个核心步骤——数据预处理、样本创建、模型构建、空间预测与精度验证,构建了一套自动化、高精度的空间预测工作流,并提供了关键的模型配置与调参技巧,助力GIS开发者高效完成土壤制图任务。

weixin_29227585的博客 396

leetCode394. 字符串解码(超详细分析) by JavaScript

例如,"abcd"可能会被编码为“1[a]1[b]1[c]1[d]”,也可能会被编码为’abcd’,同时,s也可能会被编码为嵌套的形式,例如’6[a2[bcd]]’。分析此问题,输入数据s是一个由数字字符、字母字符和方括号字符组成的字符串,题目保证输入数据有效,那么可以发现’[]’里面的内容一定对应’[’左边紧挨着的数字,由于输入的数据可以进行方括号的嵌套,所以使用栈来解决这个问题完美契合题目的特性。(a) 如果当前字符是数字字符,则向后查找进行数字字符的拼接,作为curNum,直到遇到’[’。

tangpinger的博客 2569

如何理解下一代ERP 即:华为MetaERP

如何理解下一代ERP 即:华为MetaERP 华为的 MetaERP核心定位: 华为MetaERP是华为公司自主研发的下一代企业核心商业管理系统。它不仅仅是一个传统的ERP(企业资源规划)系统,更是一个面向未来、基于云原生、AI驱动、安全可信的企业核心管理平台。

金牌架构师 1142

【docker】第10篇 Failed with result ‘exit-code和Start request repeated too quickly和Failed to start Docker

【docker】解决 Failed with result 'exit-code'和Start request repeated too quickly和Failed to start Docker。

Fanjufei的博客 6819

解析字符串

一、前言 昨天一个朋友在应聘一家公司,公司给了他一道字符串解析的问题,按照自己的思路记录一下。 二、题目 /** * 目标:解析字符串(完成时间48小时内) * 格式: src="t1a=t1b&t2a=t2b&t3a=t3b" * 结果: map[t1a]=t1b,map[t2a]=t2b,map[t3a]=t3b * 要求: 1>使用辅助类型TokenizerEx(测试源文件中包含Tokenizer.h Tokenizer.cpp),可以使用STL中任何数据结构和算法.

行走 1395

基于STM32设计自动输液监测系统(241)

该系统集成了液位传感模块、光电传感器、电机模块、按键模块和OLED显示屏等多个功能模块,以实现全面的输液过程监控和控制。液位传感模块能够实时监测输液瓶中的液位,当液位到达限定值时,系统会自动控制步进电机夹紧输液管,并发出报警提醒,确保输液过程不会因液位过低而中断。

1341

【掌握 Java 字符串处理:String 与 StringBuffer 深入解析】

通过这次学习和练习,我们回顾了String和的核心区别(不可变 vs 可变)以及它们各自的适用场景。String适用于内容固定的字符串,而(或)更适合需要频繁修改的字符串。掌握它们的常用方法,如查找、截取、替换、拼接等,对于日常 Java 开发至关重要。

m0_65015341的博客 1601

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

C 标准库 <string.h> 深度解析:字符串处理的艺术与陷阱

永远检查字符串是否以'\0'结尾永远为字符串分配足够空间优先使用安全函数snprintfstrncatstrtok_r始终检查返回值(如strchrstrstr可能返回NULL。

weixin_55932020的博客 1374

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

std::string深度解析:C++字符串处理

本文深入解析C++中的std::string字符串处理机制。相比C风格字符串,std::string通过小字符串优化(SSO)策略,在栈或堆上灵活存储数据,并自动管理内存。文章详细介绍了std::string的内部结构、内存管理策略,并通过实战案例演示了字符串构造、拼接、比较、容量管理等基础操作,以及搜索、修改等高级功能。这些特性使std::string成为更安全高效的字符串处理工具,避免了C语言中常见的缓冲区溢出等问题。

weixin_42108533的博客 936

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

【Java 11字符串处理新利器】:深入掌握String的lines()方法高效文本解析技巧

掌握Java 11 String 的 lines() 方法,轻松实现高效文本行解析。适用于日志处理、文件读取等场景,结合Stream操作灵活便捷,提升代码可读性与性能。深入解析使用技巧与实战示例,值得收藏。

VarFun的博客 943

String、StringBuffer与StringBuilder深度解析:架构师视角的字符串处理最佳实践

字符串操作选择决策树:├── 操作频率低(<10次)│ └── 使用 String├── 操作频率高(>10次)│ ├── 单线程环境│ │ └── 使用 StringBuilder│ └── 多线程环境│ ├── 局部变量│ │ └── 使用 StringBuilder│ └── 共享变量│ └── 使用 StringBuffer。

ma451152002的专栏 1045

深入理解Java字符串处理三剑客:String、StringBuffer、StringBuilder全面解析

场景推荐类理由静态常量String利用字符串池优化内存单线程动态拼接无锁设计性能最优多线程安全操作同步方法保障线程安全高频修改的小字符串char[]直接操作数组避免对象开销(如密码处理)通过深入理解三者的底层机制,开发者可以在性能与安全之间做出精准权衡。建议在代码审查时重点关注字符串处理方式,避免因滥用String导致内存泄漏或性能瓶颈。

因为热爱,所以付出 1026

HoRain云--Java字符串处理三剑客:String、StringBuilder与StringBuffer全解析

【摘要】本文深入解析Java中String、StringBuffer和StringBuilder的核心区别与应用场景。三者在可变性、线程安全和性能上存在显著差异:String不可变且线程安全,适合静态字符串;StringBuffer线程安全适合多线程环境;StringBuilder性能最优但非线程安全,推荐单线程使用。文章通过对比表格和流程图指导选型,强调避免使用"+"拼接字符串、初始化时指定容量等最佳实践,帮助开发者根据字符串修改频率和线程环境做出最优选择。

2401_86544677的博客 894

Java字符串处理三剑客:String、StringBuffer与StringBuilder深度解析

记得2024年我在参与一个大型电商平台项目时,曾遇到过一个令人难忘的性能问题。在促销活动高峰期,系统日志处理模块突然变得异常缓慢,导致整个订单处理流程延迟。经过长达8小时的紧急排查,我们最终发现问题根源竟是一段简单的字符串拼接代码——开发者在循环中使用了"+"操作符来拼接日志信息,这在Java中意味着创建了大量临时的String对象。这个价值数百万美元的教训让我深刻认识到,在Java中选择正确的字符串处理方式绝非小事。 作为Java中最基础也最常用的数据类型,字符串处理效率直接影响着系统性能。

阿新的博客 1322

Java字符串处理深度解析:String、StringBuffer与StringBuilder的奥秘

在Java开发中,字符串处理是一项基础而核心的工作。字符串不仅在日常的业务逻辑处理中应用广泛,而且在性能敏感型的应用(如大数据处理)中也扮演着重要角色。熟悉String、StringBuffer和StringBuilder这三者在不同场景下的性能差异和适用条件,对于提升应用性能至关重要。通过对String、StringBuffer与StringBuilder的全面解析,我们不仅能够更深入地理解Java字符串处理的核心原理,还能够根据具体的应用场景做出合理的性能优化决策。

仰望苍穹 1173

Java字符串处理:String.charAt 用法解析

很多朋友在开发的时候,经常会获取字符串中的某一个字符或者某一部分字符,获取某一部分用 String.substring,在我的上一篇博客中已经详细介绍了,有兴趣的朋友可以去看看。本文主要介绍 charAt 的用法并进行实际代码输出结果的演示,还拓展了 indexOf 和 charAt 用法比较,介绍的还是非常详细的。希望对大家有用!

qq_46119575的博客 3389

Java String:深入解析与实战技巧,掌握字符串处理的精髓

在Java编程中,`String` 类是不可变的(Immutable),它位于 `java.lang` 包下,是Java编程语言中最常用的类之一。`String` 对象用于表示文本信息,可以包含任何字符序列,包括字母、数字、空格和特殊字符。下面,我们将深入探讨Java中`String`类的各种特性和用法。

我是eleven,这是我的博客,希望通过我输出的内容能够帮助到大家。 530

Java 字符串处理:String、StringBuilder 与 StringBuffer 的深度解析

特性String可变性不可变可变可变线程安全性安全(因不可变)非线程安全线程安全性能低(频繁修改时)高中(因加锁)适用场景不常修改的字符串单线程频繁修改多线程频繁修改理解 String、StringBuilder 和 StringBuffer 的区别,是 Java 程序员的基本功。在实际开发中,根据场景合理选择字符串类,不仅能提升程序性能,还能避免潜在的线程安全问题。希望通过本文的解析,你能对这三种字符串类有更深入的理解,并在面试和实际开发中灵活运用。

2401_83384536的博客 444
上一篇: stl之关联容器——set,map,hashtable
下一篇: 仿函数functor和function adapters
LinuxG_G
博客等级 码龄15年 58粉丝 176原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值