当前位置: 首页 > news >正文

C++字符串的常用操作

1. 基本介绍

在程序设计中,字符串操作是必不可缺的,无论是工程设计还是算法设计均离不开字符串,字符串是由一个个单独的字符构成的串,其数据结构是线性的,常以ASCII码表示,同时只要设定得当,其展示任何一种编码也都是可以的。

字符串有很多的操作,也有非常多的扩展算法,本文从设计的角度介绍这些基本的字符串操作以及其实现代码,本文实现的大多数代码诸如C和C++中的头文件<string.h>(C++则是<cstring>)已经封装好了相应的函数和方法可以直接使用。

2. 获取字符串长度

顾名思义,指获取一个字符串的长度,在C语言中我们可以直接用strlen(str)来表示,其实现思路可以直接使用一个循环,对每一个字符进行计数,当循环遇到字符’\0’即结束符时循环结束,返回这个循环,示例代码如下:

#include<stdio.h>int _strlen(char str[]){int i=0;for(i=0;str[i]!='\\0';i++){}return i;
}int main(){char *str = "Hello";int len = _strlen(str);printf("%d",len);return 0;
}

输出19

3. 字符位置获取

给定一个字符,获取这个字符串中首次出现这个字符的位置,如果没有找到则给与一个错误信号,如给定一个hello,要求找出l的位置,那么将会找到位置3 ,C语言中可以使用strchr(str,c)表示,实现示例代码如下:

#include<stdio.h>int _charAt(char str[],char c){int i=0;for(i=0;str[i]!='\\0'&&str[i]!=c;i++){}return i;
}int main(){char *str = "Hello";int way = _charAt(str,'l');printf("%d",way);return 0;
}

输出3

4. 拆分子串操作substr

顾名思义,substr对一个字符串进行拆分,也可以称之为对一个字符串的某一段进行截取,如一个字符串的长度有0~n,改操作就是取其中i~j的位置,使其重新生成一个新的字符串,获取的就是这个字符串,在C语言中没有相关的操作,在不同的教程中这样的操作也有不同的命名,本文将此操作命名未substr(在某些别的资料中substr操作则为查找操作),本实现示例代码如下(注意拆分时需要补充结束符’\0’):

#include<stdio.h>char *_substr(char str[],int i,int j){int pos=0;char *backup;while(i<j){backup[pos++] = str[i++];}backup[pos]='\\0';return backup;
}int main(){char *str = "Hello";char *newstr = _substr(str,0,5);printf("%s",newstr);return 0;
}

输出Hello

5. 拆分子串操作prefix

如同上文的操作,截取操作变为了只截取字符串的前m个字符,组成一个全新的字符串,本实现示例代码如下(注意拆分时需要补充结束符’\0’):。

#include<stdio.h>char *_prefix(char str[],int m){int pos=0,i;char *backup;for(i=0 ;i<m ;i++){backup[pos++] = str[i];}backup[pos]='\\0';return backup;
}int main(){char *str = "Hello";char *newstr = _prefix(str,5);printf("%s",newstr);return 0;
}

输出Hello

6. 拆分子串操作suffix

如同上文的操作,截取操作变为了只截取字符串的后m个字符,组成一个全新的字符串,本实现示例代码如下(注意拆分时需要补充结束符’\0’):

这里需要稍微注意一下,在创建字符串的时候,由于各种标准的C对语法的支持不太一样,这里采用较为旧的方式实现,即直接分配一个相应的内存空间,这与上面的做法稍微不同,如果采用char *backup的创建方式,将会产生内存错误问题,这个问题原理较为晦涩,有能力的同学可以参考资料自行理解,这里为了避免冲突简化了操作。

#include<stdio.h>char *_suffix(char str[],int m){int len=0;for(;str[len]!='\\0';len++){}   //获取字符串总长度(避免使用其他封装函数,自行设计时可以使用strlen替代)printf("%d\\n",len-m);int pos=0,i;char backup[500];for(i=len-m ;i<len ;i++){backup[pos++] = str[i];}backup[pos]='\\0';return backup;
}int main(){char *str = "Hello";char *newstr = _suffix(str,3);printf("%s",newstr);return 0;
}

输出com

7.字符串连接操作

顾名思义,即将一个字符串链接到另一个字符串的尾部,我们可以创建一个函数,同时利用指针,分别先后全部遍历两个字符串,将其中一个字符串的结束符’\0’去除并链接另一个字符串直到遇到结束符’\0’即可,函数实现为:

#include<stdio.h>char *_strcat(char dest[],char src[]){char * ret = dest;while(*dest!='\\0'){dest++;}//将src内容复制在dest之后while(*src){*dest++ = *src++;}//在dest后面追加\\0*dest = '\\0';return ret;
}int main(){char str[] = "Hello";char fixstr[] = "Welcome ";_strcat(fixstr,str);printf("%s",fixstr);return 0;
}

