目录
前言
在平时我们处理一些数据时,尤其是字符串,我们经常会用到库函数中的strlen、strcmp等,C语言本身是没有字符串类型的,字符串通常放在常量字符串和字符数组中。
(1)函数头部
size_t strlen( const char *string );
(2)注意事项
- 字符串以 '\0'作为结束标志,strlen函数返回的是在字符串'\0'前面出现的字符的个数(不含\0)
- 参数指向的字符串必须要以\0结束
- 函数的返回值是类型是 size_t 这是无符号整型(易错)
+
(3)strlen的使用
- #include
- #include
- int main()
- {
- char* str = "abcef";
- int len = strlen(str);//获取字符串的长度
- printf("%d",len);
- return 0;
- }
(4)strlen的模拟实现
- //普通实现
- #include
- int my_strlen(char *str)
- {
- int count = 0;
- while (*str++)
- count++;
- return count;
- }
- int main()
- {
- char* str = "abcdef";
- int len = my_strlen(str);
- printf("%d",len);
- return 0;
- }
//链式访问实现
- #include
- int my_strlen(char *str)
- {
- int count = 0;
- while (*str++)
- count++;
- return count;
- }
- int main()
- {
- char* str = "abcdef";
- printf("%d",my_strlen(str));//链式访问
- return 0;
- }
//函数递归实现
- #include
- int my_strlen(char* str)
- {
- if (*str == '\0')
- return 0;
- else
- return (1 + my_strlen(str + 1));
- }
- int main()
- {
- char* str = "abcdef";
- int len = my_strlen(str);
- printf("%d",len);
- return 0;
- }
//指针-指针实现
- //指针- 指针
- #include
- int my_strlen(char*str)
- {
- char* end = str;
- while (*end)
- end++;
- return end - str;
- }
- int main()
- {
- char* str = "abcdef";
- int len = my_strlen(str);
- printf("%d",len);
- return 0;
- }
(1)函数头部
char *strcpy( char *strDestination, const char *strSource );
(2)注意事项
- 源字符串以'\0'结束。
- 会将源字符串的’\0‘拷贝的目标空间
- 目标空间必须足够大,以保证能放下源字符串
- 目标空间必须可变
(3)strcpy的使用
- #include
- #include
- int main()
- {
- char str1[20] = {0};
- char* str2 = "abcdef";
- strcpy(str1,str2);
- printf("%s",str1);
- return 0;
- }
- #include
- #include
- char* my_strcpy(char* str1, const char* str2)
- {
- assert(str1&&str2);//断言避免指针为空
- char* ret = str1;
- while (*str1++ = *str2++)
- ;
- return ret;
- }
- int main()
- {
- char str1[20] = { 0 };
- char* str2 = "abcdef";
- printf("%s", my_strcpy(str1, str2));
- return 0;
- }
(1)函数头部
char *strcat( char *strDestination, const char *strSource );
(2)注意事项
- 源字符必须以‘\0’结束
- 目标空间必须有足够大能容纳下源字符串
- 目标空间必须可以修改
- strcat不能自己给自己追加
(3)strcat的使用
- //strcat的使用
- #include
- #include
- int main()
- {
- char str1[20] = "abcdef";
- char* str2 = "112233";
- strcat(str1,str2);
- printf("%s",str1);
- return 0;
- }
(4)strcat的模拟实现
- #include
- #include
- char* my_strcat(char*dest,const char*src)
- {
- char* ret = dest;
- while (*dest)
- dest++;
- while (*dest++ = *src++)
- ;
- return ret;
- }
- int main()
- {
- char str1[20] = "abcdef";
- char* str2 = "112233";
- my_strcat(str1, str2);
- printf("%s", str1);
- return 0;
- }
(1)函数头部
int strcmp( const char *string1, const char *string2 );
(2)注意事项
- 根据标准规定
- 第一个字符串 大于 第二个字符串,返回大于0的数字
- 第一个字符串 等于 第二个字符串 ,返回0
- 第一个字符串 小于 第二个字符串,返回小于0的数字
(3)strcmp的使用
- #include
- #include
- int main()
- {
- char* str1 = "abcdef";
- char* str2 = "aaaaaa";
- int ret = strcmp(str1,str2);//可以知道 str1>str2
- printf("%d",ret);//编译器返回一个大于0的数字
- return 0;
- }
(4)strcmp的模拟实现
- #include
- #include
- int my_strcmp(const char*str1,const char*str2)
- {
- assert(str1&&str2);
- while (*str1 == *str2)
- {
- if (*str1 == '\0')
- return 0;
- str1++;
- str2++;
- }
- return (*str1 - *str2);
- }
- int main()
- {
- char* str1 = "abcdef";
- char* str2 = "aaaaaa";
- int ret = my_strcmp(str1, str2);
- printf("%d", ret);
- return 0;
- }
我们发现上述字符串函数 的字符串长度不受到限制
接下来介绍几个长度受到限制的字符串函数
(1)函数头部
char *strncpy( char *strDest, const char *strSource, size_t count );
(2)注意事项
- 拷贝count个字符从源字符串到目标空间
- 如果源字符小于count,则考完源字符串后,在目标的后面追加0,直到count个
(3)strncpy的使用
- #include
- #include
- int main()
- {
- char str1[20] = "aa";
- char str2[] = "bbb";
- strncpy(str1,str2,5);
- printf("%s",str1);
- return 0;
- }
接下来我们一下调试的内容
(1)函数头部
char *strncat( char *strDest, const char *strSource, size_t count );
(2)注意事项
- 当源字符串小于count,并不会一直追加,而是追加完字符串的时候再加上‘\0’,目标是完成源字符串内容
- 当等于count,会再追加一个上‘\0’
- 没有额外追加
(3)strncat的使用
- //strncat的使用
- #include
- #include
- int main()
- {
- char str1[20] = "aaa";
- char* str2 = "bbc";
- strncat(str1,str2,3);
- printf("%s",str1);
- return 0;
- }
(1)函数头部
int strncmp( const char *string1, const char *string2, size_t count );
(2)注意事项
- 比较到出现另一个字符不一样,或者一个字符串结束,或者count个字符全部比较完
< 0 不匹配的第一个字符在 str1 中的值低于 str2 中的值
0 两个字符串的内容相等
>0 第一个不匹配的字符在str1中的值比在str2中的值大
(3) strncmp的使用
- //strncmp的使用
- #include
- #include
- int main()
- {
- char* str1 = "aaab";
- char* str2 = "abba";
- int len = strncmp(str1,str2,2);//比较前两个字符
- printf("%d",len);
- return 0;
- }
(1)函数头部
char *strstr( const char *str1, const char *str2 );
(2)注意事项
在str1中找 str2在(str1)第一次出现的位置
(3)strstr的使用
- #include
- #include
- int main()
- {
- char* str1 = "abcxaxad";
- char* str2 = "xax";
- char* ret = strstr(str1,str2);
- printf("%s",ret);
- return 0;
- }
(4)strstr模拟实现
- //strstr的模拟实现
- #include
- #include
- char* my_strstr(const char* str1,const char* str2)
- {
- assert(str1&&str2);
- char* cp = str1;
- char* p1 = str1;
- char* p2 = str2;
- while (cp)
- {
- p1 = cp;//从cp指向的字符开始
- p2 = str2;//从子串的首字符开始
- while (*p1 == *p2 && *p1 && *p2)
- {
- p1++;
- p2++;
- }
- if (*p2 == '\0')
- return cp;
- cp++;
- }
- return NULL;
-
- }
- int main()
- {
- char* str1 = "abcxaxad";
- char* str2 = "xax";
- char* ret = my_strstr(str1,str2);
- printf("%s",ret);
- return 0;
- }
图解:
起始情况
找到的时候
(1)函数头部
char *strtok( char *str, const char *sep );
(2)注意事项
- sep 参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记
- 如果字符串中不存在更多的标记,则返回 NULL 指针
(3)strtok的使用 ( 把字符串根据 分隔符 分隔开来)
- #include
- #include
- int main()
- {
- char* p = "aabbcc@112233.abc";
- const char* sep = "@.";
- char arr[30];
- char* str = NULL;
- strcpy(arr,p);//临时拷贝字符串
- for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
- printf("%s\n",str);
- return 0;
- }
返回错误码,所对应的错误信息(这里是程序运行时的错误)
在介绍其他知识:库函数在执行时,发生了错误,会将一个错误码存到errno这个变量中(全局变量)
(1)函数头部
char * strerror( int errnum );
(2)strerror的使用
- #include
- #include
- #include
- int main()
- {
- int i = 0;
- for (i = 0; i < 10;i++)
- {
- printf("%d is %s\n",i,strerror(i));//打印错误码 0到9的错误信息
- }
- }
iscntr | 任何控制字符 |
isspace | 空白字符: 空格 ' ',换页 ‘\f,换行 '\n',回车 '\r' ,制表符 ‘\t’,垂直制表符 ‘\v’ |
isdigit | 十进制数字 0 - 9 |
isxdigit | 十六进制数字 0 - 9 ,a - f |
islower | 小写字母 a- z |
isupper | 大写字母 A - Z |
isalpha | 字母 a - z , A - Z |
isalnum | 字母或者数字 a - z , A - Z,0 - 9 |
ispunct | 标点符号,任何不属于字母和数字的图形字符 |
isgragh | 任何图形字符 |
isprint | 可以打印任何字符 |
根据上述字符函数,【例如】islower(a) 如果圆括里面的是小写字母,该函数就返回真。
(1)函数头部
void *memcpy( void *dest, const void *src, size_t count );
(2)注意事项
- 函数memcpy从source的位置开始向后复制count个字节的数据到destination的内存位置
- 这个函数在遇到 '\0' 的时候并不会停下来
- 用来处理不重叠的内存拷贝,如果source和destination有任何的重叠,复制的结果都是未定义的
- size_t count 是 字节的个数
(3)memcpy的使用
- #include
- #include
- int main()
- {
- int arr1[] = {1,2,3,4,5};
- int arr2[20] = {0};
- //将arr1中的内容拷贝到arr2中
- memcpy(arr2,arr1,20);
- int i = 0;
- for (i = 0; i < 20;i++)
- {
- printf("%d ",arr2[i]);
- }
- return 0;
- }
(4)memcpy的模拟使用
- //memcpy的模拟实现
- #include
- #include
- void* my_memcpy(void* dest, const void *src ,size_t count)
- {
- assert(dest && src);
- void* ret = dest;
- while (count--)//count表示的是字节的个数
- {
- //因为char类型是占一个字节
- *(char*)dest = *(char*)src;
- dest = (char*)dest + 1;
- src = (char*)src + 1;
- }
- return dest;
- }
- int main()
- {
- int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
- int arr2[20] = {0};
- my_memcpy(arr2,arr1,40);
- int i = 0;
- for (i = 0; i < 20;i++)
- {
- printf("%d ",arr2[i]);
- }
- return 0;
- }
(1)函数头部
void *memmove( void *dest, const void *src, size_t count );
(2)注意事项
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
- 如果源空间和目标空间出现重叠,就是可以使用memmove进行处理
- 用重叠的内存拷贝
(3)memmove的使用
- #include
- #include
- int main()
- {
- //这里我们给str自己拷贝一个123
- char str[] = "web online 123";
- memmove(str, str + 11,3);//可以用于重叠内存拷贝
- printf("%s",str);
- return 0;
- }
(4)memmove的模拟实现
- //memmove的模拟实现
- #include
- #include
- void* my_memmove(void* dest,const void* src,size_t num)
- {
- assert(dest&&src);
- void* ret = dest;
- //当地址src 小于 dest的时候
- if (dest < src)
- {
- //这里我们src从前到后移动
- //前->后
- while (num--)
- {
- *(char*)dest = *(char*)src;
- dest = (char*)dest + 1;
- src = (char*)src + 1;
- }
- }
- else
- {
- while (num--)
- {
- *((char*)dest + num) = *((char*)src + num);
- }
-
- }
- return ret;
- }
- int main()
- {
- int arr1[] = {1,2,3,4,5,6,7,8,9,10};
- my_memmove(arr1, arr1 + 2,12);//前->后
- //my_memmove(arr1+5,arr1+2,12);//后->前
- int i = 0;
- for (i = 0; i < 10;i++)
- {
- printf("%d ",arr1[i]);
- }
- return 0;
- }
前->后
后->前
情况1
情况2
(1)函数头部
int memcmp( const void *buf1, const void *buf2, size_t count );
(2)注意事项
- 比较从buf1 和 buf2 指针开始的num个字节
The memcmp function compares the first count bytes of buf1 and buf2 and returns a value indicating their relationship.
注意该函数的return value
(3)memcmp的使用
- //memcmp的使用
- #include
- #include
- int main()
- {
- char buf1[] = "aabbcc2210";
- char buf2[] = "aabbcc2211";
- int n = 0;
- n = memcmp(buf1,buf2,sizeof(buf1));
- if (n > 0)
- printf("buf1大于buf2");
- else if (n < 0)
- printf("buf1小于buf2");
- else
- printf("buf1等于buf2");
- return 0;
- }