> 文档中心 > 学习C语言常见常用函数与模拟【深层理解】

学习C语言常见常用函数与模拟【深层理解】


函数快速查找


文章目录

  • 函数快速查找
  • 前言
  • 一、strlen与模拟实现
    • 模拟实现
  • 二、strcpy与模拟实现
    • 模拟实现
  • 三、strcat
    • 模拟实现
  • 四、strcmp与模拟实现
    • 模拟实现
  • 五、strstr与模拟实现
    • 模拟实现
  • 六、strncpy
  • 七、strncat
  • 八、strncmp
  • 九、strtok
  • 十、strerror
  • 十一、memcpy
    • 模拟实现
  • 十二、memmove与模拟实现
    • 模拟实现
  • 总结

前言

本文收录了初学C语言时常见的有关字符串函数简介以及个别模拟实现,这些函数大大方便了编程工作,是收藏的不二选择


一、strlen与模拟实现

size_t strlen(const char * str);

字符串会以‘\0’作为结束标志,strlen则会返回’\0’以前出现的字符个数,(不包含\0).

  • 字符串须以‘\0’为结束标志,否则会出现找不到\0返回随机值的情况
  • 注意返回值为size_t,即unsigned int

模拟实现

1.指针-指针

int my_strlen(char *s){char *p = s;while(*p != ‘\0)p++;return p-s;}

2.计数器

int my_strlen(char* p){int count = 0;while (*p++){count++;}return count;}

3.不允许创建临时变量时常常采用递归

//不能创建临时变量计数器int my_strlen(const char * str){if(*str == '\0')return 0;elsereturn 1+my_strlen(str+1);}

二、strcpy与模拟实现

char* strcpy(char * destination, const char * source);
  • 源字符串即待拷贝字符串,必须以’\0‘结束
  • 会将源字符串中的’\0’拷贝到目标字符串
  • 目标空间需要足够大,来确保能够存放源字符串.
  • 目标空间必须可变

模拟实现

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

三、strcat

char * strcat ( char * dest, const char * sour);
  • 源字符串必须以’\0’为结束。
  • 目标空间足够大。
  • 目标空间可修改.
  • 注意不可字符串自己给自己追加,会出现目标空间不足的情况
    在这里插入图片描述

模拟实现

char* my_strcat(char* arr, const char* arr1){char* ret = arr;assert(arr && arr1);while (*arr){arr++;}while ((*arr++ = *arr1++)){;}return ret;}

四、strcmp与模拟实现

int strcmp ( const char * str1, const char * str 2);
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,返回小于0的数字
  • 字符串比较时,对应位置一一比较

模拟实现

int my_strcmp(const char* p, const char* p1){int ret = 0;assert(p && p1);while (!(ret = *p - *p1) && p1){*++p;*++p1;}if (ret > 0){return 1;}else if (ret < 0){return -1;}}

更为严谨

int my_strcmp (const char * src, const char * dst){int ret = 0 ;assert(src != NULL);assert(dest != NULL);while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)++src, ++dst;if ( ret < 0 )ret = -1 ;else if ( ret > 0 )ret = 1 ;return( ret );}

五、strstr与模拟实现

char * strstr ( const char *str1, const char * str2);
  • 寻找子集,看str1中是否存在str2.
  • 若存在,返回str1中出现str2的地址
  • 若不存在,返回NULL

模拟实现

char * strstr (const char * str1, const char * str2){char *cp = (char *) str1;char *s1, *s2;if ( !*str2 )return((char *)str1);while (*cp){s1 = cp;s2 = (char *) str2;while ( *s1 && *s2 && !(*s1-*s2) )s1++, s2++;if (!*s2)return(cp);cp++;}return(NULL);

六、strncpy

char * strncpy(char * dest, const char * sour, size_t num);
  • 拷贝num个字符从源字符串到目标空间.
  • 如果源字符串的长度小于num,则拷贝完字符串之后,在目标后边加0,直到num个.

七、strncat

char * strncat( char * dest, const char * sour, size_t num);
int main (){char str1[20];char str2[20];strcpy (str1,"To be ");strcpy (str2,"or not to be");strncat (str1, str2, 6);puts (str1);return 0;}

在这里插入图片描述

八、strncmp

int strncmp ( const char * str1, const char * str2, size_t num);
  • 比较出现不一样的字符
  • 一个字符串结束
  • num个字符全部比完
    在这里插入图片描述

九、strtok

char * strtok (char * str, comnst char * sep)
  • sep 是个字符串,定义了用作分隔符的字符集合
  • 第一个参数是字符串,包含了0个或多个sep中的一个或者多个分隔符分割的标记
  • 函数会找到str中的下一个标记,用\0结尾,返回一个指向这个标记的指针(由此可见,会改变字符串,须先进行临时拷贝)
  • 函数第一个参数不为NULL,找到第一个标记,函数会保存他在字符串中的位置
  • 第一个参数是NULL,将在被保存的位置开始,寻找下一个标记
  • 当没有标记,返回NULL
#include int main(){char *p = "zhangpengwei@bitedu.tech";const char* sep = ".@";char arr[30];char *str = NULL;strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容for(str=strtok(arr, sep); str != NULL; str=strtok(NULL, sep)){printf("%s\n", str);}}
int main (){char str[] ="- This, a sample string.";char * pch;printf ("Splitting string \"%s\" into tokens:\n",str);pch = strtok (str," ,.-");while (pch != NULL){printf ("%s\n",pch);pch = strtok (NULL, " ,.-");}return 0;}
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsimport warningswarnings.filterwarnings('ignore')import  sslssl._create_default_https_context = ssl._create_unverified_context

十、strerror

char * strerror (int errnum);

在这里插入图片描述

代码如下(示例):

#include #include #include //必须包含的头文件int main (){FILE * pFile;pFile = fopen ("unexist.ent","r");if (pFile == NULL)printf ("Error opening file unexist.ent: %s\n",strerror(errno));//errno: Last error numberreturn 0;}
data = pd.read_csv(    'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')print(data.head())

字符分类函数

函数 如果他的参数符合下列条件就返回真
iscntrl 任何控制字符
isspace 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit 十进制数字 0~9
isxdigit 十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F
islower 小写字母a~z
isupper 大写字母A~Z
isalpha 字母a-z或A-Z
isalnum 字母或者数字,a-z,A-Z,0-9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符

十一、memcpy

void * memcpy( void * dest, const void * sour, size_t num)
  • 函数从sour的位置开始向后复制num个字节数据到dest的内存位置
  • 遇到’\0’并不会停下来
  • 不管有任何重叠,复制的结果是未定义的

模拟实现

void * memcpy ( void * dst, const void * src, size_t count){void * ret = dst;assert(dst);assert(src);/** copy from lower addresses to higher addresses*/while (count--) {*(char *)dst = *(char *)src;dst = (char *)dst + 1;src = (char *)src + 1;}return(ret);}

十二、memmove与模拟实现

void * memmove ( void * dest, const void * sour, size_t num);
  • 和memcpy的区别是memmove函数处理的源内存块和目标内存块是可以重叠的
  • 如果出现重叠,就使用memmove

模拟实现

void* my_memmove(void* s1, const void* s2, size_t count){void* ret = s1;assert(s1 && s2);if (s1 < s2){while (count--){*(char*)s1 = *(char*)s2;     s1 = (char*)s1 + 1;s2 = (char*)s2 + 1;}}else{while (count--){*((char*)s1 + count) = *((char*)s2 + count);}}return ret;}

总结

以上就是今天要讲的内容,本文集锦好多了有趣有用常见的函数,是不是助学神器呢~~~

支持一下喽