4.目标空间不能被修改
#include<stdio.h> #include<string.h> int main() { char* p = "abcdefghi"; char arr2[] = "hehe\n"; strcpy(p, arr2);//这也是一样错的示范 - 目标空间必须可以修改 printf("%s\n", p); return 0; }
1.2.1学会strcpy模拟实现:💎
strcpy的模拟实现:函数返回类型是char*,把源头的数据拷贝到目标空间之后,整个目标空间发生变化,把目标空间的地址返回来。要感知函数的变化,返回目标空间的地址是比较合适的。
对于ret来说,返回的时候。arr2数组是一段连续的空间,所以返回首元素地址,后面就紧跟的是后序元素
#include<stdio.h> #include<string.h> char* my_strcpy(char* dest, const char* src)//加上const对源头的数据进行保护 { char* ret = dest; assert(dest && src); while (*dest++ = *src++) { ; } return ret;//数组是一段连续的空间,所以返回首元素地址,后面就紧跟的是后序元素 } int main() { char arr1[] = "hehe"; char arr2[20] = { 0 }; my_strcpy(arr2, arr1); printf("%s\n",arr2); return 0; }
合2为1写法🏈
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
assert(dest && src);
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "hehe";
char arr2[20] = { 0 };
printf("%s\n", my_strcpy(arr2, arr1));//合2为1
return 0;
}
1.3 strcat
char * strcat( char * destination, const char * source);
注意:拷贝(strcpy)的意思是覆盖掉,与追加不一样, strcat也就是追加的时候第一个字符是把'\0'给覆盖掉,之后在拷贝完后加上一个‘\0’即可。
#include<stdio.h> int main() { char arr1[20] = "hello \0xxxxxxxxxxx"; char arr2[] = "world"; strcat(arr1, arr2);//会以\0为起始位置拷贝 printf("%s\n", arr1); }
- 源字符串必须以 '\0' 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
1.3.1模拟实现strcat🏐
模拟实现的图解:
#include<assert.h> #include<stdio.h> char* my_strcat(char* dest, const char* src) { assert(dest && src); char* ret = dest; //找目标空间的'\0' while (*dest != '\0') { dest++; } //拷贝 while (*dest++ = *src++) { ; } return ret; } int main() { char arr1[20] = "hello "; char arr2[] = "world"; //追加 my_strcat(arr1, arr2); printf("%s\n", arr1); return 0; }
返回值问题?
注意问题:
只是它的返回值这里没有使用到而已,库函数是有返回值的,因为有些场景下 ,我们需要用到字符串的首地址
可以理解为:我可以不用,但是应该有, 因为这是关于这个strcat的模拟实现,是对于它的库函数的一种理解,所以说它的库函数也可能会这样使用。
1.3.2strcat自己对自己追加🎈
会陷入死循环, 这种情况是不能用strcat的,要用的是strncat!
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest != '\0')
{
dest++;
}
//拷贝
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "bit";
my_strcat(arr1, arr1);
printf("%s", arr1);
return 0;
}
图解:
注意const char*src:
不会通过src来改变里面空间的数据,但是把src指向的内容放进dest指向的空间里面去了
因为dest指针没有受到限制,是不能通过src来改变这块空间的数据,并不意味着这块空间不能被改变,数组内容还是可以被改变的.
src本身是改变了,是因为src的指向在发生变化,这块空间,是通过dest去改变的
1.4 strcmp
这里比较的是2个字符串的内容的时候,不能使用 == ,应该使用strcmp;
char* p = "abcdef";//因为"abcdef"把这个表达式首字符'a'的地址给了p指针,所以这个表达式的值是'a'的地址
//这里下面比的其实是"abcdef"的'a'的地址和"bbcdef"的'b'的地址是否相等,并没有比较内容
if ("abcdef" == "bbcdef")//这里比较的是两个字符串首字符的地址,而不是字符串内容
{
}
前提
:首先说明这个函数strcmp实现两个字符串的比较的时候是跟长度不存在对应的关系,并不是谁长谁就大!
int strcmp ( const char * str1, const char * str2 );
举例:
"abcdef"
"bbq"
这两个字符串,上面长,下面短,对应位置的字符比较,根据ascll码值,a是小于b,所以
bbq大于abcdef
总结:
当对应位置的字符比较时,,如果相等就跳过一个字符比较,当它们不相等时,ascll码值的大整个字符串就大,与长度无关
再举例:
"abcdef"
"abbbbbbbbb"
因为'c'的ascll码值大于'b',所以"abcdef"大
标准规定:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
正常代码操作:
#include<stdio.h> #include<string.h> int main() { //跟长度没关系. char arr1[] = "abcdef"; char arr2[] = "bbq"; int ret = strcmp(arr1, arr2); printf("%d\n", ret); return 0; }
arr1<arr2,所以返回-1;
1.4.1strmpy的模拟实现📌
#include<stdio.h> int my_strcmp(const char* str1, const char* str2) { while (*str1 == *str2) { if(*str1=='\0') return 0; str1++; str2++; } if (*str1 > *str2) return 1; else return -1; } int main() { char arr1[] = "abzqb"; char arr2[] = "abq"; int ret = my_strcmp(arr1, arr2); printf("%d\n", ret); return 0; }
写成(const char* str1, const char* str2)的原因:
str1和str2不会去修改原字符串的内容,只是比较它们的大小,所以只要能拿到这个字符串内容就可以了。
函数实现部分也可以写成:👓
#include<stdio.h>
int my_strcmp(const char* str1, const char* str2)
{
while (*str1 == *str2)
{
if(*str1==*str2)
str1++;
str2++;
}
return *str1 - *str2;//ascllm码值相减
}
主函数部分也可以写成:👓
int main()
{
char arr1[] = "abzqw";
char arr2[] = "abq";
//这里不能写成 if (strcmp(arr1, arr2) == 1),vs这个环境底下大于返回1,其它的平台有可能返回其它大于0的数字,所以不能这样写
⬇⬇⬇
//要写成这样
if (strcmp(arr1, arr2) > 0)
printf(">\n");
else if (strcmp(arr1, arr2) == 0)
printf("=\n");
if (strcmp(arr1, arr2) <0)
printf("<\n");
return 0;
}
整体来说:
strcpy,strcat,strcmp这三种函数,是长度不受限制的字符串函数,以及scanf这些函数在vs等高版本系列的编译器看来都是不安全的,原因是:arr2太小放不下,程序崩溃
#include<stdio.h> int main() { char arr1[] = "abcdef"; char arr2[5] = { 0 }; strcpy(arr2, arr1); printf("%s\n", arr2); return 0; }
所以为了解决这种不安全,引入了一系列的长度受限制的字符串函数strncpy,strncat,strncmp;