目录

  • 1、strlen
    • strlen的模拟实现
  • 2、strcpy
    • strcpy模拟实现
  • 3、strcat - 字符串追加
    • 模拟实现strcat
  • 4、strcmp - 比较字符串
    • 模拟实现stcmp
  • 5、长度(不)受限制的字符串函数
    • strncp
    • strncat
    • strncmp
  • 6、strstr - 字符串查找
    • 模拟实现strstr
  • 7、strtok - 分割字符串
  • 8、内存拷贝函数 - mem..
    • 8.1、memcpy
      • 模拟实现memcpy
    • 8.2、模拟实现memmove
    • 8.3、memcmp - 比较内存里的数据
    • 8.4、memset - memory set 内存设置
  • 9、strerror - 返回错误码对应的错误信息

1、strlen

size_t strlen ( const char * str );

strlen - size_t 无符号整数

#include <stdio.h>int main()
{char arr[] = "abcdef";// size_t - unsigned int// size_t sz = strlen("abcdef");size_t sz = strlen(arr);printf("%u\n", sz);return 0;
}

例:strlen比较大小

#include <stdio.h>int main()
{if (strlen("abc") - strlen("abcdef") > 0){printf("haha\n");}else{printf("hehe\n");}return 0;
}

如果想打印hehe,强制类型转化为int

int main()
{if ((int)strlen("abc") - (int)strlen("abcdef") > 0){printf("haha\n");}else{printf("hehe\n");}return 0;
}

strlen的模拟实现

1、计数器,
2、指针-指针,
3、递归

链接:

strlen模拟实现

指针-指针方法

递归求

计数器:

int my_strlen(const char * str)
{int count = 0;while(*str){count++;str++;}return count;
}

不能创建临时变量,递归:

int my_strlen(const char * str)
{if(*str == '\0')return 0;elsereturn 1+my_strlen(str+1);
}

指针-指针:

int my_strlen(char *s)
{char *p = s;while(*p != ‘\0’ )p++;return p-s;
}

2、strcpy

char* strcpy(char * destination, const char * source );

源字符串必须以 ‘\0’ 结束。
会将源字符串中的 ‘\0’ 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变

strcpy连 \0一起拷贝

int main()
{char arr1[] = "xxxxxxxxxxxxxxxx";char arr2[] = "hello";// 拷贝arr2中的字符串,包括\0,hello\0strcpy(arr1, arr2);return 0;
}

拷贝到\0,停,如果是arr2,只拷贝hello\0

int main()
{char arr1[] = "xxxxxxxxxxxxxxxx";char arr2[] = "hello\0abc";// 拷贝到\0停止// hello\0return 0;
}

strcpy模拟实现

#include <stdio.h>
#include <assert.h>char* my_strcpy(char* dest, char* src)
{assert(dest && src);char* ret = dest;while (*dest++ = *src++){;}return ret;
}int main()
{char arr1[] = "xxxxxxxxx";char arr2[] = "abc";printf("%s\n", my_strcpy(arr1, arr2));return 0;
}

3、strcat - 字符串追加

char * strcat ( char * destination, const char * source );

例:判断字符串旋转结果,用strcar求

strcat 字符串连接 - 字符串追加
返回的是目标空间的起始地址

int main()
{char arr[20] = "abc";// strcat - 字符串追加strcat(arr, "def");// strncat - 字符串追加自己strncat(arr, arr, 3);char arr1[] = "abcdefabcdef";char arr2[] = "def";// strstr - 查找字符串char* ret = strstr(arr1, arr2); // 查找arr1中有没有arr2,返回arr1中第一次出现的arr2的起始地址if (ret == NULL){printf("找不到\n");}else{printf("找到了:%s\n", ret);}
}

模拟实现strcat

#include <stdio.h>
#include <string.h>
#include <assert.h>char* my_strcat(char* dest, const char* src)
{char* ret = dest;assert(dest && src);// 1. 找到目标字符串末尾\0while (*dest){dest++;}// 2. 追加原字符串直到\0while (*dest++ == *src++){;}return ret;
}int main()
{char arr1[20] = "abc";char arr2[] = { 'd', 'e', 'f', '\0' };//my_strcat(arr1, arr2);//printf("%s\n", arr1); // abcdefprintf("%s\n", my_strcat(arr1, arr2));//abcdefreturn 0;
}

4、strcmp - 比较字符串

int strcmp ( const char * str1, const char * str2 );

比较的是字符串的内容,而不是长度

第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

arr 和 arr1 比较,因为 d<q 返回大于0的数字
arr 和 arr2 比较,返回小于0的数字

#include <stdio.h>
#include <string.h>int main()
{char arr[] = "abcdef";char arr1[] = "abcq";char arr2[] = "abc";strcmp(arr, arr1); // d<q 返回大于0的数字strcmp(arr, arr2); // <0return 0;
}

strcmp返回大于0的数字或小于0的数字,而不是1和-1,所以用1和-1判断是有风险的

#include <stdio.h>
#include <string.h>
#include <assert.h>int main()
{char arr1[] = "abcdef";char arr2[] = "abcq";int ret = strcmp(arr1, arr2);if (ret == 0){printf(">\n");}else if (ret > 0){printf(">\n");}else{printf("<\n");}if (ret == 1) // 有风险{ printf(">\n");}printf("%d", ret);return 0;
}

模拟实现stcmp

#include <stdio.h>
#include <string.h>
#include <assert.h>int my_strcmp(const char* s1, const char* s2)
{assert(s1 && s2);while (*s1 == *s2){if (*s1 == '\0')return 0;s1++;s2++;}return *s1 - *s2;
}int main()
{char arr1[] = "abcdef";char arr2[] = "abcq";int ret = my_strcmp(arr1, arr2);if (ret == 0){printf("=\n");}else if (ret > 0){printf(">\n");}else{printf("<\n");}printf("%d", ret);return 0;
}

5、长度(不)受限制的字符串函数

长度不受限制的字符串函数:strcpy strcat strcmp
不够安全

长度受限制的字符串函数:strncpy strncat strncmp
相对安全

strncp

char * strncpy ( char * destination, const char * source, size_t num );

拷贝n个字符,源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0, 知道n个

int main()
{char arr1[20] = "abcdef";char arr2[] = "xxx";strncpy(arr1, arr2, 6); // 不够用\0凑printf("%s\n", arr1);retu

VS安全版本 strcpy_s 与strncpy相似

strncat

char * strncat ( char * destination, const char * source, size_t num );

拷贝的字符数由自己传入,追加完放\0

int main()
{char arr1[20] = "abc\0xxxxxx";char arr2[] = "defghi";strncat(arr1, arr2, 3); // abcdef\0// 追加完放\0printf("%s\n", arr1);return;
}
int main()
{char arr1[20] = "abc\0xxxxxx";char arr2[] = "def";strncat(arr1, arr2, 6); // 6不起作用 值追加到\0printf("%s\n", arr1);return;
}

strncmp

int strncmp ( const char * str1, const char * str2, size_t num );

一个一个比较,直到到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完

int main()
{char arr1[] = "abcdef";char arr2[] = "abcqw";int ret = strncmp(arr1, arr2, 4); // printf("%d\n", ret);return;
}

6、strstr - 字符串查找

char * strstr ( const char *, const char * );

在一个字符串中查找子字符串
返回arr2在arr1里出现的第一次的位置,找不到返回空指针

#include <stdio.h>
#include <string.h>int main()
{char arr1[] = "i am a student, good student";char arr2[] = "student";char* ret = strstr(arr1, arr2);if (ret == NULL){printf("找不到\n");}else{printf("%s\n", ret); // student, good student}return 0;
}

模拟实现strstr

#include <stdio.h>
#include <string.h>
#include <assert.h>char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);char* s1;char* s2;char* cp = str1;if (*str2 == '\0')return str1;while (*cp){s1 = cp; // 记录起始位置s2 = str2;// while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)while (*s1 && *s2 && *s1 == *s2){s1++;s2++;}if (*s2 == '\0'){return cp;}cp++;}// 找不到return NULL;
}int main()
{char arr1[] = "i am a student, good student";char arr2[] = "student";char* ret = my_strstr(arr1, arr2);if (ret == NULL){printf("找不到\n");}else{printf("%s\n", ret);}return 0;
}

7、strtok - 分割字符串

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

如字符串:192.168.2.121 用.分割
wk@bit.tech 分隔符是@和.

1、sep参数是个字符串,定义了用作分隔符的字符集合
2、第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
3、strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改
变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
4、strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
5、strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
6、如果字符串中不存在更多的标记,则返回 NULL 指针。

#include <stdio.h>
#include <string.h>int main()
{char arr1[] = "wk@bit.tech";char arr2[20] = { 0 }; // 临时数据// wk\0bit\0techchar sep[] = "@.";strcpy(arr2, arr1);//strtok(arr2, sep);//strtok(NULL, sep);char* ret = NULL;for (ret=strtok(arr2, sep); ret!=NULL; ret=strtok(NULL, sep)){printf("%s\n", ret);}return 0;
}

8、内存拷贝函数 - mem…

memcpy memmove memset memcmp

8.1、memcpy

void * memcpy ( void * destination, const void * source, size_t num );

#include <stdio.h>
#include <string.h>
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] = { 0 };// 拷贝的是整型数据,不能用字符串拷贝strcpy,用内存拷贝memcpymemcpy(arr2, arr1, 10 * sizeof(int));int i = 0;for (i = 0; i < 20; i++){printf("%d ", arr2[i]);}return 0;
}

模拟实现memcpy

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

重叠/不重叠

void* my_memcpy(void* dest, const void* src, size_t count)
{void* ret = dest;assert(dest && src);while (count--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };my_memcpy(arr+2, arr, 16); // 起始位置3   把1234拷贝到2456// 不能完成// 但库函数和memcpy可以// memcpy - 只要完成不重叠的内存拷贝就完成任务60分,但VS中的memcpy完成了100分// 内存拷贝的时候,出现内存重叠的现象,应使用,memmoveint i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

C语言库函数记录


8.2、模拟实现memmove

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

8.3、memcmp - 比较内存里的数据

#include <stdio.h>int main()
{int arr1[] = { 1,2,3,3,5 }; // 01 00 00 00 02 00 00 00 03 00 00 00 03 00 00 00 05 00 00 00int arr2[] = { 1,2,3,5,7 }; // 01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 07 00 00 00int ret = memcmp(arr1, arr2, 13); // 返回小于0的数字return 0;
}

8.4、memset - memory set 内存设置

把每个字节初始化成1

#include <stdio.h>int main()
{int arr[] = { 1,2,3,4,5,6,7 };memset(arr, 1, 24);return 0;
}

9、strerror - 返回错误码对应的错误信息

#include <stdio.h>
#include <string.h>int main()
{printf("%s\n", strerror(0)); // No errorprintf("%s\n", strerror(1)); // Operation not permittedprintf("%s\n", strerror(2)); // No such file or directoryprintf("%s\n", strerror(3)); // No such processreturn 0;
}

C语言库函数调用失败的时候,会把错误码,存储到error变量中

fopen - 打开文件:

打开文件 以r(读)的方式 返回FILE*的指针变量
打开成功,放地址;打开失败,放NULL

int main()
{FILE* pf = fopen("test.txt", "r");// strerror - 可以返回C语言内置的错误码对应的错误信息if (pf == NULL){printf("%s\n", strerror(errno)); // No such file or directory}else{printf("打开文件成功\n");}return 0;
}

strerror - 把错误码转化成错误信息,需要自己打印
perror - 可以直接打印

int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("测试:"); // 测试:: No such file or directory}else{printf("打开文件成功\n");}return 0;
}

字符函数、字符串函数、内存函数用法及其模拟实现相关推荐

  1. c语言:字符串和内存函数介绍

    字符串和内存函数: 目录 1.strlen(包含于头文件string.h) 2.strcpy(包含于头文件string.h) 3. strcat(包含于头文件string.h) 4.strcmp(包含 ...

  2. 关于c语言字符串函数和一些内存函数的的简介

    关于c语言字符串函数和一些内存函数的的简介 求字符串长度的函数 strlen函数介绍![在这里插入图片描述](https://img-blog.csdnimg.cn/20190301142458376 ...

  3. R语言str_subset函数和str_which函数:str_subset函数提取字符串向量中所有包含匹配字符的字符串、str_which函数返回字符串向量中所有包含匹配字符的位置(索引)

    R语言str_subset函数和str_which函数:str_subset函数提取字符串向量中所有包含匹配字符的字符串.str_which函数返回字符串向量中所有包含匹配字符的位置(索引) 目录

  4. c++ 字符串合并_C语言输入字符和字符串(所有函数大汇总)

    C语言输入字符和字符串(所有函数大汇总) C语言有多个函数可以从键盘获得用户输入,它们分别是: scanf():和 printf() 类似,scanf() 可以输入多种类型的数据. getchar() ...

  5. js怎么把函数字符串转成函数_字符串处理函数

    整理一下日常用到的c++中的字符串处理函数 1.strpbrk和strspn 最近看了一个解析http请求的方法,里面用到了这俩函数,在这里记录一下.首先,http的请求报文的格式如下: strpbr ...

  6. C语言输入字符和字符串(所有函数大汇总)

    C语言有多个函数可以从键盘获得用户输入,它们分别是: scanf():和 printf() 类似,scanf() 可以输入多种类型的数据. getchar().getche().getch():这三个 ...

  7. mysql 截取第一个字符_MySQL 字符串截取SUBSTRING()函数

    MySQL 字符串截取相关函数: 1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例: select left(content,200) as ab ...

  8. 【C语言】字符串和内存函数详解

    文章目录 1. 求字符串长度 strlen

  9. 【C语言】字符串和内存函数介绍及模拟实现

  10. 自学python第四课——字符串运算符、字符串内置函数、字符串常用方法总结

    第四课 字符串 单.双.三引号 直接赋值和用 input 赋值: "+"号和"*"号在字符串中的使用 in 和 not in 字符串的格式化 r 保留原格式,即 ...

最新文章

  1. boost::mp11::mp_rename相关用法的测试程序
  2. html打开软件连接的代码,《前端开发从零学起》Lesson.7 HTML中超链接的使用方法...
  3. PHP里面最难的是那部分,那个PHP中号称最难的‘递归函数’
  4. 关于BSTR数据类型
  5. 计算机网络第四章总结
  6. html 设计页面,HTML5网页设计
  7. win10 共享打印机错误0x00000709修复
  8. 【实验技术笔记】细胞表型检测之细胞增殖(CCK-8法 + BrdU掺入法 + 平板克隆)
  9. 阿里矢量图标(字体图标) 、 阴影
  10. t恤衫尺码对照表_T恤衫
  11. 51单片机课设——温控手机散热器
  12. Angular 依赖注入框架里 useExisting 和 useClass 的使用场景
  13. mysql插入路径_Conventional-pathinsert(传统路径插入)
  14. 为什么街上发传单的人会认真发完,却不把传单丢了呢?
  15. 小程序长按识别公众号二维码、个人微信号、企业微信号、微信群、-已实现
  16. k8s cheat sheet
  17. 产品经理的分类和职责
  18. 【Suatin】不学编译原理就制作语言2——Concrete Syntax Tree
  19. 高级Spring之Scope 详解
  20. 中国科学院深圳理工大学(筹,简称深理工)明珠校区举行开园仪式并迎来首批学生...

热门文章

  1. java 打印预览_java打印和打印预览机制实例代码
  2. php like %%,thinkphp实现like模糊查询实例
  3. java分隔符 字符串_我们如何使用Java分割带有任何空白字符作为分隔符的字符串?...
  4. 观点 | 云原生时代来袭 下一代云数据库技术将走向何方?...
  5. Web安全相关(二):跨站请求伪造(CSRF/XSRF)
  6. PROFILER 技术总结(二): 利用Monte Carlo Profiler 工具
  7. AppBoxPro - 细粒度通用权限管理框架(可控制表格行内按钮)源码提供下载
  8. JdbcTemplate的主要用法
  9. Python爬虫之:下载软件包
  10. Android核心基础(五)