首页 > 编程语言 >C++学习笔记(28)

C++学习笔记(28)

时间:2024-09-18 23:52:07浏览次数:3  
标签:const str1 28 笔记 char C++ str 字符串 return

十四、实现 strchr()和 strrchr()函数
示例:
#define _CRT_SECURE_NO_WARNINGS // 使用 C 风格字符串操作的函数需要定义这个宏
#include <iostream>
using namespace std;
// 返回在字符串 s 中第一次出现 c 的位置,如果找不到,返回 0。
// babcddefae a
const char* mystrchr(const char* s, int c)
{
char* p = (char *)s; // 用于遍历字符串 s 的指针。
while (*p) // 遍历字符串,如果找到了,循环中会 return。
{
if (*p==c) return p;// 如果找到了,返回当前位置。
p++; // 如果没有找到,继续找。
}
return 0; // 返回空地址。
}
// 返回在字符串 s 中最后一次出现 c 的位置,如果找不到,返回 0。
// 注意:不要从字符串的最后一个字符往前找,因为用 strlen()获取字符串长度时,需要遍历一次
字符串,效率更低。
// babcddefae a strlen(s)
const char* mystrrchr(const char* s, const int c)
{
char* p = (char*)s; // 用于遍历字符串 s 的指针。
char* p1 = 0; // 如果没找到,p1 为 0,如果已经找到,p1 为最后一次出现 c 的
位置。
while (*p) // 遍历字符串,不管有没有找到,都要遍历整个字符串。
{
if (*p == c) p1=p; // 如果找到了,把 p1 更新为当前位置。
p++;
}
return p1; // 返回 p1。
}
int main()
{
const char* p1 = mystrchr("abccdacb", 'a');
if (p1!=0) cout << p1 << endl; // 显示 abccdacb
const char* p2 = mystrchr("abccdacb", 'e');
if (p2 != 0) cout << p2 << endl; // 什么也没有显示。
const char* p3 = mystrrchr("abccdacb", 'a');
if (p3 != 0) cout << p3 << endl; // 显示 acb
const char* p4 = mystrrchr("abccdacb", 'e');
if (p4 != 0) cout << p4 << endl; // 什么也没有显示。
}
十五、实现 strcmp()和 strncmp()函数
示例:
#define _CRT_SECURE_NO_WARNINGS // 使用 C 风格字符串操作的函数需要定义这个宏
#include <iostream>
using namespace std;
// 功能:比较 str1 和 str2 的大小。
// 返回值:相等返回 0,str1 大于 str2 返回 1,str1 小于 str2 返回 - 1;
int mystrcmp(const char* str1, const char* str2)
{
size_t pos = 0; // 数组下标。
// abc0 ab0
while (true)
{
if (str1[pos] > str2[pos]) return 1; // str1>str2
if (str1[pos] < str2[pos]) return -1; // str1<str2
if (str1[pos] == 0 && str2[pos] == 0) return 0; // 两个字符串相等。
pos++; // 如果没有分出大小,继续比较下一个字符。
}
}
// 功能:比较 str1 和 str2 前 n 个字符的大小。
// 返回值:相等返回 0,str1 大于 str2 返回 1,str1 小于 str2 返回 - 1;
int mystrncmp(const char* str1, const char* str2, const size_t n)
{
size_t pos = 0; // 数组下标。
for (size_t pos=0; pos<n; pos++)
{
if (str1[pos] > str2[pos]) return 1; // str1>str2
if (str1[pos] < str2[pos]) return -1; // str1<str2
if (str1[pos] == 0 && str2[pos] == 0) return 0; // 两个字符串相等。
}
return 0; // 如果比较了 n 次还没有分出大小,返回 0。
}
// 两个字符串比较的方法是比较字符的 ASCII 码的大小
// 从两个字符串的第一个字符开始,如果分不出大小
// 就比较第二个字符,如果全部的字符都分不出大小,就返回 0,表示两个字符串相等。
int main()
{
cout << strcmp("abcde", "abcdef") << endl;
cout << mystrcmp("abcde", "abcdef") << endl;
}
十六、实现 strstr()函数
char *strstr(const char* str,const char* substr);
返回子串 substr 在目标串 str 中第一次出现的位置,如果找不到,返回 0。
BF 算法,即暴力(Brute Force)算法。
KMP(看毛片)算法是一种改进的字符串匹配算法,由 D.E.Knuth,J.H.Morris 和 V.R.Pratt 提出(简
称 KMP 算法)。
示例:
#define _CRT_SECURE_NO_WARNINGS // 使用 C 风格字符串操作的函数需要定义这个宏
#include <iostream>
using namespace std;
// 返回子串 substr 在目标串 str 中第一次出现的位置,如果找不到,返回 0。
const char* mystrstr(const char *str,const char *substr)
{
size_t ii = 0, jj = 0; // 目标串和子串的数组下标,都从 0 开始。
size_t len = strlen(str), slen = strlen(substr); // 目标串和子串的长度。
while ( (ii < len) && (jj < slen) ) // 如果 ii==len,表示目标串已结束;如果 jj==slen,表
示已成功匹配。
{
if (str[ii] == substr[jj]) { // 如果目标串和子串数组下标指向的字符是相等的。
ii++; jj++; // 继续比较后面的字符。
}
else { // 如果目标串和子串数组下标指向的字符不相等,这次白
干了。
ii = ii - jj; // 目标串数组下标回退 jj。
jj = 0; // 子串数组下标回退到 0,准备重来。
ii++; // 目标串往右移一个字符,准备重来。
}
}
if (jj == slen) return str+(ii-jj); // 如果循环终止时,jj==slen,表示查找成功了。
return 0; // 查找失败。
}
int main()
{
const char* p1 = mystrstr("aabcde", "abc");
if (p1) cout << p1 << endl; // 显示 abcde。
const char* p2 = mystrstr("aabcde", "ba");
if (p2) cout << p2 << endl; // 什么也没有显示。
}
十七、删除字符串右边指定的字符
函数的原型:
void deleterchr(char *str,const const int cc = ' '); "abc0yy" "abc"
"西施 " "西施" 方法二:遍历 1 次字符串,写 1 次内存。
方法一:遍历 1-2 次字符串(调用 strlen()函数算一次),写 n 次内存。
示例:
#define _CRT_SECURE_NO_WARNINGS // 使用 C 风格字符串操作的函数需要定义这个宏
#include <iostream>
using namespace std;
// 删除字符串左边指定的字符。
void deleterchr(char* str, const int cc = ' ')
{
if (str == 0) return; // 如果传进来的是空地址,直接返回,防止程序崩溃。
char* p = str; // 指向字符串的首地址。
char* piscc = 0; // 右边全是字符 cc 的第一个位置。
while (*p != 0) // 遍历字符串。
{
if (*p == cc && piscc == 0) piscc = p; // 记下字符 cc 的第一个位置。
if (*p != cc) piscc = 0; // 只要当前字符不是 cc,清空 piscc。
p++;
}
if (piscc != 0) *piscc = 0;
}
int main()
{
char str[51];
strcpy(str, "abcdee aaaaa aa");
deleterchr(str,'a');
cout << str << "=" << endl;
}
十八、删除字符串左边指定的字符
函数的原型:
void deletelchr(char* str, const int cc = ' ');
// yyyabycd abycd
示例:
#define _CRT_SECURE_NO_WARNINGS // 使用 C 风格字符串操作的函数需要定义这个宏
#include <iostream>
using namespace std;
// 删除字符串左边指定的字符。
void deletelchr(char* str, const int cc = ' ')
{
if (str == 0) return; // 如果传进来的是空地址,直接返回,防止程序崩溃。
char* p = str; // 指向字符串的首地址。
while (*p == cc) // 遍历字符串,p 将指向左边第一个不是 cc 的字符。
p++;
memmove(str, p, strlen(str) - (p - str)+1); // 把结尾标志 0 也拷过来。
}
// memcpy()没有考虑内存重叠的情况,如果内存有重叠,其行为是不确定的。
// memmove()函数在 memcpy()函数的基础上加入了对内存重叠拷贝的处理,保证其正确性。
// 如果能确定拷贝内存没有重叠,memcpy()比 memmove()更高效,如果有重叠,只能 memmove()。
int main()
{
char str[51];
strcpy(str, " aaaaabbaaaa bcdee aaaaa aa");
deletelchr(str);
cout << "=" << str << "=" << endl;
}
十九、删除字符串中间的字符串
函数的原型:
void deletestr(char* str, const char* substr);
// aaxyzaa0 aaaa0
// aaxyxyzzaa aaxyzaa aaaa
示例:
#define _CRT_SECURE_NO_WARNINGS // 使用 C 风格字符串操作的函数需要定义这个宏
#include <iostream>
using namespace std;
// aaxyzaa aaaa
// aaxyxyzzaa aaxyzaa aaaa
// 删除字符串中间的字符串。
void deletestr(char* str, const char* substr)
{
if (str == 0 || substr == 0) return; // 如果传进来的是空地址,直接返回,防止程序崩溃。
size_t slen = strlen(substr); // 子串的长度。
if (slen == 0) return; // 如果子串的内容为空,直接返回,否则会死循环。
while (true) {
char* p = strstr(str, substr); // 在目标串中查找子串。
if (p == 0) return; // 如果目标串中没有子串,函数返回。
size_t len = strlen(str); // 获取目标串的长度。
// aaxyzaa0 aaaa0
// p
// p+slen
memmove(p, p + slen, len - (p - str) - slen + 1); // 从目标串中删除子串。
// deletestr(str, substr); // 递归调用自己。
}
}
// memcpy()没有考虑内存重叠的情况,如果内存有重叠,其行为是不确定的。
// memmove()函数在 memcpy()函数的基础上加入了对内存重叠拷贝的处理,保证其正确性。
// 如果能确定拷贝内存没有重叠,memcpy()比 memmove()更高效,如果有重叠,只能 memmove()。
int main()
{
char str[51];
strcpy(str, "aaxyxyzzaa");
deletestr(str, "xyz");
cout << "=" << str << "=" << endl;
}
 

