目录
strlen
size_t strlen ( const char * str );
- 返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包
含 ‘\0’ )。 - 如果字符串未以 ‘\0’ 结尾,则沿着地址继续向后找,直到找到 ‘\0’ 为止,故返回随机值。
- 返回值类型为 size_t,是无符号数。易错点如下:
int main(){
const char* str1 = "abcdef";
const char* str2 = "bbb";
if (strlen(str2) - strlen(str1) > 0){
// str2>str1 因为-3被当成一个无符号数时,特别大
//if(strlen(str2) > strlen(str1)){
// srt1>str2
printf("str2>str1\n");
}
else{
printf("srt1>str2\n");
}
return 0;
}
当if的判断语句为
strlen(str2) - strlen(str1) > 0
因值为 -3 被当作是无符号数时,远大于0,因此打印 str2>str1
当if的判断语句为
strlen(str2) > strlen(str1)
因为 strlen(str2) < strlen(str1), 因此打印 srt1>str2
strlen模拟实现
- 方法一:计数器count
size_t my_strlen(const char* str) {
int count = 0;
while (*str){
count++;
str++;
}
return count;
}
- 方法二:递归
size_t my_strlen(const char* str) {
if(*str == '\0')
return 0;
else
return 1 + my_strlen(str + 1);
}
- 方法二:指针-指针
size_t my_strlen(const char* str) {
char* p = str;
while (*p != '\0')
p++;
return p - str;
}
strcpy
char* strcpy(char * destination, const char * source );
- 将源字符串 \0 前的字符(包括 \0 ),全部拷贝到目标空间,并返回目标空间起始地址
- 源字符串必须以 \0 结尾
- 目标空间(字符串)必须足够大,并且可变,故未用 const 修饰目标空间
strcpy模拟实现
char* my_strcpy(char* dest, const char* src) {
assert(dest && src);
char* ret = dest;
while (*dest++ = *src++) {
;
}
return ret;
}
strcat
char * strcat ( char * destination, const char * source );
- 将源字符串追加在目标空间,与 strcpy 相比,多了一步找目标空间的 \0, 放回的是目标空间的地址
- 源字符串必须以 \0 结尾
- 目标空间(字符串)必须足够大,并且可变,故未用 const 修饰目标空间
strcat模拟实现
// 与strcpy相比,多一个目标空间找 \0
char* my_strcat(char* dest, const char* src) {
assert(dest && src);
char* ret = dest;
while (*dest) {
dest++;
}
while (*dest++ = *src++){
;
}
return ret;
}
strcmp
int strcmp ( const char * str1, const char * str2 );
- 比较字符串中对应位置上字符的大小(ASCLL值),返回值如下:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
strcmp模拟实现
int my_strcmp(const char* dest, const char* src) {
assert(dest && src);
int ret = 0;
while (!(ret = *(unsigned char*)src - *(unsigned char*)dest) && *dest){
++src, ++dest;
}
return ret;
}
strncpy
char * strncpy ( char * destination, const char * source, size_t num );
- 从目标空间起始地址开始,从源字符串拷贝num个字符到目标空间
- 如果源字符串长度大于 num,则拷贝相应个数
- 如果源字符串的长度小于 num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
- 与 strcpy 相比,除多了拷贝的字数 num,其余相同。
strncpy模拟实现
char* my_strncpy(char* dest, const char* src, size_t num) {
assert(dest && src);
char* ret = dest;
while (*dest++ = *src++) {
num--;
// 拷贝num个字符后,跳出循环
if (0 == num) {
break;
}
}
// 源字符串的长度小于num,后面追加\0
while (num) {
*dest++ = '\0';
num--;
}
return ret;
}
strncat
char * strncat ( char * destination, const char * source, size_t num );
- 从目标空间起始地址开始,找到 \0 ,在 \0 后从源字符串追加num个字符到目标空间
- 如果源字符串长度大于 num,则追加相应个数,追加后主动放 \0
- 如果源字符串的长度小于 num,则拷贝完源字符串之后,不在目标的后边追加0,直接结束(与 strncpy 不同)
strncat模拟实现
char* my_strncat(char* dest, const char* src, size_t num) {
assert(dest && src);
char* ret = dest;
while (*dest) {
dest++;
}
while (*dest++ = *src++) {
num--;
if (0 == num) {
*dest++ = '\0';
break;
}
}
return ret;
}
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
- 从两个字符串起始地址开始,比较字符串中对应位置上字符的大小(ASCLL值),最多比较num个字符
strncmp模拟实现
int my_strncmp(const char* dest, const char* src, size_t num) {
assert(dest && src);
int ret = 0;
while (!(ret = *(unsigned char*)src - *(unsigned char*)dest) && *dest) {
++src, ++dest;
num--;
if (0 == num) {
break;
}
}
return ret;
}