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

常用字符串函数拓展

文章目录

  • 字符串拓展函数
    • 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.kler.cn/a/107517.html

相关文章:

  • SHA-256哈希函数
  • Zookeeper的安装与使用
  • Gartner发布安全平台创新洞察:安全平台需具备的11项常见服务
  • 提取神经网络数学表达式
  • 卓胜微嵌入式面试题及参考答案(2万字长文)
  • 文件夹被占用了无法删除怎么办?强制粉碎文件夹你可以这样操作
  • 在本地模拟C/S,Socket套接字的使用
  • 【原创】解决Kotlin无法使用@Slf4j注解的问题
  • 设计模式(13)适配器模式
  • GZ035 5G组网与运维赛题第4套
  • 【Android】一个contentResolver引起的内存泄漏问题分析
  • 通信基础(一):数据传输基础
  • Java工具库——Commons IO的50个常用方法
  • 软考系统架构之案例篇(软件工程相关概念)
  • .net 7 上传文件踩坑
  • 【Python机器学习】零基础掌握DecisionBoundaryDisplay检验、检查
  • SpringMVC Day 05 : Spring 中的 Model
  • react实现步进器
  • flutter升级+生成drift文件
  • hadoop使用简介
  • C# 递归算法使用简介_常用整理
  • Vue引入异步组件
  • STM32F4X SDIO(二) SDIO协议
  • 使用Hystrix实现请求合并,降低服务器并发压力
  • Jquery 如何获取子元素。如何找到所有 HTML select 标签的选中项。jQuery 里的 ID 选择器和 class 选择器有何不同
  • 科聪协作(复合)移动机器人整体解决方案