标签:const,str1,28,笔记,char,C++,str,字符串,return
From: https://blog.csdn.net/qq_60098634/article/details/142314600

相关文章

  • java基础 -IO流笔记
    610,文件的基础知识文件流 输入流和输出流都是相对java程序内存而言 611,创建文件 在D盘下创建文件。packagecom.hspedu.file;importorg.junit.jupiter.api.Test;importjava.io.File;importjava.io.IOException;//演示创建文件publicclassFileCreate{......
  • C++学习笔记(一、预备知识)
    C++简介C++融合了三种不同的编程方式:-C语言代表的过程性语言-C++在C语言基础上添加的类代表的面向对象语言-C++模板支持的泛型编程。值得一提的是,不要把C语言与C++混为一谈,他们可以说是两个不同的语言。C++简史2.1C语言20世纪70年代,贝尔实验室的DennisRi......
  • C/C++语言基础--C++面向对象、类、对象概念讲解
    本专栏目的更新C/C++的基础语法,包括C++的一些新特性前言今天更新的比较晚了,主要一直用是谷歌Colab训练模型,访问国内csdn反而不好使了,请大家见谅;C++是面向对象的语言,本文将介绍什么是面向对象、什么是类、什么是对象、类和对象的关系是什么?欢迎大家点赞+收藏+关注;C语......
  • C++基于select和epoll的TCP服务器
    select版本服务器#include<arpa/inet.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#include<unistd.h>#include<sys/socket.h>#include<string>#include<pthread.h>#include<sys/select.h>......
  • 828 华为云征文|华为 Flexus 云服务器部署 RustDesk Server,打造自己的远程桌面服务器
    ......
  • 828华为云征文|华为Flexus云服务器打造《我的世界》游戏服务器
    一、引言在游戏的世界里,《我的世界》以其极高的自由度和创造性吸引了无数玩家。拥有一个专属的《我的世界》游戏服务器,可以让玩家和朋友们尽情享受定制化的游戏体验。2024年9月14日,我将向大家分享如何利用华为Flexus云服务器打造属于自己的《我的世界》游戏服务器,开启畅玩......
  • C++入门基础知识75(高级)——【关于C++ Web 编程】
    成长路上不孤单......
  • java代码-编译-打包-执行_云原生时代笔记总结
    楔子:可能201几年开发的时候,有个ide,加上打包插件,就可以开发了,测试的时候war包扔到服务器容器里就可以跑起来了。(而且没有做过批处理的小伙伴对jar包执行可能不甚熟悉,只见过web容器的目录结构和lib中的jar包。)但是2015年之后应该是全面进入,云原生时代。大量操作需要linux命令行......
  • c++运算符
    #include<iostream>//运算符usingnamespacestd;intmain(){inta=9;intb=6;cout<<"这是加法:"<<a+b<<endl;cout<<"这是减法:"<<a-b<<endl;cout<<"这是乘法:"<<......
  • 读书笔记(14)《敢问路在何方》
    序言1982年的春节,电视系列片《西游记》开始动工。那时距离现在,已经过去了整整三十年!八十年代,是拼搏的年代,是奋斗的年代,是奉献的年代!拍摄《西游记》系列片,用去了六年的时间。这段时间,我和全剧组的同志们一起,跋山涉水,茹苦含辛,往返于祖国的北国南疆,其中甘苦不胜枚举。《西游记》剧组......