【数据结构】数组和字符串(十二):顺序存储字符串的基本操作(串长统计、查找、复制、插入、删除、串拼接)

文章目录

  • 4.3 字符串
    • 4.3.1 字符串的定义与存储
    • 4.3.2 字符串的基本操作(顺序存储)
      • 1. 串长统计
      • 2. 串定位
      • 3. 串复制
      • 4. 串插入
      • 5. 串删除
      • 6. 串拼接
      • 7.主函数
      • 8. 代码整合及优化

4.3 字符串

  字符串(String)是由零个或多个字符(char)顺序排列组成的有限序列,简称为串。例如 “good morning”就是由12个字符构成的一个字符串。一般把字符串记作:

S = ′ ′ a 0 a 1 … a n − 1 ′ ′ S=''a_{0} a_{1}…a_{n-1}'' S=′′a0a1an1′′

  其中S是串名,引号中的字符序列是串值。字符个数是串的长度,长度为0的串被称为空串,因为它不包含任何字符。需要注意的是,空格字符(" ")并不是空串,因为它包含一个字符——空格。
  若把某个串称为主串,则主串中任意个连续的字符组成的子序列被称为子串。子串在主串中第一次出现时,其首字符在主串中的序号被称为该子串在主串中的位置。
  关于字符串的基础知识亦可参考前文:
