2025年11月18日笔记
1. 有时候题目没说要读入,但是里面变量都没有初始化初值,这时候可能是题目没说清楚。
课后作业8 5-1
计算字符串的有效长度。字符串的有效长度就是有效字符的个数,即数组中第1个 '\0' 前面的字符个数。例如,字符串"Happy"的有效长度是5。
#include <stdio.h>
int main()
{
int k, len;
char str[81];
k = 0;
while (...) {
k++;
}
...
len = ...;
printf("%d\n", len);
return 0;
}
题面并没有说要读入,但是感觉这里确实是要读入,怪题。
2. 课本的运算符优先级和结合律不全,看这张:

int a = 3, *p = &a;
*p++; // 和 a ++ ; 等价
这看似是对的,实际上后缀 ++ 的优先级比间接访问运算符 * 要高,所以是先取 *p,然后再 p ++ 。和 a ++ 不等价。
由于这俩优先级就不一样了,所以和结合方向没有关系。(课本把前缀和后缀自加/自减混为一谈了)
3. 理论题注意输入的结尾标志,如果没有说明,就是EOF,但绝对不是 '\0'。
课后作业8 1-3
以下代码实现从键盘输入一个字符串,并将小写字母转换为相应的大写字母后输出,其他字符原样输出。
while ((ch = getchar()) != '\0') {
if (ch >= 'a' && ch <= 'z')
ch = ch - 'a' + 'A';
putchar(ch);
}
这是错的,
'\0'应该改成EOF。
4. 不知道指针可不可以直接赋值一个整型常量作为地址。
课后作业8 1-18
执行语句int *p = 1000;后,指针变量p指向地址为1000的变量。
dev实测是可以这样干的:
int main()
{
int b = 1;
int c = (int)(&b);
int *d = c;
printf("%d\n", (int)d);
*d = 2;
printf("%d\n", b);
return 0;
}
不知道答案是啥,记得看一下。
5. 字符串初始化如果太多,好像会越界。
char s[6] = "Happy\0";
应该会越界?回去看一下答案。
6. 字符串常量存储在只读数据段,这部分内存在程序运行时是只读的。
char *p = "hello";
*p = 'H';
将导致段错误,因为修改了只读内存。
7. 不同类型的指针变量不可以直接相互赋值。
不同类型指针变量赋值需要强制转换,但是 void 是例外。
void 不能直接 *p 取值,要强制转换成别的类型,然后才能用间接运算符。
试图直接读取空指针的内容,编译会报Error。
要这样写*(int*)p,也就是先转成具体类型的变量,这样编译器才能得知偏移量等信息。
int main() {
int a = 10;
double b = 3.14;
void *void_ptr; // void* 可以指向任何类型
void_ptr = &a; // ✅ int* 可以赋值给 void*
void_ptr = &b; // ✅ double* 可以赋值给 void*
int *int_ptr = void_ptr; // ❌ 需要强制转换(C++ 中错误,C 中警告)
int_ptr = (int*)void_ptr; // ✅ 需要显式转换
return 0;
}
查出答案,这个PTA题目本身,是说不能直接赋值,但是dev-C不会报错,看看答案。
课后作业8 1-12
8. 指针可以判断相等,赋值,相减(得到偏移量),但是不能相加!
相减得到ptrdiff_t有符号整数,大小看操作系统。
9. 字符数组初始化的神秘小trick
char s[100]={"hello",};
多一个逗号不会报错,但是只能有一个字符串,如果写了俩会报错。
char s[100]={"hello"," world"};
[Error] excess elements in struct initializer
10. 发现一个二分检查死循环的好方法
mid = (l + r) / 2:mid可能等于lmid = (l + r + 1) / 2:mid可能等于r
可以这样考虑,如果 l 和 r 相差得很远,就没有问题,一直到 l 等于 r 或者 r-1 的时候,特别考虑即可。
实际上,r - l >= 2 的时候,mid 不会等于 l 和 r 中的任何一个。
11. 不要漏读题意……
课后作业8 5-14
是负数吗?
输入一个以#结束的字符串,滤去所有的非十二进制字符(不分大小写),组成一个新的表示十二进制数字的字符串,并输出新的字符串。过滤时,如果在第一个十二进制数字字符前出现-,代表该字符串对应的数是负数,则先输出-,再输出字符串。题目假设过滤后的字符串不为空。
#include <stdio.h>
int main()
{
int flag, i, j;
char str[81], newstr[81];
i = 0;
while ((str[i]=getchar()) != EOF) {
i++;
}
str[i] = '\0';
i = j = 0;
flag = 0;
while (str[i] != '\0') {
if ((str[i] >= '0' && str[i] <= '9') || (str[i] == 'A' || str[i] == 'B')) {
newstr[j] = str[i];
j++;
}
else if (j == 0 && str[i] == '-') {
flag = 1;
}
i++;
}
newstr[j] = '\0';
if (flag == 1) {
putchar('-');
}
for(i = 0; newstr[i] != '\0'; i++) {
putchar(newstr[i]);
}
putchar('\n');
return 0;
}
- 结束表示
#,不是EOF或者别的。 - 不区分大小写,
a和b也是合法的……
可以尝试构造hack样例,然后就会注意到题意。
12. 看清楚程序填空题for后面给没给括号……
13. 三次赋值交换变量值,不要写错。
temp=a[k],a[k]=a[index],a[index]=temp;
我服了,最后一个temp一开始写成a[k]了……
14. 注意数组名称是什么,不要被思维惯性带跑,下意识一维是 a 和 num 之类。
15. 字符数组初始化,如果有给定长度,下面五种写法等价。
static char s[6] = {'H', 'a', 'p', 'p', 'y', '\0'};
static char s[6] = {'H', 'a', 'p', 'p', 'y'};
static char s[6] ="Happy";
static char s[6] ={"Happy"};
static char s[6] = {'H', 'a', 'p', 'p', 'y', 0};
要是没有写数组大小,第二种
static char s[6] = {'H', 'a', 'p', 'p', 'y'};就是错的了!

浙公网安备 33010602011771号