C语言-字符函数和字符串函数
一、函数介绍
1.1 strlen
求字符串长度函数
size_t strlen(const char* str)
参数和返回值介绍:
const char* str:要求长度的字符串
返回值:返回字符串的长度,类型为无符号整型
1.1.1 字符串以'\0'作为结束标志,strlen函数返回的是字符串中'\0'前面出现的字符个数(不包含'\0')。
1.1.2 指向的字符串必须包含'\0',否则可能会返回随机值。
1.1.3 返回的类型是size_t也就是无符号整型。
strlen的简易模拟实现:
size_t my_strlen(const char* str)
{assert(str);size_t count = 0;while (*str++){count++;}return count;
}
1.2 strcpy
字符串拷贝函数
char* strcpy(char* destination, const char* source)
参数和返回值介绍:
const char* source:源字符串
char* destination:目标空间
返回值:返回目标空间的地址
1.2.1 源字符串必须以'\0'结尾。
1.2.2 会将源字符串中的'\0'拷贝到目标空间中。
1.2.3 目标空间必须足够大,以确保能够存放源字符串。
1.2.4 目标空间必须可变,不能是常量字符串。
strcpy的简易模拟实现:
char* my_strcpy(char* dest, const char* src)
{assert(dest && src);char* tmp = dest;while (*dest++ = *src++){;}return tmp;
}
1.3 strcat
字符串追加函数
char* strcat(char* destinaion, const char* source)
参数和返回值介绍:
const char* source:源字符串
char* destination:目标空间
返回值:返回目标空间的地址
1.3.1 源字符串必须以'\0'结尾。
1.3.2 目标空间必须足够大,能够容纳下源字符串的内容。
1.3.3 目标空间必须可修改。
1.3.4 字符串不能自己给自己追加。
注:当自己给自己追加后src就会永远找不到'\0'的位置,从而停不下来了。
strcat的简易模拟实现:
char* my_strcat(char* dest, const char* src)
{assert(dest && src);char* tmp = dest;while (*dest){dest++;}while (*dest++ = *src++){;}return tmp;
}
1.4 strcmp
字符串比较函数
int strcmp(const char* str1, const char* str2)
参数和返回值介绍:
str1和str2:要进行比较的两个字符串
返回值:当str1>str2时,返回一个大于0的数
当str1<str2时,返回一个小于0的数
当str1和str2相等时,返回0
strcmp的简易模拟实现:
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;
}
1.5 strncpy
指定长度的字符串拷贝函数
char* strcpy(char* destination, const char* source, size_t num)
参数和返回值介绍:
const char* source:源字符串
char* destination:目标空间
size_t num:要拷贝的字符个数
返回值:返回目标空间的地址
1.5.1 拷贝num个字符从源字符串到目标空间。
1.5.2 如果源字符串长度小于num,在拷贝完源字符串后,在目标空间的后面追加0,直到num个。
当源字符串长度小于num时:
strncpy的简易模拟实现:
char* my_strncpy(char* dest, const char* src, size_t num)
{assert(dest && src);char* tmp = dest;int num1 = num;while (num1-- && (*dest++ = *src++)){;}if (num1>0){while (num1--){*dest++ = '\0';}}*dest = '\0';return tmp;
}
1.6 strncat
指定追加字符个数函数
char* strncat(char* destinaion, const char* source, size_t num)
参数和返回值介绍:
const char* source:源字符串
char* destination:目标空间
size_t num:要拷追加的字符个数
返回值:返回目标空间的地址
1.6.1 向目标空间追加n个属于源字符串的字符。
1.6.2 当源字符串长度小于n时,将不在追加,后面直接加一个'\0'。
strncat的简易模拟实现:
char* my_strncat(char* dest, const char* src, size_t num)
{assert(dest && src);char* tmp = dest;while (*dest){dest++;}while (num){*dest++ = *src++;num--;if (*src == '\0'){break;}}*dest = '\0';return tmp;
}
1.7 strncmp
比较前n个字符的大小函数
int strncmp(const char* str1, const char* str2, size_t num)
参数和返回值介绍:
str1和str2:要进行比较的两个字符串
size_t num:要比较的字符个数
返回值:当str1>str2时,返回一个大于0的数
当str1<str2时,返回一个小于0的数
当str1和str2相等时,返回0
strncmp的简易模拟实现:
int my_strncmp(const char* str1, const char* str2, size_t num)
{assert(str1 && str2);while (num && (*str1 == *str2)){num--;str1++;str2++;}//只有num等于0时str1才会和str2的前num个字符相等//否则要么是num还没到0,*str1就和*str2不相等了if (num == 0){return 0;}if (*str1 > *str2){return 1;}else{return -1;}
}
1.8 strstr
字符串找子串函数
char* strstr(const char* str1, const char* str2)
参数和返回值介绍:
str1和str2:在字符串str1中找到str2第一次出现的位置
返回值:找到了就返回str1第一次找到str2后的位置,找不到返回NULL
strstr的简易模拟实现:
char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);char* ch = (char*)str1;char* s1 = NULL;char* s2 = NULL;//结束条件是ch为\0while (*ch){s1 = ch;s2 = (char*)str2;while (*s1&&*s2&&(*s1 == *s2)){s1++;s2++;}//当s2为'\0'时就找到了子串if (*s2 == '\0'){return ch;}ch++;}return NULL;
}
1.9 strtok
分割字符串
char* strtok(char* str, const char* sep)
参数和返回值介绍:
char* str:需要进行分割的字符串
const char* sep:分隔符
1.9.1 sep是一个字符串,定义了用作分隔符的字符合集。
1.9.2 第一个参数指定一个字符串,它包含0个或多个由sep字符串中一个或多个分隔符分割的标记。
1.9.3 strtok会找到str的下一个标记,并将其替换成\0,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝内容,并且可以被修改)
1.9.4 strtok第一个参数不为NULL,strtok函数将找到str中的第一个标记,strtok将保存它在字符串中的位置。
1.9.5 strtok第一个参数为NULL,strtok函数将在同一个字符串中被保存的位置开始,查找下一个标记。
1.9.6 如果字符串中不包含更多标记,将返回NULL。
使用方法:
char arr[] = "helloworld@yeah.net";
char sep[] = "@.";
char tmp[30];
strcpy(tmp, arr);
char* ret = strtok(arr, sep); //第一次传参需要传字符串,最好传一个临时拷贝的字符串
printf("%s\n", ret);
ret = strtok(NULL, sep); //除了第一次需要传字符串之外,剩下的只需要传NULL就行
printf("%s\n", ret);
ret = strtok(NULL, sep);
printf("%s\n", ret);
在不知道具体有多少分隔符时的使用方法:
char arr[] = "helloworld@yeah.net#yyy";
char sep[] = "@.#";
char tmp[30];
strcpy(tmp, arr);
char* ret = NULL;
for (ret = strtok(tmp, sep); ret != NULL;ret=strtok(NULL,sep))
{printf("%s\n", ret);
}
1.10 strerror
库函数在执行的时候如果发生了错误,会将一个错误码存放在errno这个变量中,errno是C语言提供的一个全局变量。
提供错误码,输出错误码对应的错误信息
char* strerror(int errnum)
需要包含的头文件#include<errno.h>
使用方法:
perror相较于strerror来说能够更彻底的打印错误信息。
perror("fopen");
字符串分类函数
头文件:#include<ctype.h>
函数 | 如果判断结果为真就返回一个非0的数,判断结果为假就返回0 |
iscntrl | 任意控制字符 |
isspace | 空格字符:空格' '、换页'\f'、换行'\n'、回车'\r'、制表符'\t'、垂直制表符'\v' |
isdigit | 十进制数字0~9 |
isxdigit | 十六进制数字,包括所有十进制数字0~9,小写字母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 | 任何可打印字符,包括图形字符和空白字符 |
字符转换:
int tolower(int c); //将大写字母转换成小写字母
int toupper(int c); //将小写字母转换成大写字母
1.11 memcpy
内存拷贝函数
void* memcpy(void* destaintion,const void* source,size_t num)
参数和返回值介绍:
void* destaintion:目的地
const void* source:源
size_t num:要拷贝的字节个数
返回值:返回目标空间的起始地址
1.11.1 memcpy从sourec的位置开始向后复制num个字节的数据到destaintion的内存位置。
1.11.2 这个函数并不关心'\0',在遇到'\0'时并不会停下来。
1.11.3 memcpy是专门用来处理不相关,不重叠的内存拷贝的,如果source和destination有任何的内容重叠了,那么结果是不可预测的。
1.11.4 source和destination的传参类型最好要保持一致,可以传不同类型的,但结果是不可预测的。
memcpy的简易模拟实现:
void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;while (num--){*((char*)dest) = *((char*)src);dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}
1.12 memmove
内存拷贝函数
void* memmove(void* destaintion,const void* source,size_t num)
参数和返回值介绍:
void* destaintion:目的地
const void* source:源
size_t num:要拷贝的字节个数
返回值:返回目标空间的起始地址
1.12.1 和memcpy的区别在于memmove能额外处理内容重叠的拷贝。
1.12.2 如果源空间和目标空间发生了重叠,就得使用memmove来处理。
memmove的使用场景:
memmove的简易模拟实现:
void* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;if (dest < 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;
}
1.13 memcpy
内存比较函数
int memcmp(const void* ptr1,const void* ptr2,size_t num)
参数和返回值介绍:
ptr1和ptr2:要进行比较的两组内存中的数据
num:要比较的字节个数
返回值:ptr1>ptr2返回一个大于0的数字
ptr1==ptr2返回0
ptr1<ptr2返回一个小于0的数字
1.13.1 只比较前num个字节大小。
1.13.2 memset是一对字节一对字节依次进行比较的。
1.14 memset
内存设置函数
void* memset(void* ptr,int value,size_t num)
参数和返回值介绍:
ptr:要设置的内存空间
value:要设置的值
num:设置的字节个数
返回值:返回指向的内存空间
1.14.1 memset内存设置是以字节为单位设置的。