【C语言】字符函数,字符串函数,内存函数

大家好!今天我们来学习C语言中的字符函数,字符串函数和内存函数。

目录

1. 字符函数

1.1 字符分类函数

1.2 字符转换函数

1.2.1 tolower(将大写字母转化为小写字母)

1.2.2 toupper(将小写字母转化为大写字母)

2. 字符串函数

2.1 字符串输入函数

2.1.1 gets()

​2.1.2 fgets()

2.2 字符串输出函数  puts()

​2.3 字符串求长度函数  strlen

2.4 长度不受限制的字符串函数

2.4.1 字符串复制函数  strcpy

​2.4.2 字符串连接函数  strcat

2.4.3 字符串比较函数  strcmp

​2.5 长度受限制的字符串函数

2.5.1 strncpy

​2.5.2 strncat

2.5.3 strncmp

​2.6 字符串查找函数  strstr

2.7 字符串分割函数  strtok

2.8 错误处理函数  strerror

3. 内存函数

3.1 memcpy

​3.2 memmove

3.3 memset

​3.4 memcmp

3. 总结


1. 字符函数

1.1 字符分类函数

字符分类函数的头文件为ctype.h

具体用法可以看这个:https://legacy.cplusplus.com/reference/cctype/

1.2 字符转换函数

字符转换函数的头文件也为ctype.h

1.2.1 tolower(将大写字母转化为小写字母)

函数原型:

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<ctype.h>int main() {char ch = 'B';char new_ch = tolower(ch);printf("%c", new_ch);return 0;
}

1.2.2 toupper(将小写字母转化为大写字母)

函数原型:

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<ctype.h>int main() {char ch = 'b';char new_ch = toupper(ch);printf("%c", new_ch);return 0;
}

2. 字符串函数

字符串输入函数和字符串输出函数的头文件均为stdio.h

其它的字符串函数头文件一般为string.h

2.1 字符串输入函数

2.1.1 gets()

函数原型:

gets() 函数的功能是从输入缓冲区中读取一个字符串存储到字符指针变量 str 所指向的内存空间。缓冲区(Buffer)又称为缓存(Cache),是内存空间的一部分。有时候,从键盘输入的内容,或者将要输出到显示器上的内容,会暂时进入缓冲区,待时机成熟,再一股脑将缓冲区中的所有内容“倒出”,我们才能看到变量的值被刷新,或者屏幕产生变化。

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>int main() {char str[30];gets(str);puts(str);return 0;
}

但是这个函数在C或C++不可再用(自C11和C++14起),因为不安全

(不过在实际做题中,我发现有些oj上还是能用的~)

2.1.2 fgets()

因为前面说了gets()函数不安全,在新版C++已经不可再用,所以fgets()用来替代gets()。

但注意fgets()不会删除行末的回车字符

fgets()函数是C语言中的一个输入函数,用于从标准输入(例如键盘)读取一行字符串。

函数原型:

fgets()的作用是读取一行字符并存储到指定的字符串缓冲区中,直到读取到换行符或者达到指定的最大字符数(包括换行符)为止。

其中,str是指向存储读取字符串的缓冲区的指针,num是缓冲区的大小,stream是要读取的文件流(通常使用stdin表示标准输入)。

fgets函数返回指向存储读取字符串的缓冲区的指针,如果读取成功,则返回值与str相同,如果出现错误或者到达文件末尾,则返回NULL。

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>int main() {char str[30];fgets(str,30,stdin);puts(str);return 0;
}

2.2 字符串输出函数  puts()

函数原型:

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>int main() {char str[30] = "hello world";puts(str);return 0;
}

2.3 字符串求长度函数  strlen

函数原型:

注意事项:

1. 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数不包
含 '\0'
)。
2. 参数指向的字符串必须要以 '\0' 结束。
3. 注意函数的返回值为size_t,是无符号的。

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>int main() {char str[30] = "abcdef";printf("%d\n", strlen(str));return 0;
}

strlen的模拟实现