输出Welcome Hello

8. 字符串比较操作

顾名思义,对两个字符字符字符串进行比较,常用于确认两字符串是否完全相等,部分高级用法可以扩展到利用大小差别进行容器的算法设计等,比较操作的内容就是对两个字符串进行比较,两个字符串完全相等时返回0,第一个字符串大于第二个字符串时返回一个正值,否则返回负值,实现代码为:

#include<stdio.h>int _strcmp (char  *  src, char  *  dst)   {   int  ret  =  0  ;   while(  !(ret  =  *(unsigned  char  *)src  -  *(unsigned  char  *)dst)  &&  *dst)   //两个内容相减,完全相等则会得到值 0,取反即为相等++src,  ++dst;   if  (  ret  <  0  )   ret  =  -1  ;   else  if  (  ret  >  0  )   ret  =  1  ;   return ret;   
} int main(){char str[] = "Hello ";char fixstr[] = "Welcome ";int ans = _strcmp(fixstr,str);printf("%d",ans);return 0;
}

注意比较的时候要使用unsigned char而不要直接使用char,那是因为计算机编程语言中扩展了char的字符位,使字符位也拥有了含义,因此建议在核心的比较时使用unsigned char的类型。

输出 1

9. 暴力匹配法

这并不是最理想的算法,但却这是字符串匹配算法中最容易理解的算法,算法核心为给定一个主串T和一个模式串P,求问是否P是属于T的一个字串,如:”Hello”中”llo”就是其中的一个字串,对于暴力匹配算法而言,我们可以利用两层循环进行比对,第一层循环中找寻T字符串中的每一个字符,第二层循环找寻的是每一个P字符,进入第二层循环时T字符串也会跟着进行字符前进,如果发生不匹配则产生一个回溯回到第一层循环的进入字符的下一个字符。

代码示例如下:

#include<iostream>
#include<cstring>using namespace std;bool isBF(char str1[],char str2[]){bool flag=false;int len1 = strlen(str1);int len2 = strlen(str2);for(int i=0;i<len1;i++){for(int j=0;j<len2;j++){int pos=i;if( str1[pos++] != str2[j]){break;}else{if(j=len2-1)flag=true;}}}return flag;
}int main(){char str1[] = "HI this is my lesson.";char str2[] = "is";cout<<isBF(str1,str2)<<endl;return 0;
}

输出1

综上假设字符串T的长度为n,字符串P的长度为m,则整个算法的时间复杂度为O( n * m ),而对于一个复杂的现实情况而言 n >> m >> 2 (即n远远大于m,m远远大于常数),这样的计算计算机的负担很重。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • cesium.js 入门到精通(6)
  • vue3.x项目使用高德地图JS API 2.0
  • 如何使用 Vidu Studio 根据照片和提示词生成视频
  • 深入剖析 MQTT 协议:物联网通信的核心力量
  • 【服务器第一期】Xshell、Xftp下载及连接
  • 无人机巡检:突破传统局限,引领智能监测新时代
  • Js中call、apply和bind的区别
  • LibSVM介绍及使用
  • OpenAI gym: How to get complete list of ATARI environments
  • 快人一步迅为LPDDR5版本瑞芯微RK3588核心板升级了
  • k8s环境搭建(续)
  • Typora调整图片大小的两种方式:zoom或width/height
  • docker_持久化存储
  • 2024年06月中国电子学会青少年软件编程(图形化)等级考试试卷(二级)答案 + 解析
  • 工商银行银企直联接口清单
  • C++类中的特殊成员函数
  • Cookie 在前端中的实践
  • HTML中设置input等文本框为不可操作
  • JAVA多线程机制解析-volatilesynchronized
  • Java-详解HashMap
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • Twitter赢在开放,三年创造奇迹
  • Zsh 开发指南(第十四篇 文件读写)
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 将回调地狱按在地上摩擦的Promise
  • 前端之React实战:创建跨平台的项目架构
  • 新手搭建网站的主要流程
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • #LLM入门|Prompt#3.3_存储_Memory
  • #php的pecl工具#
  • #每天一道面试题# 什么是MySQL的回表查询
  • #数据结构 笔记三
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • $.ajax()参数及用法
  • (6)添加vue-cookie
  • (C)一些题4
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)VC++中ondraw在什么时候调用的
  • (转载)虚函数剖析
  • ..回顾17,展望18
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET6 命令行启动及发布单个Exe文件
  • .NET成年了,然后呢?
  • .net反混淆脱壳工具de4dot的使用
  • .vimrc 配置项
  • @Autowired注解的实现原理
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [ vulhub漏洞复现篇 ] struts2远程代码执行漏洞 S2-005 (CVE-2010-1870)
  • [【JSON2WEB】 13 基于REST2SQL 和 Amis 的 SQL 查询分析器
  • [145] 二叉树的后序遍历 js