字符函数和字符串函数
1. 求字符串长度
1. strlen 函数
size_t strlen(const char* str);
- 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
- 参数指向的字符串必须要以 ‘\0’ 结束。
- 注意函数的返回值为size_t,是无符号的( 易错 )
- 学会strlen函数的模拟实现
了解 strlen 函数
#include <stdio.h>
#include <string.h>
int main()
{
int len = strlen("abcdef");
printf("%d\n", len);
return 0;
}
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
int len = strlen(arr);
printf("%d\n",len);
return 0;
}
打印两个strlen计算长度的数相减
#include <stdio.h>
#include <string.h>
int main()
{
const char* str1 = "abcdef";
const char* str2 = "bbb";
if (strlen(str2) - strlen(str1) > 0)
{
printf("str2 > str1\n");
}
else
{
printf("srt1 > str2\n");
}
return 0;
}
自定义strlen 函数 - my_strlen 函数
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strlen(const char* str)
{
int count = 0;
assert(str != NULL);
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
2. 长度不受限制的字符串函数
2.1 strcpy 函数
char* strcpy(char * destination, const char * source);
- Copies the C string pointed by source into the array pointed by destination, including the terminating null character(and stopping at that point).
- 源字符串必须以 ‘\0’ 结束。
- 会将源字符串中的 ‘\0’ 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
- 学会模拟实现。
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "world";
strcpy(arr1, arr2);
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
自定义strcpy函数 - my_strcpy函数
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcpy(char* dest,char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while (*src != '\0')
{
*dest++ = *src++;
}
*dest = *src;
return ret;
}
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "world";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "world";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
strcpy函数 注意事项 1
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = { 'w','o','r','l','d' };
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcpy函数 注意事项 2
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "a";
char arr2[] = "world";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcpy函数 注意事项 3
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
int main()
{
char *arr1 = "abcdefghi";
char arr2[] = "world";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
2.2 strcat 函数
char * strcat ( char * destination, const char * source );
- 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 ofthe new string formed by the concatenation of both in destination.
- 源字符串必须以‘\0’结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
- 字符串自己给自己追加,如何 ?
strcat 函数 注意事项 1
目标空间必须有足够的大,能容纳下源字符串的内容。目标空间必须可修改。
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "hello";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}

修改
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcat 函数 注意事项 2
strcat函数注意事项:源字符串必须以‘\0’结束。
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[30] = "hello\0xxxxxxxx";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}


自定义strcat函数
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}

2.3 strcmp 函数
int strcmp(const char* str1, const char* str2, size_t num);
- 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完
比较字符串错误示范
#include <stdio.h>
#include <string.h>
int main()
{
char* p1 = "opqrst";
char* p2 = "abcd";
if ("opqrst" >= "abcd")
{
printf("haha");
}
else
{
printf("hehe");
}
return 0;
}
strcmp函数使用
#include <stdio.h>
#include <string.h>
int main()
{
char* p1 = "opqrst";
char* p2 = "abcd";
int ret = strcmp(p1, p2);
printf("%d\n", ret);
return 0;
}
strcmp函数返回值
#include <stdio.h>
#include <string.h>
int main()
{
char* p1 = "qbc";
char* p2 = "abc";
if (strcmp(p1,p2) > 0)
{
printf("p1 > p2\n");
}
else if (strcmp(p1, p2) == 0)
{
printf("p1 == p2\n");
}
else if (strcmp(p1, p2) < 0)
{
printf("p1 < p2\n");
}
return 0;
}
自定义strcmp函数
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
if (*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
char* p1 = "abc";
char* p2 = "abc";
int ret1 = my_strcmp(p1, p2);
printf("ret1 = %d\n",ret1);
char* p3 = "abcdef";
char* p4 = "abc";
int ret2 = my_strcmp(p3, p4);
printf("ret1 = %d\n", ret2);
char* p5 = "abc";
char* p6 = "abcdef";
int ret3 = my_strcmp(p5, p6);
printf("ret1 = %d\n", ret3);
return 0;
}
3. 长度不受限制的字符串函数
3.1 注意点
strcpy 、strcat 、strcmp 一定要遇到 ‘\0’ 才停止运行,写程序要注意函数特性,避免写bug
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[5] = "abc";
char arr2[] = "hello world";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}

觉得长度不受限制的字符串函数会不安全,为了预防,就设置了长度受限制的字符串函数
3.2 strncpy 函数
strncpy和strcpy的差别
strcpy: char* strcpy(char * destination, const char * source);
strncpy: char* strncpy(char* destination, const char* source, size_t num);
Copies the first num characters of source to destination.
If the end of the source C string(which is signaled by a null - character)
is found before num characters have been copied,
destination is padded with zeros until a total of num characters have been written to it.
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
3.3 strncpy函数介绍
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[5] = "abc";
char arr2[] = "hello world";
strncpy(arr1, arr2, 4);
printf("arr1:%s\n", arr1);
return 0;
}


拷贝几个就覆盖目标数组的几个元素
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "hello world";
strncpy(arr1, arr2, 4);
printf("arr1:%s\n", arr1);
return 0;
}


如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
1
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "jkl";
strncpy(arr1, arr2, 6);
printf("arr1:%s\n", arr1);
return 0;
}


