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

news2024/11/19 9:27:21

文章目录

  • 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.coloradmin.cn/o/1155236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于RFID技术的优化医药供应链管理解决方案

一、社会背景和挑战 随着全球假药问题的严重性日益凸显&#xff0c;医疗产品的追溯和管理变得越来越重要。据世界卫生组织报告&#xff0c;全球假药比例已超过10%&#xff0c;而中国每年至少有20万人死于假药和不当用药。在国际上&#xff0c;医疗产品的追溯体系已成为监管机构…

总线类设备驱动——IIC

目录 一、本章目标 二、IIC设备驱动 2.1 I2C协议简介 2.2 LinuxI2C驱动 2.3 I2C 设备驱动实例 一、本章目标 一条总线可以将多个设备连接在一起&#xff0c;提高了系统的可扩展性能。这个互联的系统通常由三部分组成:总线控制器、物理总线(一组信号线) 和设备。总线控制器…

视频监控平台EasyCVR分组接口出现“pending”报错,该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台可拓展性强、视频能力灵活&#xff0c;能对外分发RTMP、RTSP、…

直线导轨的误差匹配度如何?

直线导轨的误差匹配度是评估导轨之间配合精度的重要指标&#xff0c;导轨之间的配合精度越高&#xff0c;误差匹配度就会越好&#xff0c;反之则越差。 在直线导轨的生产和加工过程中&#xff0c;每个导轨都会产生一定误差&#xff0c;例如平行误差、垂直误差、轨面平整度、滑块…

什么是跨域问题?如何解决?

跨域问题指的是不同站点之间,使用 ajax 无法相互调用的问题。跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。但这个保护机制也带来了新的问题,它的问题是给不同站点之间的正常调用,也带来的阻碍,那怎么解决这个问题呢?接下来…

2023软件测试八股文最新版(含答案+文档)

一、Web 自动化测试 1、Selenium 中 hidden 或者是 display &#xff1d; none 的元素是否可以定位到&#xff1f; 不能&#xff0c;可以写 JavaScript 将标签中的 hidden 先改为 0&#xff0c;再定位元素 2、Selenium 中如何保证操作元素的成功率&#xff1f;也就是说如何保…

连续分析:提高应用效率和成本效益的关键

作者&#xff1a;John Knoepfle 最近&#xff0c;Elastic Universal Profiling 已经正式发布。 它是我们可观察性解决方案的一部分&#xff0c;允许用户在生产环境中进行整个系统的连续分析。 如果你不熟悉连续分析&#xff0c;你可能想知道通用分析是什么以及为什么你应该关心…

【1++的Linux】之信号(一)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;关于信号二&#xff0c;深剖信号的产生1. 键盘组合建产生信号2.核心转储3. 系统调用接口产生信号4. 由软件条件产生信号5. 硬件异常产生信号 一&#xff0c;…

TSINGSEE青犀AI视频识别技术+危化安全生产智慧监管方案

一、背景分析 石油与化学工业生产过程复杂多样&#xff0c;涉及的物料易燃易爆、有毒有害&#xff0c;生产条件多高温高压、低温负压&#xff0c;现场危险化学品存储量大、危险源集中&#xff0c;重特大安全事故多发。打造基于工业互联网的安全生产新型能力&#xff0c;提高危…

storage数据存储问题,不能存undefined

这篇文章分享一下自己使用sessionStorage遇到的一个小问题&#xff0c;以后遇到要避坑。 需求是easyui表格的单元格编辑&#xff0c;点击保存的时候会结束当前行的编辑&#xff0c;然后修改editingId&#xff08;当前编辑行记录的ID&#xff09;。 待解决问题 如图&#xff0c…

操作系统的内存管理之虚拟空间

操作系统的内存管理&#xff0c;主要分为三个方面。 第一&#xff0c;物理内存的管理&#xff0c;相当于会议室管理员管理会议室。 第二&#xff0c;虚拟地址的管理&#xff0c;也即在项目组的视角&#xff0c;会议室的虚拟地址应该如何组织。 第三&#xff0c;虚拟地址和物…

vcomp140.dll丢失是什么意思,vcomp140.dll丢失这几个方法都能修复好

vcomp140.dll是什么&#xff1f; vcomp140.dll是一个动态链接库&#xff08;Dynamic Link Library&#xff09;&#xff0c;它主要用于支持Microsoft Visual C 2015编程语言的运行。这个文件包含了编译器相关的函数和资源&#xff0c;对于使用Visual C 2015开发的程序和游戏来…

Android图形系统之HWComposer、ComposerHal、ComposerImpl、Composer、Hwc2::Composer实例总结(十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

一款Nacos漏洞自动化工具

1、参考GitHub - charonlight/NacosExploitGUI: Nacos漏洞综合利用GUI工具&#xff0c;集成了默认口令漏洞、SQL注入漏洞、身份认证绕过漏洞、反序列化漏洞的检测及其利用 0x01 前言 ​ 本工具已经集成Nacos常见漏洞的检测及其利用&#xff0c;工具为GUI版本&#xff0c;简单…

[迁移学习]DA-DETR基于信息融合的自适应检测模型

原文标题为&#xff1a;DA-DETR: Domain Adaptive Detection Transformer with Information Fusion&#xff1b;发表于CVPR2023 一、概述 本文所描述的模型基于DETR&#xff0c;DETR网络是一种基于Transformer的目标检测网络&#xff0c;详细原理可以参见往期文章&#xff1a;…

k8s 资源预留

KUBERNETES资源管理之–资源预留 Kubernetes 的节点可以按照 Capacity 调度。node节点本身除了运行不少驱动 OS 和 Kubernetes 的系统守护进程&#xff0c;默认情况下 pod 能够使用节点全部可用容量&#xff0c; 除非为这些系统守护进程留出资源&#xff0c;否则它们将与 pod 争…

创造产业链协同优势后,凌雄科技在DaaS行业转动成长飞轮

企业服务领域&#xff0c;一直存在一种共识&#xff1a;做好很难&#xff0c;但一旦服务模式跑通了&#xff0c;得到了市场的认可&#xff0c;要滚起雪球就会事半功倍。 重资产、重运营的DaaS&#xff08;设备及服务&#xff09;赛道&#xff0c;是个非常典型的细分领域。在这…

泡泡玛特首度跨界超跑品牌兰博基尼汽车,以潮流基因探索时空边界

近期&#xff0c;泡泡玛特携手兰博基尼汽车&#xff0c;于上海国际赛车场进行了一场玩味十足的赛道体验。25位兰博基尼车主&#xff0c;及多位汽车领域知名媒体人、kol到场参与。兰博基尼跑车巡游、专业车手驾驶的兰博基尼涂装赛车试乘、MEGA SPACE MOLLY 1000%/400%兰博基尼汽…

深入理解计算机系统CS213学习笔记

Lecture 01 1. 计算机表示数字 int 整数运算可能会出现错误&#xff0c;超过32位时会出现溢出。 float 浮点数不适用结合律&#xff0c;因为浮点数表示的精度有限。 根其原因&#xff0c;是用有限的位数表示无限的数字空间。 2.利用分层的存储系统&#xff0c;使程序运行更…

第三届字节跳动奖学金官宣开奖,13位优秀科研学子每人获10万奖学金

最近&#xff0c;第三届字节跳动奖学金正式公布了获奖者名单。 经过字节跳动技术专家团队层层评审&#xff0c;本届字节跳动奖学金共有来自北京大学、复旦大学、清华大学、上海交通大学、香港科技大学、浙江大学、中国科学技术大学&#xff08;按拼音首字母排序&#xff09;的 …