size_t my_strlen(const char* str)
{assert(str);int cnt = 0;while (*str!='\0'){cnt++;str++;}return cnt;
}

2.4 长度不受限制的字符串函数

2.4.1 字符串复制函数  strcpy

函数原型:

注意事项:

1. 源字符串必须以 '\0' 结束。

2. 会将源字符串中的 '\0' 拷贝到目标空间。

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

4. 目标空间必须可变。

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = { 0 };char str2[30] = "abcdef";strcpy(str1, str2);printf("%s\n",str1);return 0;
}

strcpy的模拟实现

char* my_strcpy(char *dest,const char *src)
{assert(dest && src);char* ret = dest;while (*dest++=*src++){;}return ret;
}

2.4.2 字符串连接函数  strcat

函数原型:

注意事项:

1. 源字符串必须以 '\0' 结束。

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

3. 目标空间必须可修改。

4. 字符串不能自己追加自己

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = "hello ";char str2[30] = "world";printf("%s\n",strcat(str1,str2));return 0;
}

strcat的模拟实现

char* my_strcat(char* dest, const char* src)
{assert(dest && src);char* ret = dest;while (*dest!='\0')dest++;while (*dest++ = *src++){;}return ret;
}

2.4.3 字符串比较函数  strcmp

函数原型:

标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字。
第一个字符串等于第二个字符串,则返回0。
第一个字符串小于第二个字符串,则返回小于0的数字。

我们结合下图就能很直观理解上面的标准规定~

用法示例:

情况一:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = "above";char str2[30] = "about";printf("%d\n",strcmp(str1,str2));return 0;
}

情况二:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = "About";char str2[30] = "about";printf("%d\n",strcmp(str1,str2));return 0;
}

情况三:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = "about";char str2[30] = "about";printf("%d\n",strcmp(str1,str2));return 0;
}

strcmp的模拟实现

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;else return -1;
}

2.5 长度受限制的字符串函数

2.5.1 strncpy

函数原型:

注意事项:

1. 拷贝num个字符从源字符串到目标空间。

2. 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
 

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = "abcdef";char str2[30] = "xxxxxxxxxxxxxx";strncpy(str1, str2, 4);printf("%s\n", str1);return 0;
}

2.5.2 strncat

函数原型:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = "hello ";char str2[30] = "worldxxxxxx";strncat(str1, str2, 5);printf("%s\n", str1);return 0;
}

2.5.3 strncmp

函数原型:

逐个比较两个字符串字符的ASCII码值,直到出现不一样的字符或者一个字符串结束或者num个字符全部比较完。

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = "abc";char str2[30] = "abcdef";char str3[30] = "aba";printf("%d\n", strncmp(str1, str2, 3));printf("%d\n", strncmp(str1, str2, 4));printf("%d\n", strncmp(str1, str3, 5));return 0;
}

2.6 字符串查找函数  strstr

函数原型:

strstr函数的作用是在字符串str1中查找是否含有字符串str2的子串,如果存在,返回str2在str1中第一次出现的地址;否则返回空指针NULL。

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str1[30] = "abcdef";char str2[30] = "abc";if (strstr(str1, str2))printf("找到了\n");elseprintf("找不到\n");return 0;
}

strstr的模拟实现

char* my_strstr(char* str1, char* str2)
{assert(str1 && str2);char* cp = str1;char* s1 = cp;char* s2 = str2;if (str2 == '\0')return str1;while (*cp){s1 = cp;s2 = str2;while (*s1 && *s2 && *s1 == *s2){s1++;s2++;}if (*s2 == '\0')return cp;cp++;}return NULL;
}

2.7 字符串分割函数  strtok

strtok函数的作用是将一个字符串按照指定的分隔符进行分割,并返回分割后的子字符串。

函数原型:

注意事项:

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

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

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

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

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

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

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main() {char str[] = "Hello, world! How are you today?";char delim[] = " ,!?"; // 分隔符包括空格、逗号和感叹号// 使用第一次调用strtok函数char* token = strtok(str, delim);// 循环调用strtok函数以获取每个子字符串while (token != NULL) {printf("%s\n", token);token = strtok(NULL, delim);}return 0;
}

