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

C语言进阶--字符串+内存函数

求字符串长度strlen()

长度不受限制的字符串函数strcpy()、strcat()、strcmp()

长度受限制的字符串函数strncpy()、strncat()、strncmp()

字符串查找函数strstr()、strtok()

错误信息报告strerror()

字符操作

内存操作函数memcpy()、memmove()、memset()、mencmp()

strlen()

size_t strlen(const char* str);

字符串将’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包括’\0’).

参数指向的字符串必须要以’\0’结束。

注意函数的返回值是size_t,是无符号的(易错)。

在这里插入图片描述

#include <stdio.h>
#include <string.h>int main()
{char arr[] = {"abcdef"}; //abcdef\0int len = strlen(arr);printf("%d\n", len); //6return 0;
}
#include <stdio.h>
#include <string.h>int main()
{char arr[] = {'b', 'i', 't'}; //[][][][][][][b][i][t][][][][]int len = strlen(arr); printf("%d\n", len); //随机值return 0;
}
#include <stdio.h>
#include <string.h>int main()
{//if (strlen("abc") - strlen("abcdef") > 0)  //size_t。error,>if (strlen("abc") > strlen("abcdef")) //<={printf(">\n");}else{printf("<=\n"); }return 0;
}

模拟实现strlen

1、计算器方法

2、指针-指针的方法

3、递归的方法

#include <assert.h>
#include <stdio.h>size_t my_strlen(const char* str)
{size_t count = 0;assert(str);while (*str != '\0'){count++;str++;}return count;
}
int main()
{char arr[] = "abcdef";size_t n = my_strlen(arr);printf("%u\n", n); //6return 0;
}

strcpy()

Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).

源字符串必须以’\0’结束。

会将字符串中的’\0’拷贝到目标空间。

目标空间必须足够大,以确保能存放源字符串。

目标空间必须可变。

在这里插入图片描述

#include <stdio.h>
#include <string.h>int main()
{char name[20] = {0};strcpy(name, "zhangsan"); //name = "zhangsan"; //error,name数组名是地址,地址是一个常量值,不能被赋值printf("%s\n", name);  //zhangsanreturn 0;
}
#include <stdio.h>
#include <string.h>int main()
{char name[20] = {0};strcpy(name, "zhang\0san"); printf("%s\n", name);  //zhangreturn 0;
}
#include <stdio.h>
#include <string.h>int main()
{char name[20] = "xxxxxxxxxxx";char arr[] = {'b', 'i', 't'};strcpy(name, arr); //原始数据须有\0printf("%s\n", name);  //zhangreturn 0;
}

在这里插入图片描述

#include <stdio.h>
#include <string.h>int main()
{char name[3] = "";char arr[] = "abcdef";strcpy(name, arr); printf("%s\n", name);  //abcdef,程序崩溃return 0;
}

在这里插入图片描述

#include <string.h>int main()
{char* p = "abcdef";char arr[] = "bit";strcpy(p, arr); //目标区域不可变return 0;
}

在这里插入图片描述

模拟实现strcpy

#include <stdio.h>
char* my_strcpy(char* dest, const char* src)
{assert(dest);assert(src);char* ret = dest;while (*src){*dest++ = *src++;}*dest = *src; // \0return ret; //返回目标空间的地址
}
int main()
{char arr1[] = {"abcdef"};char arr2[] = {0};my_strcpy(arr2, arr1);printf("%s\n", arr2); //abcdefreturn 0;
}
//优化
#include <stdio.h>
char* my_strcpy(char* dest, const char* src)
{assert(dest && src);char* ret = dest;while (*dest++ = *src++){;}return ret; //返回目标空间的起始地址
}
int main()
{char arr1[] = {"abcdef"};char arr2[] = {0};my_strcpy(arr2, arr1);printf("%s\n", arr2); //abcdefreturn 0;
}

strcat():字符串追加

源字符串必须以’\0’结束。

目标空间必须足够大,能容纳下源字符串的内容。

目标空间必须可修改。
在这里插入图片描述

#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "hello ";strcat(arr1, "world");printf("%s\n", arr1); //hello worldreturn 0;
}

模拟实现strcat

#include <stdio.h>
#include <assert.h>char* my_strcat(char* dest, const char* src)
{char* ret = dest;assert(dest && src);//1.找到目标空间的末尾\0while(*dest != '\0'){dest++;}//2.拷贝字符串while (*dest++ = *src++){;}return ret;
}
int main()
{char arr1[20] = "hello ";my_strcat(arr1, "world");printf("%s\n", arr1); //hello worldreturn 0;
}

