考试不挂科,高分直通车快要期末了,字符串理解还不透?

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的地址

【同】

  • 返回值相同
  • 都可以起到复制的作用
  • 都不进行溢出检查(不安全,有越界风险)

【异】

  • strcpydestination 中第一个元素开始拷贝,直到拷贝到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

三、后记

本文部分内容整理自网络,难免片面武断,读者如果发现错误,还请不吝赐教。今天考完了英语四级,听力听的我身心俱疲,读者老爷们不点个赞再走🤣

以上是关于考试不挂科,高分直通车快要期末了,字符串理解还不透?的主要内容,如果未能解决你的问题,请参考以下文章

自考数据结构第三章,栈队列数组,期末不挂科指南,第3篇

自考大学本科那个数据结构怎么学,期末不挂科指南,第1篇

只用半小时,只用半小时,只用半小时!给自己一个机会!!!看完保你web开发一期末不挂科,老师看了都说好!!!

一天学完操作系统,两天通过期末考试

《管理统计学》期末备考(不挂科)

Python0基础(中)——期末不挂科