目录
一、strlen
特别注意:
-
打印的时候,计算机存的是补码,但是我们打印出来的是十进制,
-
我们得把补码转成原码,然后把原码转成十进制数,得到的结果才和打印出来的十进制数一致。
size_t strlen ( const char * str );
返回值是无符号整形
#include<stdio.h>
#include<string.h>
/*strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')。
size_t strlen ( const char * str );
参数指向的字符串必须要以'\0'结束。
注意函数的返回值为size_t,是无符号的(易错)*/
int main()
{
const char* str1 = "abcdef";
const char* str2 = "bbb";
printf("%d\n", strlen(str1));//6
printf("%d\n", strlen(str2));//3
if (strlen(str2) - strlen(str1) > 0)
//3-6=-3
//10000000 00000000 00000000 00000011 - 补码
//11111111 11111111 11111111 11111100 - 反码
//11111111 11111111 11111111 11111101 - 原码
//再转成十进制数
{
printf("%u\n", strlen(str2) - strlen(str1));
printf("%d\n", strlen(str2) - strlen(str1));
printf("str2>str1\n");
}
/*结果显示,str1 >str2 ,与预期结果不符合,
原因是strlen返回值是无符号的,相减之后作为无符号数处理,结果<0*/
else
{
printf("str1>str2\n");
}
return 0;
}
打印的时候,计算机存的是补码,但是我们打印出来的是十进制,
我们得把补码转成原码,然后把原码转成十进制数,得到的结果才和打印出来的十进制数一致。
所以%u打印出来的会认为无符号型打印会非常大
str2>str1
1.模拟实现strlen
int my_strlen(const char* str)
{
int count = 0;
while (*str++)
{
count++;
}
return count;
}
int main()
{
char arr[] = "abcdefg";
int ret = my_strlen(arr);
printf("%d\n", ret);
return 0;
}
注意下图结果为3是因为,这样{""}都算,所以打印出3.
二、strcpy
模拟实现需要注意:1)源字符串必须以 '\0'结束。2)会将源字符串中的 '\0'拷贝到目标空间。3)目标空间必须足够大,以确保能存放源字符串。4)目标空间必须可变。
2.模拟实现strcpy
/*模拟实现需要注意:
1)源字符串必须以 '\0'结束。2)会将源字符串中的 '\0'拷贝到目标空间。
3)目标空间必须足够大,以确保能存放源字符串。4)目标空间必须可变。*/
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest++ = *src++);
return ret;
}
int main()
{
char arr1[20] = {0};
char arr2[10] = "abcdefg";
printf("%s\n", my_strcpy(arr1, arr2));
return 0;
}
三、strcat
模拟实现注意:
char * strcat ( char * destination, const char * source );
源字符串必须以'\0' 结束。目标空间必须有足够的大,能容纳下源字符串的内容,目标空间必须可修改。
int main()
{
char src[20], dest[50];
strcpy(src, "This is source");
strcpy(dest, "This is destination");
strcat(dest, src);
printf("最终的目标字符串: |%s|", dest);
return(0);
}
3. 模拟实现strcat
/*while(*dst++);这样写是错误的*/
/*由于运算符*的优先级高于运算符++,所以是先取指针dst指向的地址单元的数据。具体如下:
1、取数组当前位置的值*dst;
2、然后,dst指向下一位置的数据。
所以这样写会导致直接到\0就结束了,只会输出woshiyige*/
char* my_strcat(char* dst, const char* src)
{
assert(dst && src);
char* ret = dst;
while (*dst)
{
dst++;
}
while (*dst++ = *src++);
return ret;
}
int main()
{
char arr1[50] = "wo shi yi ge ";
char arr2[20] = { 's','b','!' ,'\0'};
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
四、strcmp
int main()
{
char str1[15];
char str2[15];
int ret;
strcpy(str1, "abcdef");
strcpy(str2, "ABCDEF");
ret = strcmp(str1, str2);
if (ret < 0)
{
printf("str1 小于 str2");
}
else if (ret > 0)
{
printf("str1 大于 str2");
}
else
{
printf("str1 等于 str2");
}
return(0);
}
注意:不会因为字符串长度不同而区别大小,只是从开始到找到\0停止。只要发现ascii码值不同的,就有返回值。
4. 模拟实现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;
}
int main()
{
char arr1[] = "aAASebcd";
char arr2[] = "aAAsebcdD";
int ret = my_strcmp(arr1, arr2);
if (ret > 0)
{
printf("arr1 大于 arr2");
}
else if (ret < 0)
{
printf("arr1 小于 arr2");
}
else
{
printf("arr1 等于 arr2");
}
return 0;
}
五、strstr
strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。
注意下列情况的返回值:
5. 模拟实现strstr
思路:因为我们要在str1里找str2,那么如果在str1中找到了str2,那如果返回str1,我们找不到最开始的位置,因为我们的思路一开始肯定是两个指针遍历两个数组,如果在str1中找到了和str2相同的,就同时往后走,这样我们就无法找到最开始的位置返回str1了。
怎么解决上述问题?
引入一个指针在str1上,让他去记住最开始的位置,然后别的指针接着遍历。
这样综上我们就知道起码使用三个指针完成
char* n1 = (char*)str1;
char* n2 = (char*)str2;
char* n3 = (char*)str1;
以下是普通的思路:
但是如果出现如下情形时:
char arr1[] = "abbbcdef";
char arr2[] = "abbc";
那么我们就必须想办法让n2能回到最初的位置,再重新遍历。完善以下思路,代码就出来了,如下所示:
char* my_strstr(const char* str1, const char* str2)
{
char* n1 = (char*)str1;
char* n2 = (char*)str2;
char* n3 = (char*)str1;
if (n2 == '\0')
{
return (char*)str1;
}
else
{
while (*n2)
{
while (*n1 && *n1 != *n2)
{
n2 = (char*)str2;
n3++;
n1 = n3;
}
n2++;
n1++;
if (*n1 == '\0')
{
return NULL;
}
}
return (char*)n3;
}
}
int main()
{
char arr1[] = "abbbcdef";
char arr2[] = "abbc";
char* ret = my_strstr(arr1, arr2);
if (NULL == ret)
printf("没找到\n");
else
printf("%s\n", ret);
return 0;
}
六、笔试题
逆序输出字符串:
相当于模拟实现reverse
void reverse(char* left, char* right)
{
while (left < right)
{
char tmp = 0;
tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
int main()
{
char arr[100] = { 0 };
gets(arr);//获取字符串
//将字符串倒置
int len = strlen(arr);//计算字符串长度,以求最后一位的地址
printf("%d\n", len);
reverse(arr, arr + len - 1);//进行倒置
printf("%s\n", arr);
return 0;
}
gets函数,C语言gets函数详解_gets()的功能-CSDN博客https://blog.csdn.net/wowocpp/article/details/119888876