這一章講控制流程,基本就是if-else、while、do-while、switch-case之類的。基本的東西大家都懂。需要強調的是在預設狀態下,if-else語句中的else是與之前最近的if匹配的,所以如果這不是你的本意,那麼最好加上大括弧括起來。其實我幾乎不會犯這個錯誤,因為我寫程式時,習慣於即便if後面只有一條語句,我也會打上括弧(這個習慣好像是看C++primer上養成的)。
書中給出了一個shell排序演算法的程式
void shellsort(int V[], int n){int gap, i, j, temp;for (gap = n/2; gap > 0; gap /= 2)for (i = gap; i < n; i++)for (j = i-gap; j>=0 && V[j]>V[j+gap]; j -= gap) {temp = V[j];V[j] = V[j+gap];V[j+gap] = temp;}}
恕我愚鈍,我至今還沒有完全弄明白它是怎麼搞的。一般人的shell排序演算法寫不了這麼簡潔。
這個程式也讓我感想頗多,大牛有時候是不一定會考慮小白們的感受的,就好比有時候數學書上的一句“顯然……”,就可能難倒一大片學生。不光是中國人喜歡簡潔、漂亮的東西(比如同濟的《高等數學》,其實那本書寫的很不錯),國外的人也一樣。但是國外的入門書籍一般都會煞費苦心的蘿莉囉嗦的講很多東西,國內的很多書可沒有這個耐心。
書裡面有個習題很有意思,就是將數字轉化為對應的字串:
void itoa(int n, char s[]){int i, sign;if ((sign = n) < 0) /* record sign */n = -n; /* make n positive */i = 0;do { /* generate digits in reverse order */s[i++] = n % 10 + '0'; /* get next digit */} while ((n /= 10) > 0); /* delete it */if (sign < 0)s[i++] = '-';s[i] = '\0';reverse(s);}
但是在習題中,告訴你這個程式是不能轉化最小的負數的:即-2^(n-1),這是因為通過程式,可以看出,這段代碼先提取加號或減號,然後把剩下的數字轉化為對應的字元。但是當遇到最小的負數時,因為n位能表達的最大的數字是2^(n-1)-1(有一位用作符號位了),所以不能簡單地採用對於負數,先求出他的相反數,然後利用這個相反數化成字串,最後在前面補上負號來實現。對於這種特殊的情況,可以採用對於每次求模運算時計算絕對值,最後補上負號來繞過這個問題:
#define abs(x) ((x)<0 ? -(x):(x))void reverse(char s[]){int c, i , j;for(i = 0, j = strlen(s)-1;i < j;i++,j--){c = s[i];s[i] = s[j];s[j] = c;}}void itoa(int n, char s[]){int i ,sign;sign = n;i = 0;do{s[i++] = abs(n % 10) + '0';}while((n /= 10) != 0);if(sign < 0)s[i++] = '-';s[i] = '\0';reverse(s);}
這個例子也提醒我們,寫程式時,有時候還是需要注意體層和一些邊界值情況,否則有可能出錯的。