> 文档中心 > 【C进阶】Three -> 字符函数(万字讲解,不明白,就来找我。)

【C进阶】Three -> 字符函数(万字讲解,不明白,就来找我。)


 ⭐前言

※※※大家好!我是同学〖森〗,一名计算机爱好者,今天让我们进入学习模式。若有错误,请多多指教。

👍 点赞  收藏 📝留言 都是我创作的最大的动力!


 ⭐往期真集

【C进阶】 【C进阶】two -> 指针进阶练习(三)
【C进阶】 【C进阶】two -> 指针进阶(二)
【C进阶】 【C进阶】two -> 指针进阶
【C进阶】 【C进阶】 one -> 数据的存储

⭐思维导图⭐


 

⭐目录⭐

 ⭐前言⭐

⭐往期真集⭐

⭐思维导图⭐

⭐目录⭐

1.strlen

1.1strlen函数的简介

 1.2strlen函数的克隆

2.strcpy

2.1strcpy函数的简介

2.2合格程序员不得不知的4个点

2.3strcpy函数的克隆 

2.4strncpy函数的简介

3.strcat

3.1strcat函数的简介

3.2那字符串自己给自己追加呢? 

3.3 strcat函数的克隆

3.4strncat函数的简介

4.strcmp

4.1strcmp函数的简介

4.2strcmp函数的克隆

4.3strncmp函数的简介

5.strstr

5.1strstr函数的简介

5.2strstr函数的克隆

 6.strtok

6.1strtok函数的简介

6.2strtok函数的注意事项

7.strerror

7.1strerror函数的简介

8.字符分类函数

9.字符转换

10.memcpy

10.1memcpy函数的简介

10.2memcpy函数的克隆

11.memmove

11.1memmove函数的简介

11.2memmove函数的克隆

12.memcmp 

12.1memcmp函数的简介

13.memset

13.1memset函数的简介


1.strlen

1.1strlen函数的简介

链接: strlen

size_t strlen( const char *string );

头文件:

功能:获取字符串长度,返回 C 字符串的长度

参数:c字符串

 返回值:字符串的长度。

例:

 arr数组  

a  b  c  d  e  f  \0

\0前面有6个字符,所以 ret = 6。

字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。

参数指向的字符串必须要以 '\0' 结束。

注意函数的返回值为size_t,是无符号的( 易错 )

 如上例:

若你以为strlen的返回值是有符号整形的话应该打印<=号。

正因为strlen的返回值是无符号整形,把-3的补码认为是一个无符号型的数,即非常大的正数。

 1.2strlen函数的克隆

#include//方法一:计数器方式size_t my_strlen1(const char* str){assert(str != NULL);//断言,str为空时报错。size_t count = 0;while(*str++ != '\0'){count++;}return count;}//方法二:递归(不能创建临时变量)size_t my_strlen2(const char* str){assert(str != NULL);//断言,str为空时报错。if (*str == '\0'){return 0;}else{return 1 + my_strlen2(str + 1);}}//方法三:指针-指针的方式size_t my_strlen3(const char* str){assert(str != NULL);//断言,str为空时报错。char* p = str;while (*p != '\0'){p++;}return p - str;}

2.strcpy

2.1strcpy函数的简介

strcpy

char * strcpy ( char * destination, const char * source );

头文件:

功能:复制字符串

所指向的 C 字符串复制到目标所指向的数组中,包括终止空字符(并在该点停止)。
为避免溢出,目标所指向的数组的大小应足够长,以包含与相同的 C 字符串(包括终止空字符),并且内存中不应与重叠。

参数:

char * destination:指向要复制内容的目标数组的指针。

const char * source:要复制的 C 字符串。

返回值:返回目标空间的起始地址。为了实现链式访问。

Each of these functions returns the destination string. No return value is reserved to indicate an error

例:

2.2合格程序员不得不知的4个点

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

 若字符数组结尾没有‘\0’

 若字符素组结尾有‘\0’

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

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

4、目标空间必须可变 

程序会崩溃。 

2.3strcpy函数的克隆 

