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