自己给自己追加?死循环

#include <stdio.h>
#include <assert.h>char* my_strcat(char* dest, const char* src)
{char* ret = dest;assert(dest && src);//1.找到目标空间的末尾\0while(*dest != '\0'){dest++;}//2.拷贝字符串while (*dest++ = *src++){;}return ret;
}
int main()
{char arr1[20] = "hello ";my_strcat(arr1, arr1);printf("%s\n", arr1); return 0;
}

在这里插入图片描述

strcmp()

在这里插入图片描述
在这里插入图片描述

//error,这里是在比较2个地址,而不是比较2个字符串的内容
#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "zhangsan";char arr2[] = "zhangsanfen";//比较两个字符串是否相等if (arr1 == arr2)  //arr1是数组名,数组名是数组首元素的地址;arr2是数组名,数组名是数组首元素的地址{printf("==\n");}elseprintf("!=\n"); //!=return 0;
}

2个字符串比较相等,应该使用strcmp。

#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "zhangsan";char arr2[] = "zhangsanfen";int ret = strcmp(arr1, arr2);if (ret < 0)printf("<\n"); //<else if (ret == 0)printf("==\n");elseprintf(">\n");return 0;
}
#include <stdio.h>
#include <string.h>int main()
{char arr1[] = "abcdef";char arr2[] = "abq";  //一对一对比较ASCII码值int ret = strcmp(arr1, arr2);if (ret < 0)printf("<\n"); //<else if (ret == 0)printf("==\n");elseprintf(">\n");return 0;
}

模拟实现strcmp

#include <stdio.h>
#include <string.h>
#include <assert.h>int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while (*str1 == *str2){if (*str1 == '\0')return 0; //相等str1++;str2++;}if (*str1 > *str2)return 1;elsereturn -1;
}
int main()
{char arr1[] = "abc";char arr2[] = "abc";  int ret = my_strcmp(arr1, arr2);if (ret < 0)printf("<\n"); else if (ret == 0)printf("==\n"); //==elseprintf(">\n");  return 0;
}
//优化
#include <stdio.h>
#include <string.h>
#include <assert.h>int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while (*str1 == *str2){if (*str1 == '\0')return 0; //相等str1++;str2++;}return (*str1 - *str2);
}
int main()
{char arr1[] = "abc";char arr2[] = "abc";  int ret = my_strcmp(arr1, arr2);if (ret < 0)printf("<\n"); else if (ret == 0)printf("==\n"); //==elseprintf(">\n");  return 0;
}

strncpy()

长度受限制的字符串函数strncpy()、strncat()、strncmp()

在这里插入图片描述

#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "abcdef";char arr2[] = "hello bit";strncpy(arr1, arr2, 5);printf("%s\n", arr1); //hellofreturn 0;
}

在这里插入图片描述

strncat()

在这里插入图片描述

在这里插入图片描述

strncmp()

#include <stdio.h>
#include <string.h>int main()
{char arr1[] = "abcdef";char arr2[] = "abcq";int ret = strncmp(arr1, arr2, 4);if (ret == 0)printf("==\n");else if (ret < 0)printf("<\n"); //<elseprintf(">\n");return 0;
}
#include <stdio.h>
#include <string.h>int main()
{char arr1[] = "abcdef";char arr2[] = "abcq";int ret = strncmp(arr1, arr2, 3);printf("%d\n", ret); //0return 0;
}

strstr():查找子串

在这里插入图片描述

#include <stdio.h>
#include <string.h>int main()
{char email[] = "zpw@bitejiuyeke.com";char substr[] = "bitejiuyeke";char* ret = strstr(email, substr);if (ret == NULL)printf("子串不存在\n");elseprintf("%s\n", ret); //bitejiuyeke.comreturn 0;
}

模拟实现strstr

#include <stdio.h>
#include <string.h>
char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* s1 = str1;const char* s2 = str2;const char* p = str1;while (*p){s1 = p;s2 = str2;while (*s1!='\0' && *s2!='\0' && *s1 == *s2){s1++;s2++;}if (*s2 == '\0'){return (char*)p;}p++;}return NULL;
}
int main()
{char email[] = "zpw@bitejiuyeke.com";char substr[] = "bitejiuyeke";char* ret = my_strstr(email, substr);if (ret == NULL)printf("子串不存在\n");elseprintf("%s\n", ret); //bitejiuyeke.comreturn 0;
}

