常用字符串函数拓展

news/2024/11/28 13:30:55/

文章目录

  • 字符串拓展函数
    • strncpy
    • strncat
    • strncmp
    • strstr
    • strtok
    • strerror
    • memcpy
    • memmove
    • memcmp
    • memset
  • 库函数模拟实现
    • memmove
    • qsort

我们在学习C语言时已经学习了一些常见的字符串函数,但这还不能满足我们的需求,为此我们拓展了几个常用的字符串函数。

字符串拓展函数

strncpy

函数原型为:

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

该函数用于从源字符串拷贝num个字符到目标空间,如果字符串的长度小于num,在拷贝完源字符串后,在目标后面追加0,直至num个字符。

strncat

函数原型为:

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

该函数将源字符串前num个字符追加到目标空间中,追加完后自动在目标字符串后加上‘\0’,如果num大于源字符串的长度,最多也只会将源字符串全部追加到目标字符串后面。

strncmp

函数原型为:

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

用于两个字符串的比较,比较到出现两个字符不一样或其中一个字符串结束或num个字符全部比完,
其返回值的含义为:
在这里插入图片描述

strstr

函数原型为:

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

该函数用于查找在str1中是否出现了str2,如果有,返回str2在str1中第一次出现的地址,否则返回空指针。

strtok

函数原型为:

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

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

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

从加粗部分我们可以知道strtok函数具有记忆功能,因此我们若想将字符串分为多部分,第一次调用strtsr函数时str传非空指针,后面都要传空指针,直至分割完毕。

#include <stdio.h>
#include <string.h>int main ()
{char str[] ="This,a sample/string.";char * pch;pch = strtok (str,",/");//第一次传非空while (pch != NULL){printf ("%s\n",pch);pch = strtok (NULL, ",/");//后面都传空指针}return 0;
}输出结果为:
This
a simple
string.

strerror

函数原型为:

char * strerror ( int errnum );

该函数会返回错误码所对应的错误信息,可以通过printf函数将错误信息打印出来。
库函数在执行过程中发生了错误会将错误码放在errnum这个变量中,该变量是C语言提供的全局变量,记录最后一次错误信息的错误码,因此要包含头文件<errno.h>。

memcpy

函数原型为:

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

该函数是将souce开始的num个字节的内容拷贝到destination中,换言之,memcpy是对内存进行拷贝,而不只是单单拷贝字符串那么简单。这也意味着如果destination和source存在内存重叠,那么拷贝的内容是不确定的。

memmove

函数原型为:

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

memmove函数是对memcpy函数的改进,解决了源内存块和目标内存块的内存不能重叠的问题。

memcmp

函数原型为;

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

用于比较ptr1和ptr2指针开始的num个字节
其返回值为:
在这里插入图片描述

memset

函数原型为:

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

该函数用于将ptr开始的num个字节全部设为value,要注意是以一个字节为单位的。

库函数模拟实现

memmove

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

要实现memmove函数,主要是解决内存重叠的问题。
我们的解决办法是:由拷贝字节大小和比较源空间与目标空间起始地址的大小来决定我们是选择从前往后还是从后往前拷贝内存。
在这里插入图片描述

void * memmove ( void * dst, const void * src, size_t count)
{void * ret = dst;if (dst <= src || (char *)dst >= ((char *)src + count)) {while (count--) {*(char *)dst = *(char *)src;dst = (char *)dst + 1;src = (char *)src + 1;}}else {dst = (char *)dst + count - 1;src = (char *)src + count - 1;while (count--) {*(char *)dst = *(char *)src;dst = (char *)dst - 1;src = (char *)src - 1;}}return(ret);
}

qsort

可以对任意可以进行比较的数据进行排序
函数原型为:

qsort
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));

相关参数介绍:
在这里插入图片描述

假如我们要对一个数组排升序,可以这样用:

#include <stdio.h>      /* printf */
#include <stdlib.h>     /* qsort */int compare (const void * a, const void * b)
{return ( *(int*)a - *(int*)b );
}int main ()
{int values[] = { 40, 10, 100, 90, 20, 25 };qsort (values, 6, sizeof(int), compare);return 0;
}

这里为了简便,选择冒泡排序进行模拟:

#include <stdio.h>
int int_cmp(const void * p1, const void * p2)
{return (*( int *)p1 - *(int *) p2);
}void _swap(void *p1, void * p2, int size)
{int i = 0;for (i = 0; i< size; i++){char tmp = *((char *)p1 + i);*(( char *)p1 + i) = *((char *) p2 + i);*(( char *)p2 + i) = tmp;}}void bubble(void *base, int count , int size, int(*cmp )(void *, void *))
{int i = 0;int j = 0;for (i = 0; i< count - 1; i++){for (j = 0; j<count-i-1; j++){if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0){_swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);}}}
}

由于其他函数的模拟比较容易实现,这里就不在一一进行模拟实现。至此,本文已经结束。


http://www.ppmy.cn/news/1183655.html

相关文章

MySQL实战2

文章目录 主要内容一.回访用户1.准备工作代码如下&#xff08;示例&#xff09;: 2.目标3.实现代码如下&#xff08;示例&#xff09;: 二.如何找到每个人每月消费的最大天数1.准备工作代码如下&#xff08;示例&#xff09;: 2.目标3.实现代码如下&#xff08;示例&#xff09…

[AUTOSAR][诊断管理][ECU][$22] 读取相关的数据

文章目录 一、简介$22服务的实际用途是什么?$22服务的应用场景有哪些呢?$22服务的诊断格式如何?常见DID总结请求实例服务响应负响应NRCNRC优先级二、示例代码uds22_read_data_by_ld.c一、简介 22服务作为诊断服务种的基础服务,可以简单理解为就是一个用于读取ECU数据的外部…

应用案例|基于三维机器视觉的机器人引导电动汽车充电头自动插拔应用方案

Part.1 项目背景 人类对减少温室气体排放、提高能源效率以及减少对化石燃料的依赖&#xff0c;加速了电动汽车的普及&#xff0c;然而&#xff0c;电动汽车的充电依然面临一些挑战。传统的电动汽车充电通常需要人工干预&#xff0c;插入和拔出充电头&#xff0c;这不仅可能导致…

网络滤波器/网络滤波器/脉冲变压器要怎样进行测试,一般要测试哪些参数?

Hqst华强盛导读&#xff1a;网络滤波器/网络滤波器/脉冲变压器要怎样进行测试&#xff0c;一般要测试哪些参数&#xff1f;测试网络滤波器的测试方法和步骤如何&#xff0c;需用到哪些测试工具和仪器设备呢&#xff1f; 一&#xff0c;网络流量的监控和过滤能力测试&am…

uniapp 常见的问题以及解决办法

当开发UniApp时&#xff0c;可能会遇到一些常见问题。以下是一些常见问题及其解决办法&#xff1a; 1. 页面或组件无法正常显示 确保页面或组件的路径和文件名的大小写正确。检查模板代码中是否存在错误或不完整的标签闭合。使用调试工具&#xff08;如Chrome开发者工具&…

正点原子嵌入式linux驱动开发——Linux 串口RS232/485/GPS 驱动

串口是很常用的一个外设&#xff0c;在Linux下通常通过串口和其他设备或传感器进行通信&#xff0c;根据 电平的不同&#xff0c;串口分为TTL和RS232。不管是什么样的接口电平&#xff0c;其驱动程序都是一样的&#xff0c;通过外接RS485这样的芯片就可以将串口转换为RS485信号…

Java之数据类型与变量

目录 1. 字面常量 2. 数据类型 3. 变量 3.1 变量概念 3.2 语法格式 3.3 整型变量 3.3.1 整型变量 3.3.2 长整型变量 3.3.3 短整型变量 3.3.4 字节型变量 3.4 浮点型变量 3.4.1 双精度浮点型 3.4.2 单精度浮点型 3.5 字符型变量 3.6 布尔型变量 3.7 类型转换 3.7…

中微爱芯74逻辑兼容替代TI/ON/NXP工规品质型号全

这里写自定义目录标题 工业级型号全产品线概述![在这里插入图片描述](https://img-blog.csdnimg.cn/097ef810b2234f07b0c0c1e962a73761.png)批量应用行业头部客户兼容替代封装对照逻辑参数对比电平转换系列型号对照HC/HCT 系列型号对照AHC/AHCT 系列型号对照LV/LVC 系列型号对照…