2
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = "abcdefgh";
char arr2[] = "jkl";
strncpy(arr1, arr2, 6);
printf("arr1:%s\n", arr1);
return 0;
}


3.4 strncat 函数
strncat函数介绍
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[30] = "hello";
char arr2[] = "world";
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}


问题1:
“wor”后的“\0”的追加的还是怎么样?
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[30] = "hello\0xxxxxxxx";
char arr2[] = "world";
strncat(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}


问题2:
要是追加超过字符串的长度会怎么样?
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[30] = "hello\0xxxxxxxxxxxx";
char arr2[] = "world";
strncat(arr1, arr2, 8);
printf("%s\n", arr1);
return 0;
}


3.5 strncmp 函数
int strncmp(const char* str1, const char* str2, size_t num);
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
#include <stdio.h>
#include <string.h>
int main()
{
const char* p1 = "abcdef";
const char* p2 = "abcqwer";
int ret1 = strncmp(p1, p2, 3);
printf("%d\n", ret1);
int ret2 = strncmp(p1, p2, 4);
printf("%d\n", ret2);
return 0;
}
4. 字符串查找
4.1 strstr 函数
char * strstr ( const char *, const char * );
Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
返回str1中str2第一次出现的指针,如果str2不属于str1,则返回一个空指针。
strstr 函数的使用1
#include <stdio.h>
#include <string.h>
int main()
{
char* p1 = "abcdef";
char* p2 = "def";
char* ret = strstr(p1, p2);
if (ret == NULL)
printf("字符串不存在");
else
printf("%s\n", ret);
return 0;
}
strstr 函数2
#include <stdio.h>
#include <string.h>
int main()
{
char* p1 = "abcdefqhi";
char* p2 = "def";
char* ret = strstr(p1, p2);
if (ret == NULL)
printf("字符串不存在");
else
printf("%s\n", ret);
return 0;
}
strstr 函数3
#include <stdio.h>
#include <string.h>
int main()
{
char* p1 = "abcdefabcdef";
char* p2 = "def";
char* ret = strstr(p1, p2);
if (ret == NULL)
printf("字符串不存在");
else
printf("%s\n", ret);
return 0;
}
模拟实现strstr函数
简单版
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strstr(const char* p1, const char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
if (*p2 == '\0')
{
return p1;
}
while (*p1)
{
while ((*p1 != '\0') && (*p2 != '\0') && (*p1 == *p2))
{
p1++;
p2++;
}
p1++;
}
}
int main()
{
char* p1 = "abcdef";
char* p2 = "def";
char* ret = my_strstr(p1, p2);
if (ret == NULL)
{
printf("字串不存在");
}
else
{
printf("%s\n", ret);
}
return 0;
}

while ((*p1 != '\0') && (*p2 != '\0') && (*p1 == *p2))

修改模拟实现strstr函数
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strstr(const char* p1, const char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
char* s1 = p1;
char* s2 = p2;
char* cur = p1;
if (*p2 == '\0')
{
return p1;
}
while (*cur)
{
s1 = cur;
s2 = p2;
while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cur;
}
cur++;
}
return NULL;
}
int main()
{
char* p1 = "abcdef";
char* p2 = "def";
char* ret = my_strstr(p1, p2);
if (ret == NULL)
{
printf("字串不存在");
}
else
{
printf("%s\n", ret);
}
return 0;
}

运行警告修改



#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strstr(const char* p1, const char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
char* s1 = (char*)p1;
char* s2 = (char*)p2;
char* cur = (char*)p1;
if (*p2 == '\0')
{
return (char*)p1;
}
while (*cur)
{
s1 = cur;
s2 = (char*)p2;
while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cur;
}
cur++;
}
return NULL;
}
int main()
{
char* p1 = "abcdef";
char* p2 = "def";
char* ret = my_strstr(p1, p2);
if (ret == NULL)
{
printf("字串不存在");
}
else
{
printf("%s\n", ret);
}
return 0;
}
疑问:若p2的字符串比p1的字符串长?

#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strstr(const char* p1, const char* p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
char* s1 = (char*)p1;
char* s2 = (char*)p2;
char* cur = (char*)p1;
if (*p2 == '\0')
{
return (char*)p1;
}
while (*cur)
{
s1 = cur;
s2 = (char*)p2;
while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cur;
}
if (*s1 == '\0')
{
return NULL;
}
cur++;
}
return NULL;
}
int main()
{
char* p1 = "abcdef";
char* p2 = "def";
char* ret = my_strstr(p1, p2);
if (ret == NULL)
{
printf("字串不存在");
}
else
{
printf("%s\n", ret);
}
return 0;
}
4.2 strtok 函数
char *strtok(char *str, const char *delim);
函数特性
函数特性1
sep参数是个字符串,定义了用作分隔符的字符集合
一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "lqbz@bili.com";
char* p = "@.";
return 0;
}

函数特性2
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改 变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。 如果字符串中不存在更多的标记,则返回 NULL 指针。
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "lqbz@bili.com";
char* p = "@.";
char* ret = strtok(arr, p);
printf("%s\n", ret);
ret = strtok(NULL, p);
printf("%s\n", ret);
ret = strtok(NULL, p);
printf("%s\n", ret);
return 0;
}

 GitHub代码
|