以上代码将输入字符串"Hello, world! How are you today?"按照空格、逗号和感叹号作为分隔符,将其分割成多个子字符串,并依次打印每个子字符串。输出结果如下:

注意:在整个循环过程中,使用NULL作为第一个参数,以便继续分割原字符串。这样可以依次获取每个子字符串。

2.8 错误处理函数  strerror

strerror的作用是根据给定的错误代码返回相应的错误描述字符串。

具体而言,strerror函数接受一个整数参数errno作为输入,该参数代表了一个错误代码。函数会根据给定的错误代码查找对应的错误描述字符串,并将其返回。

函数原型:

用法示例:

示例一:

下面代码是将错误码0~9所对应的错误信息给打印出来:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>int main()
{int i = 0;for (int i = 0; i < 10; i++){printf("%d:%s\n", i, strerror(i));}return 0;
}

示例二:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <errno.h>int main() {FILE* file = fopen("nonexistent.file", "r");if (file == NULL) {int error_code = errno;const char* error_msg = strerror(error_code);printf("Failed to open file: %s\n", error_msg);}else {// 文件打开成功,继续其他操作// ...fclose(file);}return 0;
}

以上代码尝试打开一个名为"nonexistent.file"的文件,如果文件打开失败,则获取对应的错误代码,并使用strerror函数获取错误描述字符串,最后将错误描述字符串打印出来。输出结果类似于:

需要注意的是,strerror函数返回的错误描述字符串可能是静态分配的,多次调用strerror函数可能会覆盖之前的结果。因此,建议尽量将结果保存在变量中,而不是直接在printf等函数中使用strerror函数。

3. 内存函数

内存函数的头文件一般也为string.h

3.1 memcpy

memcpy函数作用是将指定长度的内存块从源地址复制到目标地址。

也就是说,memcpy函数用来处理不重叠的内存拷贝。

函数原型:

注意事项:

1. 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。

2. 这个函数在遇到 '\0' 的时候并不会停下来。

3. 如果source和destination有任何的重叠,复制的结果都是未定义的。

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>int main() {int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] = { 0 };//将arr1中的内容,拷贝到arr2中memcpy(arr2, arr1, 40);for (int i = 0; i < 20; i++)printf("%d ", arr2[i]);return 0;
}

memcpy的模拟实现

void* my_memcpy(void* dest, const void* src, size_t num) //num单位是字节
{void* ret = dest;assert(src && dest);while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}

3.2 memmove

memmove函数作用是将指定长度的内存块从源地址移动到目标地址,允许源和目标内存块重叠。

也就是说,memmove函数用来处理重叠内存拷贝

函数原型:

用法示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };memmove(arr1 + 2, arr1, 20);for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);return 0;
}

memmove的模拟实现:

void* my_memmove(void* dest, const void* src, size_t num) //num单位是字节
{void* ret = dest;assert(dest && src);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;
}

3.3 memset

memset函数作用是将指定长度的内存块填充为指定的值。

函数原型:

用法示例:

示例一:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main()
{int arr[5];memset(arr, 0, sizeof(arr));for (int i = 0; i < 5; i++)printf("%d ", arr[i]);return 0;
}

数组arr的所有元素都将被设置为0。

示例二:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main(){char arr[] = "hello world";memset(arr + 1, 'x', 4); //以字节为单位设置的printf("%s\n", arr);return 0;
}

3.4 memcmp

memcmp的作用是比较两个内存块的内容。

函数原型:

注意事项:

比较从ptr1和ptr2指针开始的num个字节

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>int main(){int arr1[] = { 1,2,1,4,5,6 };int arr2[] = { 1,2,257 };int ret = memcmp(arr1, arr2, 10);printf("%d\n", ret);return 0;
}

3. 总结