【重拾C语言】六、批量数据组织(三)数组初值;字符串、字符数组、字符串数组;类型定义 typedef
【重拾C语言】七、指针(三)指针与字符串(字符串与字符串数组;指针与字符串的遍历、拷贝、比较;反转字符串

4.3.1 字符串的定义与存储

  字符串在许多非数值计算问题中扮演着重要的角色,并在模式匹配、程序编译和数据处理等领域得到广泛应用。在高级程序设计语言中,字符串通常被定义为以特殊字符’\0’(称为空字符或字符串结束符)结尾的字符序列。这个约定使得在处理字符串时可以方便地确定字符串的结束位置。关于字符串的存储方式,主要有两种常见的方式:

  • 顺序存储:字符串的字符按照顺序依次存储在连续的内存空间中。这种方式使得字符串的访问和操作效率较高,可以通过索引直接访问任意位置的字符。在顺序存储方式中,字符串的长度可以通过计算字符个数或者遇到’\0’结束符来确定。

  • 链式存储:字符串的字符通过链表的方式进行存储。每个节点包含一个字符和指向下一个节点的指针。链式存储方式可以动态地分配内存,适用于长度可变的字符串。但是相比于顺序存储,链式存储方式需要更多的内存空间,并且访问字符需要遍历链表。

  选择何种存储方式取决于具体的应用场景和需求。顺序存储适合于需要频繁访问和操作字符串的情况,而链式存储适合于长度可变的字符串或者对内存空间要求较高的情况。具体C语言实现可参照前文:
  【数据结构】数组和字符串(十一):字符串的定义与存储(顺序存储、链式存储及其C语言实现)

4.3.2 字符串的基本操作(顺序存储)

  • 串长统计返回串s的长度;
  • 串定位返回字符或子串在母串s中首次出现的位置的指针;
  • 串复制将一个串s2复制到另一个串s1中;
  • 串插入在指定位置后面插入字符串;
  • 串删除是删除一个子串;
  • 串拼接将串s2拼接到串s1的尾部;
  • ……

1. 串长统计

  返回字符串的长度,即字符串中字符的个数。

int stringLength(const char* str) {int length = 0;while (str[length] != '\0') {length++;}return length;
}
  • 接受一个指向字符数组的指针作为参数
  • 通过遍历数组中的字符,直到遇到字符串结束符\0,来确定字符串的长度。
  • 返回值为字符串的长度。

2. 串定位

  查找字符或子串在母串中首次出现的位置,返回指向该位置的指针或索引。

int stringSearch(const char* str, const char* target) {int strLen = stringLength(str);int targetLen = stringLength(target);for (int i = 0; i <= strLen - targetLen; i++) {int j;for (j = 0; j < targetLen; j++) {if (str[i + j] != target[j]) {break;}}if (j == targetLen) {return i;}}return -1;
}
  • 接受两个指向字符数组的指针作为参数:str是要搜索的字符串,target是要查找的目标字符串。
  • 使用双重循环来遍历字符串,并在每个可能的位置比较目标字符串和源字符串的字符。
    • 如果找到了目标字符串,函数返回目标字符串在源字符串中的起始位置;
    • 否则,返回-1表示未找到。

3. 串复制

  将一个串复制到另一个串中:将源串的内容复制到目标串中,使得目标串与源串内容相同。

void stringCopy(char* dest, const char* src) {int i = 0;while (src[i] != '\0') {dest[i] = src[i];i++;}dest[i] = '\0';
}
  • 接受两个指向字符数组的指针作为参数:dest是目标字符串,src是源字符串。
  • 通过遍历源字符串中的字符,并将每个字符复制到目标字符串中的相应位置,直到遇到源字符串的结束符\0
  • 注意,在目标字符串的末尾添加结束符\0

  显然,复制函数通过将字符串s2中的字符逐个复制到s1中来实现,这就要求s1足够大,否则一旦字符串s2比s1长,该程序无检查复制出界和报告错误的机制,可能导致字符的丢失。可以检查出界和报错机制的算法请读者自己尝试给出。(具体错误检查和报错机制详见8. 代码整合及优化

4. 串插入

  在指定位置后面插入一个字符串:在母串中的指定位置插入一个子串,改变母串的内容。

void stringInsert(char* str, const char* insertStr, int pos) {int strLen = stringLength(str);int insertStrLen = stringLength(insertStr);// 移动字符,为插入字符串腾出空间for (int i = strLen; i >= pos; i--) {str[i + insertStrLen] = str[i];}// 插入字符串for (int i = 0; i < insertStrLen; i++) {str[pos + i] = insertStr[i];}
}
  • 接受三个参数:str是要插入字符串的目标字符串,insertStr是要插入的字符串,pos是插入位置的索引。
  • 函数首先移动目标字符串中的字符,为插入字符串腾出空间。然后,将插入字符串的字符逐个复制到目标字符串的指定位置。

5. 串删除

  删除一个子串:母串中删除指定位置的子串,改变母串的内容。

void stringDelete(char* str, int pos, int length) {int strLen = stringLength(str);// 移动字符,删除指定位置的子串for (int i = pos + length; i <= strLen; i++) {str[i - length] = str[i];}
}
  • 接受三个参数:str是要删除子串的目标字符串,pos是要删除的子串的起始位置,length是要删除的子串的长度。
  • 通过移动目标字符串中的字符,将指定位置后的字符覆盖掉待删除的子串,从而实现删除操作。

6. 串拼接

  将一个串连接到另一个串的尾部:将两个串的内容连接起来,形成一个新的串。

void stringConcat(char* str1, const char* str2) {int str1Len = stringLength(str1);int str2Len = stringLength(str2);// 将str2拼接到str1的尾部for (int i = 0; i < str2Len; i++) {str1[str1Len + i] = str2[i];}str1[str1Len + str2Len] = '\0';
}
  • 接受两个参数:str1是目标字符串,str2是要拼接的字符串。
  • 通过遍历第二个字符串中的字符,并将每个字符依次追加到第一个字符串的末尾。
  • 最后,在目标字符串的末尾添加结束符\0

7.主函数

int main() {char S[100] = "Qomolangma";char target[] = "lang";char insertStr[] = " H ";int pos = 4;int length = 3;printf("String S: %s\n", S);printf("String Length: %d\n", stringLength(S));int searchResult = stringSearch(S, target);if (searchResult != -1) {printf("Target found at position: %d\n", searchResult);} else {printf("Target not found\n");}char copyStr[100];stringCopy(copyStr, S);printf("Copied String: %s\n", copyStr);stringInsert(S, insertStr, pos);printf("String after insertion: %s\n", S);stringDelete(S, pos, length);printf("String after deletion: %s\n", S);stringConcat(S, "H");printf("String after concatenation: %s\n", S);return 0;
}

在这里插入图片描述

8. 代码整合及优化

#include <stdio.h>
#include <stdbool.h>int stringLength(const char* str) {int length = 0;while (str[length] != '\0') {length++;}return length;
}int stringSearch(const char* str, const char* target) {int strLength = stringLength(str);int targetLength = stringLength(target);if (targetLength > strLength) {// 目标字符串比源字符串长,无法找到printf("Error: Target string is longer than the source string.\n");return -1;}for (int i = 0; i <= strLength - targetLength; i++) {bool match = true;for (int j = 0; j < targetLength; j++) {if (str[i + j] != target[j]) {match = false;break;}}if (match) {return i;}}// 未找到目标字符串printf("Error: Target string not found in the source string.\n");return -1;
}bool stringCopy(char* dest, const char* src, int destSize) {int i = 0;while (src[i] != '\0') {if (i >= destSize - 1) {// 目标字符串空间不足,报错并返回printf("Error: Destination string is too small to hold the source string.\n");return false;}dest[i] = src[i];i++;}dest[i] = '\0';return true;
}bool stringInsert(char* str, const char* insertStr, int pos, int maxSize) {int strLength = stringLength(str);int insertStrLength = stringLength(insertStr);if (pos < 0 || pos > strLength) {// 插入位置越界printf("Error: Invalid insertion position.\n");return false;}if (strLength + insertStrLength >= maxSize) {// 目标字符串空间不足,报错并返回printf("Error: Destination string is too small to hold the inserted string.\n");return false;}// 向后移动字符,为插入字符串腾出空间for (int i = strLength; i >= pos; i--) {str[i + insertStrLength] = str[i];}// 插入字符串for (int i = 0; i < insertStrLength; i++) {str[pos + i] = insertStr[i];}return true;
}bool stringDelete(char* str, int pos, int length) {int strLength = stringLength(str);if (pos < 0 || pos >= strLength) {// 删除位置越界printf("Error: Invalid deletion position.\n");return false;}if (pos + length > strLength) {// 删除长度超出字符串范围printf("Error: Deletion length exceeds the length of the string.\n");return false;}// 向前移动字符,覆盖待删除的子串for (int i = pos; i < strLength - length; i++) {str[i] = str[i + length];}str[strLength - length] = '\0';return true;
}bool stringConcat(char* str1, const char* str2, int maxSize) {int str1Length = stringLength(str1);int str2Length = stringLength(str2);if (str1Length + str2Length >= maxSize) {// 目标字符串空间不足,报错并返回printf("Error: Destination string is too small to hold the concatenated string.\n");return false;}// 追加字符串for (int i = 0; i < str2Length; i++) {str1[str1Length + i] = str2[i];}str1[str1Length + str2Length] = '\0';return true;
}int main() {char S[20] = "Qomolangma";const char target[5] = "lang";char copyStr[10];const char insertStr[5] = " H ";int pos = 4;int maxSize = 20;int length = 3;int searchIndex = stringSearch(S, target);if (searchIndex != -1) {printf("Target string found at index: %d\n", searchIndex);}bool copied = stringCopy(copyStr, S, sizeof(copyStr));if (copied) {printf("Copied string: %s\n", copyStr);}bool inserted = stringInsert(S, insertStr, pos, maxSize);if (inserted) {printf("After insertion: %s\n", S);}bool deleted = stringDelete(S, pos, stringLength(insertStr));if (deleted) {printf("After deletion: %s\n", S);}bool concatenated = stringConcat(S, "H", maxSize);if (concatenated) {printf("After concatenation: %s\n", S);}return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/155340.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php收发邮件的多种方法?

1、添加扩展&#xff1a; # 第一种&#xff1a; composer require php-imap/php-imap # 第二种&#xff1a; composer require phpmailer/phpmailer2、这里采用第二种方式&#xff1a; <?php declare(strict_types1);namespace App\Controller\v1\email;use App\Controll…

【linux】文件系统+软硬连接+动静态库

文件系统软硬连接动静态库 1.理解文件系统1.1磁盘的物理结构1.2磁盘的存储结构1.3磁盘的逻辑结构1.4文件系统 2.软硬链接2.1什么是软硬链接2.2软硬链接的作用 3.动静态库3.1什么是库3.1静态库和静态链接3.2动态库和动态链接3.2.1通过环境变量找到动态库路径3.2.2把动态库拷贝到…

关于FreeTypeFont‘ object has no attribute ‘getsize‘问题的解决方案

引言 这个问题是在训练yolov5_obb项目遇到的&#xff0c;大概率又是环境问题。如下图&#xff1a; 解决方法 出现这个问题是Pillow版本太高了&#xff0c;下载低版本的&#xff1a; pip install Pillow9.5 OK&#xff01;

使用pycharm远程调试

使用pycharm 专业版&#xff0c; 在设置解释器中&#xff0c;具备ssh 解释器功能&#xff1b; 一般在本地无法调试远程端代码&#xff0c;机械性的scp传输文件十分影响工作效率&#xff0c;PyCharm的Pro支持远程Run&#xff0c;Debug&#xff0c;等可视化的功能。 操作系统&…

【c++|opencv】二、灰度变换和空间滤波---3.均值滤波

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 均值滤波 1. 均值滤波 #include <iostream> #include <opencv2/opencv.hpp> #include"Salt.h"using namespace cv; using names…

Thread

Thread 线程启动线程第一种创建线程线程的第二种创建方式使用匿名内部类完成线程的两种创建 Thread API线程的优先级线程提供的静态方法守护线程用户线程和守护线程的区别体现在进程结束时 多线并发安全问题同步块 线程 启动线程 启动线程:调用线程的start方法,而不是直接调用…

SQL注入思路扩展

目录 一、资产搜集 二、开始sql注入常规流程 三、sqlmap验证 总结&#xff1a;测试sql注入的时候不要只局限于明文传输&#xff0c;也要注意编码或者加密后的值。 还没看够&#xff1f;欢迎关注&#xff0c;带你走进黑客世界&#xff0c;下面也有免费的靶场视频 一、资产搜…

C++中vec.size()-1的坑

问题描述&#xff1a;如下代码&#xff0c; #include <iostream> #include <vector>using namespace std;int main() {vector<int> vec {};for (int i 0; i < vec.size() - 1; i) {cout << "i " << i << ", vec[i] …

Vue Router使用VueUse更改标签页名称的工具函数

进入正题 安装 npm i vueuse/core or pnpm i vueuse/core or yarn add vueuse/corerouter/helper.js import { useTitle } from vueuse/coreexport const usePageTitle (to) > {const projectTitle import.meta.env.VITE_APP_TITLE // 将可变名抽出到 .env 内配置cons…

建筑建材物料展示预约小程序的作用

建材物料在工程和家庭中的应用度非常高&#xff0c;涵盖服务与产品&#xff0c;如墙面翻新、刷墙、墙纸等&#xff0c;所谓专业事专业人做&#xff0c;因此建筑建材服务商家需要不断拓展客户进行产品/服务的销售。 而在市场拓展方面&#xff0c;由于当今主流需求者年轻化&…

OpenHarmony docker环境搭建所见的问题和解决

【摘要】OpenHarmony docker环境搭建需要一台安装Ubuntu的虚拟机&#xff0c;并且虚拟机中需要有VScode。 整个搭建流程请参考这篇博客&#xff1a;OpenHarmony docker环境搭建-云社区-华为云 (huaweicloud.com) 上篇博主是用Ubuntu的服务器进行环境搭建的&#xff0c;在使用VS…

通过shiro框架记录用户登录,登出及浏览器关闭日志

背景&#xff1a; 公司项目之前使用websocket记录用户登录登出日志及浏览器关闭记录用户登出日志&#xff0c;测试发现仍然存在问题&#xff0c; 问题一&#xff1a;当浏览器每次刷新时websocket其实是会断开重新连接的&#xff0c;因此刷新一下就触发记录登出的日志&#xff0…