也可使用KMP算法:用来实现一个字符串中查找子字符串的,效率高,但是实现难度大。(B站搜索:大比特博哥)

strtok():切割字符串

在这里插入图片描述

char* strtok(char* str, const char* sep);

sep参数是一个字符串,定义了用作分隔符的字符集合。

第一个参数指定一个字符串,它包含了0个或多个由sep字符串中一个或多个分隔符分割的标记。

strtop函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注意:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)

strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。

strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。

如果字符串中不存在更多的标记,则返回NULL指针。

#include <stdio.h>
#include <string.h>int main()
{const char* sep = "@.";char email[] = "zhangpengwei@bitejiuyeke.com";char cp[30] = {0}; strcpy(cp, email);char* ret = strtok(cp, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);return 0;
}

在这里插入图片描述

//显得啰嗦
#include <stdio.h>
#include <string.h>int main()
{const char* sep = "@.";char email[] = "zhangpengwei@bitejiuyeke.com";char cp[30] = {0}; strcpy(cp, email);char* ret = strtok(cp, sep);if (ret != NULL)printf("%s\n", ret);ret = strtok(NULL, sep);if (ret != NULL)printf("%s\n", ret);ret = strtok(NULL, sep);if (ret != NULL)printf("%s\n", ret);return 0;
}
//for循环修正
#include <stdio.h>
#include <string.h>int main()
{const char* sep = "@.";char email[] = "zhangpengwei@bitejiuyeke.com";char cp[30] = {0}; strcpy(cp, email);char* ret = NULL;for (ret = strtok(cp, sep); ret != NULL; ret = strtok(NULL, sep)){printf("%s\n", ret);}return 0;
}

在这里插入图片描述

strerror():返回错误码,所对应的错误信息

C语言的库函数,在执行失败的时候,都会设置错误码。0 1 2 3 4 5 6 7 8

#include <stdio.h>
#include <string.h>
int main()
{printf("%s\n", strerror(0));printf("%s\n", strerror(1));printf("%s\n", strerror(2));printf("%s\n", strerror(3));printf("%s\n", strerror(4));printf("%s\n", strerror(5));return 0;
}

在这里插入图片描述

//errno:C语言设置的一个错误码存放的全局变量,但需要包含头文件#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}else{//}return 0;
}

在这里插入图片描述
在这里插入图片描述

字符分类函数

函数如果它的参数符合下列条件就返回真
iscntrl任何控制字符
isspace空白字符:空格‘ ’,换页’\f’,换行’\n’,回车’\r’,制表符’\t’或者垂直制表符’\v’
isdigit十进制数字0-9
isxdigit十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F
islower小写字母a-z
isupper大写字母A-Z
isalpha字母a-z或A-Z
isalnum字母或者数字,a-z,A-Z,0-9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符
#include <stdio.h>
#include <ctype.h>int main()
{int a = isspace(' ');printf("%d\n", a); //8return 0;
}
#include <stdio.h>
#include <ctype.h>int main()
{int a = isdigit('0');printf("%d\n", a); //4return 0;
}
#include <stdio.h>
#include <ctype.h>int main()
{int a = isdigit('x');printf("%d\n", a); //0return 0;
}

字符转换函数

tolower()

toupper()

#include <stdio.h>
#include <ctype.h>int main()
{printf("%c\n", tolower('W')); //wreturn 0;
}
#include <stdio.h>
#include <ctype.h>int main()
{printf("%c\n", tolower('@')); //@return 0;
}

memcpy():内存拷贝

strcpy()和strncpy()只能拷贝字符串。如果想要拷贝整型或者其它类型怎么办呢?

在这里插入图片描述

#include <stdio.h>
#include <string.h>
int main()
{int arr1[] = {1,2,3,4,5,6,7};int arr2[10] = {0};memcpy(arr2, arr1, 28);float arr3[5] = {1.0, 2.5, 3.0, 5.0, 6.0};float arr4[10] = {0.0};memcpy(arr4, arr3, 20);return 0;
}

在这里插入图片描述

模拟实现memcpy

#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}
int main()
{int arr1[] = {1,2,3,4,5,6,7};int arr2[10] = {0};my_memcpy(arr2, arr1, 28);return 0;
}

在这里插入图片描述
在这里插入图片描述
memcpy负责拷贝两块独立空间中的数据。

像上述案例,想要重叠内存的拷贝,是怎么做的呢?使用memmove()函数。

memmove()