到这里,我们就介绍完了C语言中的字符函数,字符串函数和内存函数。有什么问题欢迎在评论区讨论。如果觉得文章有什么不足之处,可以在评论区留言。如果喜欢我的文章,可以点赞收藏哦!

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

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

相关文章

ZigBee案例笔记 -- RFID卡片读写(模拟饭卡)

RFID模拟饭卡应用 RFID&#xff08;射频识别技术&#xff09;RFID通讯协议RFID发展历史RFID操作流程说明RFID卡片读写流程RFID寻卡RFID防碰撞RFID选卡RFID卡密验证RFID读卡RFID写卡读写数据流程 RFID饭卡模拟案例驱动代码串口协议饭卡操作案例结果优化建议 RFID&#xff08;射频…

Cordova Android 生成的 APK 中添加代码混淆

要在 Cordova Android 生成的 APK 中添加代码混淆&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1. 在项目根目录下&#xff0c;找到 platforms/android/ 目录&#xff0c;进入该目录。 2. 打开 build.gradle 文件&#xff0c;并在 android { ... } 部分添加以下代码&…

关于两个不同数据库的两张表建立数据库链接,关联查询数据

一、数据库链接 数据库链接&#xff08;database link&#xff09;是用于跨不同数据库之间进行连接和数据传输的工具或方法。它允许在一个数据库中访问另一个数据库中的对象和数据。 二、具体操作 以Oracle数据库为例 --1.建立链接tjpt CREATE DATABASE LINK tjpt CONNECT…

go语言--锁

锁的基础&#xff0c;go的锁是构建在原子操作和信号锁之上的 原子锁 原子包实现协程的对同一个数据的操作&#xff0c;可以实现原子操作&#xff0c;只能用于简单变量的简单操作&#xff0c;可以把多个操作变成一个操作 sema锁 也叫信号量锁/信号锁 核心是一个uint32值&#…

基于单片机的串行通信发射机设计

一、项目介绍 串行通信是一种常见的数据传输方式&#xff0c;允许将数据以比特流的形式在发送端和接收端之间传输。当前实现基于STC89C52单片机的串行通信发射机&#xff0c;通过红外发射管和接收头实现自定义协议的数据无线传输。 二、系统设计 2.1 单片机选择 在本设计中&…

前端基础2——CSS样式

文章目录 一、使用方式1.1 内联方式1.2 内部方式1.3 外部导入方式&#xff08;推荐&#xff09; 二、选择器类型2.1 元素选择器2.2 ID选择器2.3 类选择器2.4 派生选择器 三、常用属性3.1 内边距和外边距3.2 文本3.3 边框3.4 背景3.5 定位3.6 浮动3.7 字体3.8 其他属性 四、案例…

MySQL 数据库常用命令大全(完整版)

文章目录 1. MySQL命令2. MySQL基础命令3. MySQL命令简介4. MySQL常用命令4.1 MySQL准备篇4.1.1 启动和停止MySQL服务4.1.2 修改MySQL账户密码4.1.3 MySQL的登陆和退出4.1.4 查看MySQL版本 4.2 DDL篇&#xff08;数据定义&#xff09;4.2.1 查询数据库4.2.2 创建数据库4.2.3 使…

DataTable扩展 列转行方法(2*2矩阵转换)

源数据 如图所示 // <summary>/// DataTable扩展 列转行方法&#xff08;2*2矩阵转换&#xff09;/// </summary>/// <param name"dtSource">数据源</param>/// <param name"columnFilter">逗号分隔 如SDateTime,PM25,PM10…

docker desktop安装es 并连接elasticsearch-head:5

首先要保证docker安装成功&#xff0c;打开cmd&#xff0c;输入docker -v&#xff0c;出现如下界面说明安装成功了 下面开始安装es 第一步&#xff1a;拉取es镜像 docker pull elasticsearch:7.6.2第二步&#xff1a;运行容器 docker run -d --namees7 --restartalways -p 9…

ShardingSphere——压测实战

