1,strlen函数是计算字符串长度的函数
2,他的返回值类型是size_t也就是unsigned int 类型
int main()
{
char arr1[] = "hello";
char arr2[] = "hello world";
if (strlen(arr1) - strlen(arr2)>0)
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
我们第一眼看到这个函数的时候大概率以为输出的结果是小于号,实则不然,这就是因为strlen函数的返回值是unsigned int类型,上面两个数相减结果是-6,他的补码是
11111111111111111111111111111010
但这是无符号类型的整数,其实这是一个非常大的数字。
3,模拟实现
size_t my_strlen(const char* str)
{
char* start = str;
while (*str)
{
str++;
}
return str - start;
}
1,字符串拷贝函数,将源头字符串的内容拷贝到目标字符串中
2,目标字符串要有足够大的空间
3,字符串在拷贝的过程中,‘\0’,也进行了拷贝
4,源头字符串中必须有’\0’
可以看到拷贝发生了错误。
5,目标空间可以被修改
6,模拟实现
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
assert(dest && src);
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
1,这是一个字符串链接函数
2,目标空间足够大
3,目标空间可以被修改
4,目标字符串中与源头字符串中都含有’\0’
(1)若源头字符串中不含有’\0’,会与strcpy函数源头字符串不含结束标志结果一致
(2)函数的连接点是目标字符串中’\0’的位置
5,与strcpy函数相同结束标志’\0’也进行了拷贝
6,能否实现自己给自己连接呢?答案是否定的(你可以想一下这是为什么?)
7,模拟实现
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest)
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
1,字符串比较函数,一个字节一个字节的比较字符串的ascall码,若str1大于str2则返回大于0 的值,相反返回小于0的值,否则返回0.
int main()
{
char arr1[] = "abce";
char arr2[] = "abcd";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
2,两个字符串中必须含有’\0’,
如图,两个字符串明明相等,却返回-1.并且还造成了越界访问。
3,模拟实现
int my_strcmp(const char* arr1, const char* arr2)
{
assert(arr1 && arr2);
while (*arr1 == *arr2)
{
if (*arr1 == '\0')
return 0;
arr1++;
arr2++;
}
return *arr1 - *arr2;
}
int main()
{
char arr1[20] = "hello world";
char arr2[] = "xxxxxx";
strncpy(arr1, arr2, 5);
printf("%5s\n", arr1);
return 0;
}
1,有长度限制的字符串拷贝函数
2,目标空间足够大
3,模拟实现
char* my_strcpy(char* arr1, const char* arr2, size_t num)
{
assert(arr1 && arr2);
char* ret = arr1;
while (num&&*arr2)
{
*arr1 = *arr2;
arr1++;
arr2++;
num--;
}
while (num--)
{
*arr1 = '\0';
arr1++;
}
return ret;
}
这个函数就可以实现自己给自己追加了
int main()
{
char arr1[30] = "hello world ";
strncat(arr1, arr1,11);
printf("%s\n", arr1);
return 0;
}
1,有长度限制的字符串追加函数
2,目标空间足够大
3,在追加num个字符之后,还会追加上一个’\0’
4,模拟实现
char* my_strncat(char* dest, const char* src, size_t num)
{
assert(dest && src);
char* ret =dest;
while (*dest)
{
dest++;
}
while (num-- && *src != '\0')
{
*dest = *src;
dest++;
src++;
}
if (*src == '\0')
{
*dest = *src;
return ret;
}
else
{
*dest = '\0';
}
return ret;
}
1,有长度限制的字符串比较函数
2,相比较几个,就比较几个
1,字符串查找函数
2,在主串中查找子串,返回字串在主串中的地址,若在主串中找到多次字串那么返回第一次找到的地址。
3,模拟实现
char* my_strstr(const char* arr1, const char* arr2)
{
assert(arr1 && arr2);
char* p = arr1;
char* s1 = p;
char* s2 = arr2;
while (*p)
{
s1 = p;
while (*s2&&*s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
return p;
p++;
}
return NULL;
}
但这是一种暴力求解方法,如果追求更高的效率,可以看后期的KMP算法。
1,sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
2,函数会将分隔符位置改成’\0’(真的会把字符串改变,所以通常先拷贝一下源字符串)
3,此函数具有记忆功能,如果一个字符串需要分隔多次,只需第一次传入字符串地址
后面传空指针为参数即可。
4,函数返回值为指向分割后的字符串的指针。
这是一个将错误码,转化成错误信息的函数。
perror=strerror+printf
这里有很多函数,我们介绍几个
例如,将小写字母全部转化成大写字母的代码。
int main()
{
char arr[] = "Hello world";
char* pc = arr;
while (*pc)
{
if (islower(*pc))
{
*pc = toupper(*pc);
}
pc++;
}
printf("%s\n", arr);
return 0;
}
运行结果
1,这个函数会将 num个字节的内容 从source中拷贝到 destination中。
2,模拟实现
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,与memcpy大致相同,和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
2,模拟实现
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,比较从ptr1呵ptr2开始的num个字节的内容
2,返回值与上述的strcmp相同
3,模拟实现
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
assert(ptr1 && ptr2);
while (num--)
{
if (*(char*)ptr1 == *(char*)ptr2)
{
ptr1 = (char*)ptr1 + 1;
ptr2 = (char*)ptr2 + 1;
}
else
{
return *(char*)ptr1 - *(char*)ptr2;
}
}
}