windows自带的“画图”工具。【英文名:mspaint】

在这里插入图片描述
复习前半段:

#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}void test2()
{int arr1[] = {1,2,3,4,5,6,7,8,9,10};my_memcpy(arr1+2, arr1, 20); //1 2 1 2 3 4 5 8 9 10int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}
}
int main()
{test2();return 0;
}

在这里插入图片描述
并未如结果所示,所以使用memmove():

#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}void test2()
{int arr1[] = {1,2,3,4,5,6,7,8,9,10};//my_memcpy(arr1+2, arr1, 20); //1 2 1 2 3 4 5 8 9 10memmove(arr1+2, arr1, 20);  //memcpy函数是不用来处理重叠的内存之间的数据拷贝;使用memmove函数来实现,重叠内存之前的数据拷贝int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}
}
int main()
{test2();return 0;
}

在这里插入图片描述
注意:VS下的内置memcpy()函数是可以实现重叠内存的数据拷贝,可自己尝试,由此看出函数也很卷啊!

模拟实现memmove()

#include <stdio.h>
#include <string.h>
#include <assert.h>void my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;if (dest < src){//前->后while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{//后->前while (num--){*((char*)dest+num) = *((char*)src+num);}}return ret;
}
void test3()
{int arr1[] = {1,2,3,4,5,6,7,8,9,10}; my_memmove(arr1+2, arr1, 20);  //my_memmove(arr1, arr1 + 2, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}
}
int main()
{test3();return 0;
}

有时候需要从前往后处理数据,有时候又需要从后往前处理数据。

memcmp()

在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <string.h>int main()
{int arr1[] = {1,2,3,4,5}; //01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00int arr2[] = {1,3,2};     //01 00 00 00 03 00 00 00 02 00 00 00int ret = memcmp(arr1, arr2, 12);printf("%d\n", ret); //-1return 0;
}

memset():内存设置

在这里插入图片描述

#include <stdio.h>
#include <string.h>
int main()
{char arr[] = "hello bit";memset(arr, 'x', 5);printf("%s\n", arr); //xxxxx bitreturn 0;
}
#include <stdio.h>
#include <string.h>
int main()
{char arr[] = "hello bit";memset(arr+6, 'x', 3);printf("%s\n", arr); //hello xxxreturn 0;
}
//将arr初始化为全1,答案并非我们所想
#include <stdio.h>
#include <string.h>
int main()
{int arr[10] = {0};memset(arr, 1, 40);int i = 0;for (i = 0; i < 10; i++){printf("%d\n", arr[i]);}return 0;
}

在这里插入图片描述
在这里插入图片描述

总结

今天就暂且更新至此吧,期待下周再会。如有错误还请不吝赐教。希望对您学习有所帮助,翻页前留下你的支持,以防下次失踪了嗷。

作者更新不易,免费关注别手软。

相关文章:

  • CSS篇-1
  • 三套知识系统的实践比较:Notion、Confluence 与 Gitee Wiki
  • 深入详解编译与链接:翻译环境和运行环境,翻译环境:预编译+编译+汇编+链接,运行环境
  • 乾元通渠道商中标青海省自然灾害应急能力提升工程基层防灾项目
  • 微深节能 码头装卸船机定位与控制系统 格雷母线
  • 国内高频混压PCB厂家有哪些?
  • 员工管理系统 (Python实现)
  • 【MySQL】C语言连接
  • SQL正则表达式总结
  • 如何使用 Redis 快速实现排行榜?
  • Unity 中 Update、FixedUpdate 和 LateUpdate 的区别及使用场景
  • MySQL字段为什么要求定义为not null ?
  • Vue项目打包常见问题
  • 怎么选择合适的高防IP
  • 服务器数据恢复—EMC存储raid5阵列故障导致上层应用崩了的数据恢复案例
  • 【Kubernetes】集群内部 Pod 与 Pod 如何通信,CNI是什么?Flannel vs Calico
  • 如何通过数据分析优化项目决策
  • T5和GPT哪个更强大
  • DexGarmentLab 论文翻译
  • DeepSeek R1开源模型的技术突破与AI产业格局的重构
  • 搜索网站做推广/seo站内优化最主要的是什么
  • 济南网站建设模板/中国软文网官网
  • 广州网站建设出名 乐云践新/网站推广计划
  • 17网站一起做网店优势与劣势/小程序制作费用一览表
  • 地方旅游网站建设必要性/网络营销策划书1500字
  • 手机做任务赚钱的网站/ping站长工具