題目要求比較明確,可能做起來難度不是很大。
但我這道題用了比較久的時間。
原因是我用了一種特別容易錯的方法。我在移動陣列元素的時候採用不用輔助陣列由前往後複製的方法(想來我也真是沒事找事幹),然後在這種方法下我起初交了許多遍WA,然後自己經過長時間的測試終於發現了問題所在,不止一個,各種邏輯錯誤。
總結主要有以下幾點:
- 分類討論不夠明確,不夠完整
- 沒有考慮到前邊操作對後邊資料的影響
- 沒有意識到陣列越界的後果(a[-1],a[maxn])
要發現和解決這些問題並不容易,需要有很高的除錯技巧,通過這個題的練習,也積累了一些經驗:在不使用gdb的情況下,通過在恰當的位置輸出中間值來進行測試是相當重要的。關鍵在於如何選擇恰當的位置。選擇的位置不好,看不出啥問題來,還顯著輸出結果很亂。
下邊展開說一下導致邏輯錯誤的三大原因。
首先,分類討論的問題。
分類討論首先想到的是頭尾可能需要特殊考慮。比如這題。在最後插入輸入的情況下不需要往後複製東西,要是執意複製可能導致陣列越界。
這就引出了第三個問題,陣列越界。
陣列越界是一個神奇的東西。我第一次發現A[-1]竟然是一個合法的東西(意思是這個陣列前邊的資料),第一次發現陣列越界一位之後恰好把定義在他後邊的變數修改了導致輸出超限。導致這個的原因經過百度與C程式記憶體結構有關係。
關於第二個問題,我的錯誤在於迴圈結束條件已經在迴圈中被修改過了。不仔細找真的不太好改此類錯誤,以後應該加強這方面經驗的積累。
下邊貼一下這次作業的程式碼,以備日後檢視。
#include <stdio.h> #define MAX_SIZE 1001 int getkey(int key[]){ int k; scanf("%d",&k); for(int i=0;i<k;i++)scanf("%d",&key[i]); return k; } int getarray(int array[]){ int i=0; while(scanf("%d",&array[i])==1&&array[i]!=0)i++; if(i<MAX_SIZE-1)array[MAX_SIZE-1]=-1; return 0; } int insert(int array[], int key, int vol){ int i=0; if(array[vol]==0)return -2; while(key>array[i]&&array[i]!=0)i++; if(array[i]==key)return -1; else{ int t1=array[i]; int t2=1; int j=i; if(t1)for( j=i;!j||t2;j++){ t2=array[j+1]; array[j+1]=t1; t1=t2; } array[j+1]=0; array[i]=key; return i; } } int result(int flag){ if(flag==-1)printf("The key is already in this array!"); else if(flag==-2)printf("The array if full!"); else { printf("The key is inserted in position %d.",flag); } printf("\n"); return 0; } int main() { int array[MAX_SIZE], cases, ca, i, key[MAX_SIZE], size; scanf("%d", &cases); for(ca = 1; ca <= cases; ca++) { getarray(array); size = getkey(key); printf("Case %d:\n", ca); for(i = 0; i < size; i++){ result(insert(array, key[i], MAX_SIZE - 1)); // array[1001]=2; } } return 0; }