1. 程式人生 > >PAT Basic 1033. 舊鍵盤打字(20)——c實現

PAT Basic 1033. 舊鍵盤打字(20)——c實現

題目
   

舊鍵盤上壞了幾個鍵,於是在敲一段文字的時候,對應的字元就不會出現。現在給出應該輸入的一段文字、以及壞掉的那些鍵,打出的結果文字會是怎樣?

    輸入格式:

    輸入在2行中分別給出壞掉的那些鍵、以及應該輸入的文字。其中對應英文字母的壞鍵以大寫給出;每段文字是不超過10^5個字元的串。可用的字元包括字母[a-z, A-Z]、數字0-9、以及下劃線“_”(代表空格)、“,”、“.”、“-”、“+”(代表上檔鍵)。題目保證第2行輸入的文字串非空。

    注意:如果上檔鍵壞掉了,那麼大寫的英文字母無法被打出。

    輸出格式:

    在一行中輸出能夠被打出的結果文字。如果沒有一個字元能被打出,則輸出空行。

    輸入樣例:
    7+IE.
    7_This_is_a_test.
    輸出樣例:
    _hs_s_a_tst

思路

這道題目開始沒有特別明確的思路。想著用兩個字串進行儲存,然後逐個比對,但是還需要第三個字串去儲存特殊的字元才行……總之沒有特別好的思路。

學習了一下網上的教程,比較好的思路是這樣的:

    讀取:在記錄壞鍵的時候很多種鍵,但是都是ASCII字元,因此用一個int[128]陣列記錄就好了,一視同仁,簡單粗暴。
    輸出:第二行是不會有'+'符號的,因此除了大寫字母要特殊判斷,只要這個鍵沒有壞(陣列沒有記錄),不管是哪一類符號,輸出就行了。
    使用邊讀取邊處理的方式,空間佔用降到最低。
    toupper函式對非字母字元會返回引數本身,因此記錄/查詢的時候不必區分字元型別,全都轉換成大寫。

這種方法比有多少種字元就建立多大的陣列去記錄要方便的多,程式碼量極少。

注意:第一行可能為空,使用scanf這樣跳過空白字元的函式就不行了。我一開始就用的逐字元讀取的方法,每次讀到換行,一直都沒有發覺這一點……

所以相應思路也就出來了:

  1. 定義ASCII的128個整形字串,初始為0;
  2. 讀到一個壞鍵,將其都轉化為大寫字母,就置為1,這樣知道哪個件事壞的。當然前提是讀到換行為止,同時只要置為1就可以,壞鍵一般也就出現一次吧,兩次置為1也完全沒問題呀;
  3. 讀到第二個字串時,如果不是壞鍵(也就是值為1,!bad[toupper(c)]),同時還不是大寫字母,這裡“+”的特殊性。如果是+,同時判斷讀到的是不是大寫字母,這裡用到了<ctype.h>的isupper函式。如果是,則仍不輸出。思路有一些亂,整理下是這樣的:只需要判斷輸出的條件,如果輸出第二行的字元,說明字元本身不是壞鍵,同時還得滿足如果是大寫字母,那第一行中就沒有“+”。

程式碼如下:

//PAT1033V1
#include <stdio.h>
#include <ctype.h>
int main()
{
    char c;
    int bad[128] = {0}; /* record keys are broken or not */
 
    while((c = getchar()) != '\n')      /* read broken keys */
        bad[toupper(c)] = 1;
 
    while((c = getchar()) != '\n')      /* read string and print */
        if(!bad[toupper(c)] && !(isupper(c) && bad['+']))
              putchar(c);

    return 0;
}