考试不挂科,高分直通车快要期末了,字符串理解还不透?
Posted 罅隙`
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了考试不挂科,高分直通车快要期末了,字符串理解还不透?相关的知识,希望对你有一定的参考价值。
一、前言🎉
阅读这篇文章你可以学到什么:
- “ ”如何创建一个字符串
- “abc”什么时候是常量,什么时候不是常量
- 常见错误:修改数组名
- 常见错误:strcpy越界访问
- 易混点:strcpy与strcmp函数的异同
二、正文现在开始⭐
- 问题①:将字符串赋值给字符指针变量
int main()
char*p = "I Love study";
return 0;
先来分析一下" "都做了哪三件事:
- 在
只读区
申请中为字符串申请了内存,用于存放了字符串 - 在字符串尾部加上‘\\0’
- 返回字符串首元素的地址
【总结】我们使用字符串的时候,实际使用的是字符串的首元素地址而不是字符串本身
。因此也就不难理解将字符串赋值给指针变量的操作了。
- 问题②:用字符串初始数组
int main()
char str[] = "abc";
return 0;
在这里并不是将该字符串的地址赋值给数组,而是用字符串中的各个元素为数组赋值。怎么理解这个问题呢?我们接下来来讨论一下什么时候“abc”什么时候是常量,什么时候不是:
- 不是常量的情况
int main()
char str[] = "abc";
return 0;
[分析]:
- 首先,我们定义的是一个字符数组,默认数组是开辟在
栈区
上的,栈区上的数据是可以被修改的 - 其次,我们定义了一块空间存储"abc",这块空间也就是上面提到的
栈区
,因此此时的“abc”并不是开辟在只读区上,也说明了它并不是常量 - 是常量的情况
int main()
char* p = "abc";
return 0;
[分析]
- 正如我们提到的第一个案例,因为我们并没有为"abc"申请一块空间,所以说“ ”为abc在
只读区
上开辟了一块空间
- 我们可以看到,虽然执行时并没有报错,但是调试时就产生了访问冲突的的
执行异常
,因为我们试图修改只读区上的内容,这显然是不允许的。从中也说明了此时“abc”是一个常量 - 回到刚才的问题
int main()
char str[] = "abc";
return 0;
- 此时"abc"并不是常量,我们实际是用字符串的各个元素对数组进行的赋值操作
- 因为有了双引号定界符,所以我们不需要额外的花括号
- 问题③ 为数组名赋值
int main()
char s[10];
s = "abcd";
printf("%s\\n", s);
return 0;
[分析]
- s是代表字符串首元素地址,“abcd”表示该字符串首元素地址
- 试想如果赋值成功了,那么s的地址将发生改变,也就意味着我们无法找到之前开辟的数组空间,那我们之前所开辟的空间不就石沉大海了吗
- 不只是字符数组,任何类型的数组,数组名的地址值都不能发生改变
int main()
int arr[10];
int* p = NULL;
arr++;//错误
arr--;//错误
arr = p;//错误
arr += 10;//错误
【结论】数组名是一个指针常量
,不可以被修改。通常都是用 int *p = arr[0] 然后通过p的偏移来访问不同的空间元素,而不会使用arr或者arr[0]来进行操作,案例如下:
int main()
char a[10];
char* p = a;
p = "Visual C";//正确
a = "Visual C";//错误
return 0;
[分析] p是一个指针变量,只不过初始值和a的指向的空间地址相同罢了。
- 问题④:为二维数组赋值
int main()
char str[3][10];
str[1] = "abcd";
[分析]
- str[1]是二维数组str第一行一维数组的数组名
- 上文提到,数组名是指针常量,是不可以被赋值修改的,所以上面是一个错误案例
- 问题⑤: strcpy函数实现赋值
//两数组内容交换
#include<string.h>
int main()
char p[] = "Taylor·Swift";
char q[] = "gorgeous";
char t[13];
strcpy(t,p);
strcpy(p,q);
strcpy(q,t);
return 0;
[分析]
- strcpy是一个不安全的函数,为什么这么说呢?不管目标空间是否充足,strcpy都会把source的内容拷贝到destination中去
- 因此如果destination空间不足,就好造成非法访问内存的错误。上面的代码正是犯了这个错误
- 易混点①:strcpy函数和strcat函数的异同
(1)strcpy函数
- 参数: char *strcpy( char *strDestination, const char *strSource );
- 功能:strcpy函数将strSource(
包括终止null字符
)复制到strDestination指定的位置。复制字符串时不执行溢出检查
- 返回值:返回destination的地址
(2)strcat函数
- 参数: char *strcat( char *strDestination, const char *strSource );
- 功能: strcat函数将strSource追加到strDestination,并以一个空字符结束结果字符串。strSource的初始字符
覆盖strDestination的终止null字符
。复制或附加字符串时不执行溢出检查
- 返回值:返回destination的地址
【同】
- 返回值相同
- 都可以起到复制的作用
- 都不进行溢出检查(不安全,有越界风险)
【异】
- strcpy从 destination 中第一个元素开始拷贝,直到拷贝到source的NULL为止; strcat 一直找到destination的NULL后才开始追加
strcpy和strcat的自定义实现
#include<string.h>
#include<assert.h>
char* my_strcpy(char* des, const char* src)
assert(des && src);//断言防止des或者src为空指针
char* start = des;
while (*des++ = src++);//巧妙使用 = ,而不是 ==
return start;
char* my_strcat(char* des, const char* src)
assert(des && src);
char* start = des;
while (*++des);//直到*des为NULL为止
while (*des++ = *src++);
return start;
- 课后练习题
练习题①:
int main()
char str[50] = "xyz", p1[20] = "abcd", * p2;
p2 = "ABCD";
strcpy(str+2, strcat(p1+1,p2+1));
printf("%s\\n", str);
return 0;
[分析]
- 首先注意, strcat 一定是找到des的
NULL
才开始追加 - 其次,注意 strcat 的返回值是des的地址,也就是p1+1
- 因此strcat(p1+1, p2+1)的结果就是 "bcdBCD "
- strcpy 则是从传入位置开始拷贝,所以最终结果就是 xybcdBCD
练习题②:
int main()
char Arr1[80] = "AB", Arr2[80] = "LMNP";
int i = 0;
strcat(Arr1, Arr2);
while (Arr1[i++] != '\\0')
Arr2[i] = Arr1[i];
printf("%s", Arr2);
[分析]
- 注意这里的i++就好,答案是LBLMNP
练习题③:当输入串: love Taylor!时,程序的输出结果
int main()
while (putchar(getchar()) != '!');
return 0;
[分析]
- 答案为love Taylor!看到答案就明白了吧
练习题④
int main()
char a[10] = "1,2,3,4,5";
printf("%d, %d", sizeof(a), strlen(a));
return 0;
[分析]
- 逗号有坑到你吗?反正我是被坑到了
练习题⑤
int main()
int i = 0;
char* s = "a\\\\04\\b\\\\b\\xab\\06";
while (*s++ && ++i);
printf("%d", i);
return 0;
[分析]
- 注意这里的转义字符: ‘\\’ ‘\\b’ ‘\\xab’ ‘\\06’
练习题⑥
int main()
char s1[] = "Basic";
char s2[] = "Base";
strcpy(s1,s2);
printf("%s",s1);
return 0;
[分析]
- strcpy拷贝的时候别忽略了’\\0’也被拷贝过来,所以c其实被‘\\0’覆盖
- 因此答案为Base
三、后记
本文部分内容整理自网络,难免片面武断,读者如果发现错误,还请不吝赐教。今天考完了英语四级,听力听的我身心俱疲,读者老爷们不点个赞再走🤣
以上是关于考试不挂科,高分直通车快要期末了,字符串理解还不透?的主要内容,如果未能解决你的问题,请参考以下文章