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) / 2mid 可能等于 l
  • mid = (l + r + 1) / 2mid 可能等于 r

可以这样考虑,如果 lr 相差得很远,就没有问题,一直到 l 等于 r 或者 r-1 的时候,特别考虑即可。

实际上,r - l >= 2 的时候,mid 不会等于 lr 中的任何一个。

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或者别的。
  • 不区分大小写,ab 也是合法的……

可以尝试构造hack样例,然后就会注意到题意。

12. 看清楚程序填空题for后面给没给括号……

13. 三次赋值交换变量值,不要写错。

temp=a[k],a[k]=a[index],a[index]=temp;

我服了,最后一个temp一开始写成a[k]了……

14. 注意数组名称是什么,不要被思维惯性带跑,下意识一维是 anum 之类。

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'}; 就是错的了!

posted @ 2025-11-19 11:24  Zlc晨鑫  阅读(12)  评论(0)    收藏  举报