摘要 Apache ShardingSphere 关注于全链路压测场景下&#xff0c;数据库层面的解决方案。 将压测数据自动路由至用户指定的数据库&#xff0c;是 Apache ShardingSphere 影子库模块的主要设计目标。 一、压测背景 在基于微服务的分布式应用架构下&#xff0c;业务需要多个服…

WebVR — 网络虚拟现实

推荐&#xff1a;使用 NSDT编辑器 快速搭建3D应用场景 虚拟现实设备 随着Oculus Rift和许多其他生产设备即将上市&#xff0c;未来看起来很光明——我们已经有足够的技术来使VR体验“足够好”&#xff0c;可以玩游戏。有许多设备可供选择&#xff1a;像Oculus Rift或HTC Vive这…

JasperReport定义变量后打印PDF变量为null以及整个pdf文件为空白

问题1: JasperReport打印出来的整个pdf文件为空白文件&#xff1b; 问题2&#xff1a;JasperReport定义变量后打印PDF变量为null&#xff1b; 问题1原因是因为缺少数据源JRDataSource JasperFillManager.fillReport(jasperReport, params,new JREmptyDataSource());如果你打印…

Go 使用 Gorm 将操作信息集成到链路跟踪 Jaeger,进行增删改查使用举例,并做可视化UI界面展示(附源码)

Go 使用 Gorm 将操作信息集成到链路跟踪 Jaeger,进行增删改查使用举例(附源码)。 为了增强程序的可观测性,方便问题定位,在发起数据库操作请求时我们也可以调用代码统一集成链路跟踪的能力,Jaeger 是当今比较流行的选择。使用 Gorm 来将操作信息集成到 Jaeger 中。 全面…

Autofac中多个类继承同一个接口,如何注入?与抽象工厂模式相结合

多个类继承同一个接口,如何注入&#xff1f;与抽象工厂模式相结合 需求: 原来是抽象工厂模式,多个类继承同一个接口。 现在需要使用Autofac进行选择性注入。 Autofac默认常识: Autofac中多个类继承同一个接口,默认是最后一个接口注入的类。 解决方案&#xff1a;(约定大于配…

使用远程桌面软件改善工作与生活的平衡

在当今高度互联的世界中&#xff0c;我们的工作和个人生活之间的界限变得越来越模糊。在本文中&#xff0c;我们将探讨像 Splashtop 这样的远程桌面工具如何成为实现和谐工作与生活平衡不可或缺的一部分。 在当今的背景下理解工作与生活的平衡 工作与生活的平衡不仅仅是一个时…

【C++进阶】模板进阶

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

Ansible学习笔记5

copy模块&#xff1a;&#xff08;重点&#xff09; copy模块用于对文件的远程拷贝&#xff08;如把本地的文件拷贝到远程主机上。&#xff09; 在master的主机上准备一个文件&#xff0c;拷贝文件到group1的所有主机上。 这个用的频率非常高&#xff0c;非常有用的一个模块…

pdf加密如何解除?这样解除加密很简单

pdf加密如何解除&#xff1f;有时&#xff0c;我们可能会收到一些加密的PDF文件&#xff0c;它们不允许我们对其进行编辑或打印。这时&#xff0c;我们需要使用PDF解密工具&#xff0c;以便能够轻松地解除PDF加密并对其进行编辑。那么接下来就给大家介绍一下pdf加密解除的方法。…

11.物联网lwip,网卡原理

一。LWIP协议栈内存管理 1.LWIP内存管理方案 &#xff08;1&#xff09;堆heap 1.灰色为已使用内存 2.黑色为未使用内存 3.紫色为使用后内存 按照某种算法&#xff0c;把数据放在内存块中 &#xff08;2&#xff09;池pool 设置内存池&#xff0c;设置成大小相同的内存块。 2…

JVM调优指令参数

常用命令查找文档站点&#xff1a;https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html -XX:PrintFlagsInitial 输出所有参数的名称和默认值&#xff0c;默认不包括Diagnostic和Experimental的参数。可以配合 -XX:UnlockDiagnosticVMOptions和-XX:UnlockEx…