程序设计基础第五~六周答疑要点整理
函数的return
语句的意义:表示函数结束
对一个函数来说,当执行到return
语句的时候,表示这个函数要直接结束,返回到函数外面调用这个函数的地方继续运行。即使return
套在多重循环里,而循环可能还剩很多趟要跑,也会直接“撒手不管”,不会去执行执行顺序在return
后面的语句。
关于函数单向传参问题
有些同学想使用如下函数将传入函数的两个局部变量的值交换,是一种很常见的错误写法:
1 |
|
大家在学习函数的时候都知道,函数传参是单向的。函数在被调用时,会在内存中开辟一块自己的内存空间。此时,作为函数参数的变量,它们的值会被相应地拷贝一份,存在属于函数自己的内存空间中。当在函数内“交换”变量a
和b
的时候,事实上是把函数自己的内存空间中保存的a
、b
变量值的一个副本进行了交换,而外面真正的变量a
和b
的值并没有受到影响。
如果需要通过在函数中的操作修改外部变量的值,一种可选的方法是使用全局变量。此时,因为函数可以直接访问全局变量,所以不需要将全局变量的值作为参数传入函数:
1 |
|
另外一种方法是将待交换变量的指针作为函数参数传入函数,下次课学过指针后会有详细讲解。
字符串字面值和字符字面值的区别
字符字面值是由一对单引号''
括起来的单个字符(转义字符的反斜杠\
和后面的字符合起来算作一个字符),一个字符字面值存在一个字节(char
)的内存空间中。
字符串字面值是由一对双引号""
括起来的任意个字符,在内存中,字符串中的每个字符都各自存在一个字节(char
)的内存空间中,这些字节按字符在字符串中的顺序连续排列,最后以一个存有结束符'\0'
的字节作为结尾。
1 |
|
字符串在数组中的存储
当使用scanf("%s", str);
或gets(str);
读取长度为len
的字符串,并存入字符数组str
时,字符串中的字符在数组中存储的下标范围是0 ~ len-1
,下标为len
的位置上则是一个标识字符串结束位置的'\0'
。在遍历字符串时需要注意下标范围。
与此同时,也需要注意:字符串里的'\0'
也是需要一个位置来存储的。所以声明数组时,请适量地把长度开大一点。
字符数组的推荐初始化方法
在声明字符数组时,推荐将字符数组的各位置初始化为全0
:
1 |
|
初始化为全0
后,字符数组的每个位置上的字符都是'\0'
,即标识字符串结束的字符。万一遇到需要自己手动给字符数组的某个位置赋值'\0'
、标识字符串的结尾但是不小心忘记了的情况,也能使字符串能够结尾。
字符串操作函数的传入参数
strcpy
、strcat
、strcmp
、strlen
、strstr
等诸多字符串操作函数,当需要对一维字符数组执行操作时,需要传入这些函数的参数是数组名。
1 |
|
事实上,传入的参数需要是指向一维char
数组的指针类型,下次课学到指针后会有详细讲解。
遍历字符串时一个常见的易超时写法
在需要遍历字符串的题目中,经常出现一种比较典型的写法:
1 |
|
当不会在循环中修改字符串str
的长度时,这种写法的效率是十分低的。
因为由for
循环中语句的执行顺序可知:每跑完一趟循环,都要去执行for
后面括号里中间的判断条件i < strlen(str)
,来判断循环要继续还是结束。而strlen
是通过遍历字符数组,寻找第一次出现的'\0'
结束符来计算字符串长度的。当字符串长度固定时,strlen
函数返回的值也是固定的值。如果每次循环都要重新计算一次这个值,那就要白白地多遍历字符串strlen(str)
趟,显然是不必要的操作。
因此,可以在遍历字符串前,先声明一个变量待存字符串的长度,使用一次strlen
函数计算长度并存入变量中,然后在遍历字符串时,使用这个变量的值作为循环的判断条件。这样就能减少不必要的操作,提高代码效率:
1 |
|
当然,如果字符串str
的长度在每次循环中都可能发生变化时,使用i < strlen(str)
作为判断条件就没什么问题了。
逻辑表达式的短路求值性质在访问字符数组中的应用
我们知道:逻辑表达式具有短路求值的性质。逻辑表达式从左往右执行,对两个以逻辑与运算&&
连接的关系语句,当左面的关系语句为假(值为0
)时,右面的关系语句不需要计算,可以直接得出整个逻辑表达式为假(值为0
)的结果。
因此,当要在一个if
条件里使用逻辑与运算&&
,实现 判断数组下标是否越界、在不越界时取出该下标位置中的元素判断该元素是否满足某条件 时,最好将判断下标是否越界的关系语句写在左面。这样,当下标越界时左面的语句值为假,就不会执行右面的语句访问越界的位置,有助于培养大家对访问数组前先检查下标是否越界的好习惯:
1 |
|
作者:逐月的游星、梁秋月