char* MyStrcpy(char* strTarget, const char* strSource){assert(strTarget && strSource);//断言char* ret = strTarget;while (*strTarget++ = *strSource++)   //复制{;}return ret;}

while (*strTarget++ = *strSource++)

先将*strSource赋值给*strTarget,然后再++,即指针后移,并且判断*strTarget的内容是不是'\0'.是循环结束,不是继续执行第一步。


2.4strncpy函数的简介

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

头文件:

功能:从字符串中复制字符

的前 num 个字符复制到目标。如果在复制 num 个字符之前找到 C 字符串(由空字符指示)的末尾,则目标将填充零,直到向其写入总共 num 个字符。如果的长度过 num,则不会在目标末尾隐式追加空字符。因此,在这种情况下,目标不应被视为以空值结尾的 C 字符串(这样读取它会溢出)。
目的地来源不得重叠

参数:

char * destination:指向要复制内容的目标数组的指针。

const char * source:要复制的 C 字符串。

size_t num:要从复制的最大字符数。
size_t是无符号整数类型。

返回值:返回目标空间的起始地址。为了实现链式访问。

比strcpy多了一个功能,即能控制复制的字符数;

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

例:


3.strcat

3.1strcat函数的简介

char * strcat ( char * destination, const char * source );

头文件:

功能:连接字符串

字符串的副本追加到目标字符串。目标中终止的空字符将被的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符。
目的地来源不得重叠。

参数:

char * destination:指向目标数组的指针,该数组应包含 C 字符串,并且足够大以包含串联的结果字符串。

const char * source:要追加的 C 字符串。这不应与目标重叠。

返回值:返回目标空间的起始地址。为了实现链式访问。

例:

1、 Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination. 2、 源字符串和目标字符串必须以 '\0' 结束。 3、 目标空间必须有足够的大,能容纳下源字符串的内容。 4、 目标空间必须可修改。

3.2那字符串自己给自己追加呢? 

#include#includeint main(){char arr1[50] = "I love ";//char arr2[] = "China!";strcat(arr1, arr1);puts(arr1);return 0;}

 由于字符串中的'\0'被覆盖,导致程序一直拷贝字符串。程序崩溃。

3.3 strcat函数的克隆

char* MyStrcat(char* strDestination, const char* strSource){assert(strDestination && strSource);char* ret = strDestination;while (*strDestination)//找到'\0'{strDestination++;}while (*strDestination++ = *strSource++) //复制{;}return ret;}

3.4strncat函数的简介

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

头文件:

功能:从字符串追加字符

的前 num 个字符追加到目标,外加一个终止空字符。

如果中 C 字符串的长度小于 num,则仅复制直至终止空字符的内容。

参数:

char * destination:指向目标数组的指针,该数组应包含 C 字符串,并且足够大以包含串联的结果字符串,包括附加的 null 字符。

const char * source:要追加的 C 字符串。

size_t num:要追加的最大字符数。
size_t是无符号整数类型。

由图可知:

拷贝相对应的字符串后会在后面加‘\0’

4.strcmp

4.1strcmp函数的简介

int strcmp ( const char * str1, const char * str2 );

头文件:

功能:比较两个字符串

将 C 字符串 str1 与 C 字符串 str2 进行比较
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同或达到终止空字符。此函数执行字符的二进制比较。

参数:

const char * str1:要比较的 C 字符串。

const char *str2:要比较的 C 字符串。

返回值:

例:

#include#includeint main(){char arr1[] = "abcdef";char arr2[] = "acq";int ret = strcmp(arr1, arr2);if (ret > 0){printf("arr1 > arr2\n");}else if (ret < 0){printf("arr1 < arr2\n");}else{printf("arr1 = arr2\n");}printf("ret = %d\n", ret);return 0;}

 4.2strcmp函数的克隆

int MyStrcmp(const char* str1, const char* str2){assert(str1 && str2);while (*str1++ == *str2++){if (*(str1)  *(str2)){return 1;}elsereturn 0;}}

 4.3strncmp函数的简介

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

头文件:

功能:比较两个字符串的字符

将 C 字符串 str1 的最多 num 个字符与 C 字符串 str2 的字符数进行比较。
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同,直到达到终止空字符,或者直到两个字符串中的数字字符匹配,以先发生者为准。

参数:

const char * str1:要比较的 C 字符串。

const char * str2:要比较的 C 字符串。

size_t num 要比较的最大字符数。 size_t 是无符号整数类型。
 

返回值:

例: 

 

5.strstr

5.1strstr函数的简介

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

头文件:

功能:定位子字符串

返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回空指针。

匹配过程不包括终止空字符,但它就此停止。

参数:

const char * str1: 要扫描的 C 字符串。

const char * str2: 包含要匹配的字符序列的 C 字符串。

返回值指向 str1 中首次出现的 str2 中指定的整个字符序列的指针,如果序列在 str1 中不存在,则为空指针。

例:

5.2strstr函数的克隆

char* MyStrstr(const char* str1, const char* str2){    assert(str1 && str2);//断言char* p1 = str1;char* p2 = str2;char* cur = str1;while (*cur){p1 = cur;p2 = str2;while (*p1 && *p2 && (*p1 == *p2))//若两个指针所指向的字符相等,指针向后移动。{p1++;p2++;}if (*p2=='\0')//表示需要比较的字符串已经比较完,返回第一个字母的地址。{return cur;}cur = p1;cur++;}return NULL;//没找到返回空指针。}

 6.strtok

6.1strtok函数的简介

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

头文件:

功能:将字符串拆分为标记

对此函数的调用序列将 str 拆分为标记,这些标记是由分隔的任何字符分隔的连续字符序列。

在第一次调用时,该函数需要一个 C 字符串作为 str 的参数,其第一个字符用作扫描令牌的起始位置。在后续调用中,该函数需要一个空指针,并使用最后一个标记末尾的位置作为扫描的新起始位置。

为了确定令牌的开头和结尾,该函数首先从起始位置扫描分隔包含的第一个字符(这将成为令牌的开头)。然后从令牌的开头开始扫描分隔符中包含的第一个字符,这将成为令牌的结尾。如果找到终止空字符,扫描也会停止。令牌的此末尾将自动替换为空字符,令牌的开头由函数返回。

在对 strtok 的调用中找到 str 的终止空字符后,对此函数的所有后续调用(以空指针作为第一个参数)都将返回空指针。

找到最后一个令牌的点由要在下一次调用时使用的函数保留在内部(不需要特定的库实现来避免数据争用)。

参数:

str:要截断的 C 字符串。
请注意,此字符串通过分解为较小的字符串(标记)进行修改。
或者,可以指定空指针,在这种情况下,函数将继续扫描上一次成功调用该函数结束的位置。

delimiters:包含分隔符字符的 C 字符串。这些呼叫可能因呼叫而异。

返回值:

如果找到令牌,则为指向令牌开头的指针。否则,为空指针
当在所扫描的字符串中达到字符串的末尾(即空字符)时,始终返回空指针

例:

#include#includeint main(){char str[] = "- This, a sample string.";char str1[30];strcpy(str1, str);char sep[] = " -,.";char* pch;printf("Splitting string \"%s\" into tokens:\n", str);pch = strtok(str1, sep);//只找第一个标记while (pch != NULL)//pch为NULL时表示没有标识的字符。{printf("%s\n", pch);//打印pch = strtok(NULL, sep);//是从保存好的位置开始继续向后找}return 0;}

6.2strtok函数的注意事项

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

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

3、strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。

(注: strtok函数会改变被操作的字符串,所以在使用 strtok 函数切分的字符串一般都是临时拷贝的内容并且可修改。)4、 strtok 函数的第一个参数不为 NULL ,函数将找到 str 中第一个标记, strtok 函数将保存它在字符串 中的位置。5、 strtok 函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。6、如果字符串中不存在更多的标记,则返回 NULL 指针。

7.strerror

7.1strerror函数的简介

char * strerror ( int errnum );

头文件:

功能:获取指向错误消息字符串的指针

解释 errnum 的值,生成一个字符串,其中包含一条描述错误条件的消息,就好像库的函数设置为 errno 一样。
返回的指针指向静态分配的字符串,程序不得修改该字符串。对此函数的进一步调用可能会覆盖其内容(不需要特定的库实现来避免数据争用)。
strerror 生成的错误字符串可能特定于每个系统和库实现。

参数:

errnum:错误编号。

返回值:指向描述错误的错误字符串的指针。

例:

8.字符分类函数

字符分类函数
函数 如果他的参数符合下列条件就返回真
iscntrl 检查字符是否为控制字符
isspace 检查字符是否为空格
isdigit 检查字符是否为十进制数字
isxdigit 检查字符是否为十六进制数字
islower 检查字符是否为小写字母
isupper 检查字符是否为大写字母
isalpha 检查字符是否按字母顺序排列
isalnum 检查字符是否为字母数字
ispunct 检查字符是否为标点字符
isgraph 检查字符是否具有图形表示
isprint 检查字符是否可打印

9.字符转换:

字符转换
tolower 将大写字母转换为小写字母
toupper 将小写字母转换为大写字母

10.memcpy

10.1memcpy函数的简介

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

头文件:

功能:复制内存块

将 num 字节值从指向的位置直接复制到目标所指向的内存块。

指针和目标指针所指向的对象的基础类型与此函数无关。结果是数据的二进制副本。

该函数不检查中是否有任何终止空字符 - 它始终精确地复制数字字节。

为避免溢出,目标参数和参数所指向的数组的大小应至少为 num 字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)。

参数:

destination:指向要在其中复制内容的目标数组的指针,以类型转换为 void* 类型的指针。

source:指向要复制的数据源的指针,类型转换为 const void* 类型的指针。

num:要复制的字节数。size_t 是无符号整数类型。

返回值:返回destination
 

例:

#include #include struct {char name[40];int age;} person, person_copy;int main(){char myname[] = "Pierre de Fermat";/* using memcpy to copy string: */memcpy(person.name, myname, strlen(myname) + 1);person.age = 46;/* using memcpy to copy structure: */memcpy(&person_copy, &person, sizeof(person));printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);return 0;}

 输出:

 10.2memcpy函数的克隆

#includevoid* MyMemcpy(void* destination, const void* source, size_t num){assert(destination && source);//要引用头文件void* ret = destination;while (num--){*(char*)destination = *(char*)source;destination = (char*)destination + 1;source = (char*)source + 1;}return ret;}

输出:

11.memmove

11.1memmove函数的简介

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

头文件:

功能:移动内存块

将 num 字节的值从所指向的位置复制到目标所指向的内存块。复制就像使用中间缓冲区一样进行,允许目标重叠。

指针和目标指针所指向的对象的基础类型与此函数无关;结果是数据的二进制副本。

该函数不检查中是否有任何终止空字符 - 它始终精确地复制数字字节。

为避免溢出,目标参数和参数所指向的数组的大小应至少为 num 字节。

参数:

destination:指向要在其中复制内容的目标数组的指针,以类型转换为 void* 类型的指针。

source:指向要复制的数据源的指针,类型转换为 const void* 类型的指针。

num:要复制的字节数。size_t是无符号整数类型。

返回值:返回destination的地址。

memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

如果源空间和目标空间出现重叠,就得使用memmove函数处理。

例: 

 

11.2memmove函数的克隆

void * MyMemmove(void* destination, const void* source, size_t num){assert(destination && source);void* ret = destination;if (destination < source){while (num--){//从前向后拷贝。*(char*)destination = *(char*)source;destination = (char*)destination + 1;source = (char*)source + 1;}}else{while (num--){//从后向前拷贝。*((char*)destination + num) = *((char*)source + num);}}return ret;}

输出:

12.memcmp 

12.1memcmp函数的简介

 memcpy

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

头文件:

功能:比较两个内存块

将 ptr1 所指向的内存块的第一个字节数与 ptr2 所指向的第一个字节数进行比较,如果它们全部匹配,则返回零,或者返回一个与零不同的值,表示如果不匹配,则哪个值更大。

请注意,与 strcmp 不同,该函数在找到空字符后不会停止比较。

参数:

ptr1:指向内存块的指针。

ptr2:指向内存块的指针。

num:要比较的字节数。

返回值:

#include #include int main(){char buffer1[] = "DWgaOtP12df0";char buffer2[] = "DWGAOTP12DF0";int n;n = memcmp(buffer1, buffer2, sizeof(buffer1));if (n > 0) printf("'%s' is greater than '%s'.\n", buffer1, buffer2);else if (n < 0) printf("'%s' is less than '%s'.\n", buffer1, buffer2);else printf("'%s' is the same as '%s'.\n", buffer1, buffer2);return 0;}

输出:

13.memset

13.1函数的简介

memset

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

头文件:

功能:填充内存块

将 ptr 指向的内存块的第一个字节数设置为指定的(解释为无符号字符)。

参数:

ptr:指向要填充的内存块的指针。

value:要设置的值。该值作为 int 传递,但该函数使用此无符号字符转换填充内存块。

num:要设置为该的字节数。size_t是无符号整数类型。

返回值:ptr 将返回。

例:

 

 

365PC电脑装机网