C 語言初學教材 - 第四章 刪除使用者帳號

如果要刪除使用者的帳號,有個簡單的想法就是拷貝空字串給要刪除的帳號位置,這樣一來,儲存該帳號的字元陣列就會變成空字串

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
if (!strcmp(instruction, "delete")) {
    state = N;
                             
    printf("\n請輸入要刪除的帳號: ");
    scanf("%s", searchname);
                             
    for (j = 0; j < SIZE; j++) {
        if (!strcmp(userID[j], searchname)) {
            state = Y;
            break;
        }
    }
                             
    if (state == Y) {
        strcpy(userID[j], "");
        strcpy(userCODE[j], "");
                                 
        printf("\n%s 的帳號資料已刪除\n", searchname);
    }
    else if (state == N) {
        printf("\n%s 的帳號資料不存在,無法刪除\n", searchname);
    }
    continue;
}


一開始跟搜尋是同樣的作法,要求管理員先輸入要刪除的帳號,然後做線性搜尋找到後用變數 j 記下該帳號的索引值,然後就把空字串拷貝進去,這樣一來,帳號就刪除了。


完整的範例程式碼及編譯執行,請繼續參考


可是這樣會有個問題,如果我們刪除某個前面、後面都有資料的帳號,我們去列印帳號名單會發生刪除帳號後面的資料不見的情況,雖然查詢還是找得到,問題是列印不出來。


為什麼會這樣子呢?想一想,其實發生的原因很簡單的,就是因為我們在列印功能裡添加了遇到空字串就結束列印的機制,所以遇到空字串就會列印不出來,要解決這個問題也很簡單,把 break 改成 continue 就行了,就會把 userID 中有內容的字串都印出來。


可是這樣刪除一個帳號,就平凡無故就佔去 userID 的一個空間, userID 的可用空間就變成 SIZE - 1 ,如果我們刪除了很多個使用者,會導致 userID 沒有空間繼續儲存新的帳號,因此程式執行會發生錯誤。


當然,加大 SIZE 會是一個解決方式,但這樣還是不太實際,所以我們提供另一個解決方法
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
if (!strcmp(instruction, "delete")) {
    state = N;
                             
    printf("\n請輸入要刪除的帳號: ");
    scanf("%s", searchname);
                             
    for (j = 0; j < SIZE; j++) {
        if (!strcmp(userID[j], searchname)) {
            state = Y;
            counter--;
            break;
        }
    }
                             
    if (state == Y) {
        for (j; j < SIZE; j++) {
            strcpy(userID[j], userID[j + 1]);
            strcpy(userCODE[j], userCODE[j + 1]);
        }
                                 
        printf("\n%s 的帳號資料已刪除\n", searchname);
    }
    else if (state == N) {
        printf("\n%s 的帳號資料不存在,無法刪除\n", searchname);
    }
    continue;
}


我們提供的解決方法在第 141 行到第 143 行
141
142
143
144
for (j; j < SIZE; j++) {
   strcpy(userID[j], userID[j + 1]);
   strcpy(userCODE[j], userCODE[j + 1]);
}


也就是把 j + 1 拷貝給 j ,這樣索引 j 的陣列內容就會被 j + 1 的內容所取代,也就是說,我們依序把後面的元素向前移一個位置,因此完成刪除的工作。


另外要注意在第 134 行
134
counter--;


變數 counter 要做遞減,不然就沒有節省空間的效果了。


完整的範例程式碼及編譯執行,請繼續參考


問題與討論
  1. 第一個刪除帳號的方式有什麼優缺點?
  2. 把列印指令中的 break 改成 continue 有什麼優缺點?
  3. 想一想,還有其他刪除帳號資料的方法嗎?




沒有留言: