字符串函数及内存函数C语言

字符函数及内存函数

  • 一.字符串函数函数
    • 1.strlen函数
    • 2.strcpy函数
    • 3.strcat函数
    • 4.strcmp函数
    • 5.strncpy函数
    • 6.strncat函数
    • 7.strncmp函数
    • 8.strstr函数
    • 9.strtok函数
    • 10.strerror函数
  • 二.内存函数
    • 1.memcpy函数
    • 2.memmove函数
    • 3.memcpy函数
    • 4.memset函数

一.字符串函数函数

1.strlen函数

size_t strlen ( const char * str );

作用: 计算字符串长度,返回的是字符串长度,无符号整数

  • strlen()函数以\0作为结束标志,返回的是\0之前的字符个数,不包含\0
  • 参数指向的字符串必须以\0结束
  • 参数的返回值是一个无符号整数,所以在做差比较时要切记,防止负数但数值很大的情况
  • strlen()函数模拟实现如下
//计数法
size_t my_strcopy(const char* str)
{assert(str != NULL);int count = 0;while (*str!='\0'){count++;str++;}return count;
}

2.strcpy函数

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

作用: 将源字符串拷贝到目标字符串中,返回的是目标字符串的地址

  • 源字符串必须以\0结尾
  • 会将源字符串中的\0拷贝到目标空间
  • 目标空间足够大,以确保能放下源字符串
  • 目标空间必须可变,不能是常量字符串,常量字符串不可变
  • strcpy()函数模拟如下
char* my_strcopy(char* dest, const char* src)
{assert(dest != NULL);assert(src != NULL);char* result = dest;while (*src!='\0'){*dest = *src;dest++;src++;}*dest = *src;return result;
}

3.strcat函数

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

作用: 将源字符串拼接到目标字符串的后面,返回的是目标字符串的地址

  • 源字符串必须以\0结束
  • 目标空间必须足够的大,能容纳的下源字符串
  • 目标空间必须可修改
  • 切记该函数不能自己追加自己
  • 模拟strcat()函数
char* my_strcat(char* dest, const char* src)
{assert(dest != NULL);assert(src != NULL);char* result = dest;while (*dest!='\0'){dest++;}while (*src != '\0'){*dest = *src;dest++;src++;}*dest = *src;return result;
}

4.strcmp函数

作用: 比较两个字符串的大小关系

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

  • 第一个数大于第二个数返回>0的数
  • 第一个数小于第二个数返回<0的数
  • 第一个数等于第二个数返回==0的数
  • 模拟strcmp函数
int my_strcmp(const char* s1,const char* s2)
{assert(s1 != NULL);assert(s2 != NULL);while (*s1==*s2){if (*s1 == '\0'){return 0;}s1++;s2++;}if (*s1 - *s2 > 0){return 1;}else {return -1;}}

上面四种都是字符串长度不受限制的,下面介绍三种字符串长度受限制的

5.strncpy函数

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

  • 可见比strcpy只是多了一个num的参数
  • 此函数复制时,只会复制指定长度n个
  • 若n>要复制的字符串长度,那么后面会复制\0

6.strncat函数

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

  • 可见只是比strcat多了一个长度限制参数
  • 该函数会将指定长度num个字符拼接到目标函数后面,如果num>源字符串时,也只会拼接源字符串的长度个字符
  • 该函数拼接完后,会在末尾拼接一个\0

7.strncmp函数

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

  • 该函数比strcmp函数多了一个参数num的长度限制
  • 该函数只会比较num个字符
  • 这num个字符相同就返回0,第一个字符大于第二个字符返回>0的数,第一个字符小于第二个字符返回<0的数

8.strstr函数

char * strstr ( const char *str1, const char * str2)

作用: 在一个字符串中查找指定子串存不存在,存在返回第一次出现的位置到结束的字符串

  • 模拟实现strstr函数
char* my_strstr(const char* s1, const char* s2)
{assert(s1 != NULL);assert(s2 != NULL);char* position = s1;char* move1 = s1;char* move2 = s2;while (*position!=NULL){move1 = position;move2 = s2;while (*move1==*move2&&*move1!=NULL&&*move2!=NULL){move1++;move2++;}if (*move2 == NULL){return position;}position++;}
}

9.strtok函数

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

==作用:==将一个字符串按照特定的字符串进行分割

  • const char* sep这个参数是一个字符串,定义了分隔符的集合
  • 第一个参数是一个字符串,该字符串里面可以包含0个或多个分隔符字符
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。注:
    strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
    并且可修改。
  • 如果第一个参数不为NULL,那么该函数会找到该字符串中第一次出现该分隔符的位置,进行分割,并且记录下一次出现分隔符的位置
  • 如果第一个参数为NULL,那么该函数会从下一次被标记的位置开始,进行分割
  • 如果字符串中不存在更多的标记那么返回NULL

strtok函数的使用

int main()
{char s1[] = "LC@AI>Ming@666";char s2[] = { '@','>','\0' };char s3[30];strcpy(s3, s1);for (char* i = strtok(s3, s2);i != NULL;i = strtok(NULL,s2)){printf("%s\n", i);}
}

10.strerror函数

char * strerror ( int errnum )

==作用:==将程序中产生的错误码转为字符串,方便我们直到哪里有错

  • 库函数在执行的时候,发生了错误会将一个错误码存放在errno这个变量中errno是C语言提供的一个全局的变量
  • 参数为错误码,只要给一个错误码,就会返回当前错误码对应的错误信息
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));//perror(字符串);自带打印return 1;}fclose(pf);return 0;
}
  • 这里我们在传错误码时,直接传errno,这个变量当程序发生错误时,会将错误存放在这个变量中
  • printf(“%s\n”, strerror(errno))这句代码可以用perror()这个函数替换,perror()里面可以传一个参数,以确保我们知道哪里出了问题,它自带打印
//这两句代码等价
printf("fopen:%s\n", strerror(errno));
perror("fopen");

二.内存函数

下面是几个常用的内存函数

1.memcpy函数

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

作用: 拷贝内存中的数据

  • 函数从source所指向的地址开始,复制num个字节数据到destination所指向的内存地址
  • 这个函数在遇到\0时并不会停下来,因为它可以复制所有类型数据,与\0无关,与内存有关
  • 如果source和destination有任何的重叠,复制的结果都是未定义的,即不能复制重叠部分的内容
  • memcpy函数模拟实现
void* my_memcpy(void* dest, const void* src,size_t num)
{assert(dest != NULL);assert(src != NULL);void* result = dest;while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return result;
}

2.memmove函数

void * memmove ( void * destination, const void * source, size_t num )

作用: 拷贝内存中的数据

  • 和memcpy作用类似,但它可以拷贝重叠部分的内容,也可以拷贝不重叠部分的内容
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理,如果没有重叠,两者都可以
  • 模拟实现memmove函数
void* my_memmove(void* dest,const void* src,size_t num)
{assert(dest != NULL);assert(src != NULL);void* result = 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 result;
}

3.memcpy函数

int memcmp ( const void * ptr1, const void * ptr2, size_t num )

作用: 两个数据进行比较,以内存字节为基准

  • 按照一个一个字节比较,如果这些字节都相等就返回0.如果第一个字节大返回>0的数,如果第一个字节小返回<0的数

4.memset函数

void * memset ( void * ptr, int value, size_t num )

作用: 将ptr所指向的内存空间,按字节填充为value

  • 这里要注意是将内存空间里的字节里的值填充为value,并不是将数据直接填充为value

比如我执行下面代码

int main()
{int arr[] = { 1,2,3,4,5 };memset(arr, 1, 20);for (int i = 0;i < 5;i++){printf("%d ", arr[i]);}
}

初学者看到,有可能会以为我是要将arr数组中的五个元素全部设置为1,但是实际上并不是,这样设置会将内存中每个字节都设置为1,结果是一个很大的数
在这里插入图片描述
而此时内存图如下:
在这里插入图片描述
可见该函数是以字节进行内存设置的,如果要将该数组全部填充为某一值(0除外),这个方法是不行的

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

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

相关文章

【程序员必须掌握哪些算法?】

一个程序员一生中可能会邂逅各种各样的算法&#xff0c;但总有那么几种&#xff0c;是作为一个程序员一定会遇见且大概率需要掌握的算法。今天就来聊聊这些十分重要的“必抓&#xff01;”算法吧~ 常见算法介绍 本文所介绍的排序算法均以升序为例。 文章目录 常见算法介绍一 …

P106-100组A卡(R5 240)指南

P106-100组A卡&#xff08;R5 240&#xff09;指南 不建议小白尝试 不建议小白尝试 不建议小白尝试文章目录 P106-100组A卡&#xff08;R5 240&#xff09;指南资料合集硬件软件基础卸载所有原驱动安装驱动修改注册表自动调用——只改一个注册表手动调用——改两个注册表 劝退…

Qt中QMainWindow的相关介绍

目录 菜单栏 工具栏 状态栏&#xff1a; 停靠窗口&#xff1a; QMainWindow 是标准基础窗口中结构最复杂的窗口&#xff0c;其组成如下: 提供了菜单栏 , 工具栏 , 状态栏 , 停靠窗口 菜单栏&#xff1a;只能有一个&#xff0c;位于窗口的最上方 工具栏&#xff1a;可以有多…

攻不下dfs不参加比赛(十四)

标题 为什么练dfs题目为什么练dfs 相信学过数据结构的朋友都知道dfs(深度优先搜索)是里面相当重要的一种搜索算法,可能直接说大家感受不到有条件的大家可以去看看一些算法比赛。这些比赛中每一届或多或少都会牵扯到dfs,可能提到dfs大家都知道但是我们为了避免眼高手低有的东…

软件体系结构-KWIC索引系统

引言 KWIC作为一个早年间在ACM的Paper提出的一个问题&#xff0c;被全世界各个大学的软件设计课程奉为课堂讲义或者作业的经典。&#xff08;From Wiki&#xff0c;FYI&#xff0c;D. L. Parnas uses a KWIC Index as an example on how to perform modular design in his pap…

MySQL(三)SQL优化、Buffer pool、Change buffer

MySQL系列文章 MySQL&#xff08;一&#xff09;基本架构、SQL语句操作、试图 MySQL&#xff08;二&#xff09;索引原理以及优化 MySQL&#xff08;三&#xff09;SQL优化、Buffer pool、Change buffer MySQL&#xff08;四&#xff09;事务原理及分析 MySQL&#xff08;五&a…

自学数据结构和算法(5)

二叉树的遍历 分为先序、中序、和后序遍历。 这三种遍历都可以由递归序来得到&#xff1a; &#xff08;1&#xff09;先序遍历&#xff08;也是二叉树的深度优先遍历&#xff09;是第一次到某个结点才打印&#xff1b; &#xff08;2&#xff09;中序遍历是第二次到某个结…

谋合作、创新境 | 百度参观图为科技生产全链路

当代科技的发展不断催生出新的变革和机遇&#xff0c;百度作为全球顶尖的高科技公司&#xff0c;凭借其强大的创新基因&#xff0c;一直处于人工智能领域的最前沿。   近日&#xff0c;百度公司派出了一支专业团队来到了图为科技&#xff0c;对图为的研发技术及生产线进行了全…

《Maven实战》读后感

目录 一、一些思考1、为什么平时编写的Java项目也叫做Maven项目&#xff1f;2、平常的Java项目目录为什么长这样&#xff0c;可以改变目录结构吗&#xff1f;3、对于Maven项目来说&#xff0c;Maven能帮我们做什么&#xff1f;4、为什么一定需要Maven私服&#xff0c;不要行不行…

每天一道C语言编程:排队买票

题目描述 有M个小孩到公园玩&#xff0c;门票是1元。其中N个小孩带的钱为1元&#xff0c;K个小孩带的钱为2元。售票员没有零钱&#xff0c;问这些小孩共有多少种排队方法&#xff0c;使得售票员总能找得开零钱。注意&#xff1a;两个拿一元零钱的小孩&#xff0c;他们的位置互…

GoFrame v2.5 版本发布,企业级 Golang 开发框架

大家好啊&#xff0c;GoFrame 框架今天发布了 v2.5.0 正式版本啦&#xff01;&#x1f44f;&#x1f44f;&#x1f44f;&#x1f44f; 本次版本主要是对已有功能组件以及开发工具上的改进工作。其中&#xff0c;开发工具新增了 gf gen ctrl 命令&#xff0c;以规范化定义、开发…

orcle报错:TNS 监听程序无法为请求的服务器类型找到可用的处理程序

orcle报错&#xff1a;TNS 监听程序无法为请求的服务器类型找到可用的处理程序 方法一&#xff1a;配置文件修改 服务端的数据库是专用服务器,但是在客户端的tnsname.ora里配置中设置了连接方式为shared,这种情况下打开tnsnames.ora, 找到安装orcle的安装目录&#xff0c;点…