• 常用字符串函数拓展



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

    字符串拓展函数

    strncpy

    函数原型为:

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

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

    strncat

    函数原型为:

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

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

    strncmp

    函数原型为:

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

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

    strstr

    函数原型为:

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

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

    strtok

    函数原型为:

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

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

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

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

    #include 
    #include 
    
    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.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    strerror

    函数原型为:

    char * strerror ( int errnum );
    
    • 1

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

    memcpy

    函数原型为:

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

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

    memmove

    函数原型为:

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

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

    memcmp

    函数原型为;

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

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

    memset

    函数原型为:

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

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

    库函数模拟实现

    memmove

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

    要实现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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    qsort

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

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

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

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

    #include       /* printf */
    #include      /* 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    #include 
    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);
    			 }
    		 }
    	 }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

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

  • 相关阅读:
    HTML学生个人网站作业设计——HTML+CSS+JavaScript优分期大学生分期购物商城(7页)
    【小游戏】2D游戏炸弹超人BombSuperman(无限关卡模式)
    一文详解Web自动化测试
    新版校园跑腿独立版小程序源码 多校版本,多模块,适合跑腿,外卖,表白,二手,快递等校园服务
    玩家们最关心的绝地求生游戏作战秘籍,分享大神干货,助您轻松提升战斗力!
    【学习笔记】各类基于决策单调性的dp优化
    四类取整方式
    阿里云跨账号建立局域网
    车联网安全集智联盟正式成立
    tinymce prism代码高亮图文详解
  • 原文地址:https://blog.csdn.net/m0_74494481/article/details/134088864