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這樣跳過空白字元的函式就不行了。我一開始就用的逐字元讀取的方法,每次讀到換行,一直都沒有發覺這一點……
所以相應思路也就出來了:
- 定義ASCII的128個整形字串,初始為0;
- 讀到一個壞鍵,將其都轉化為大寫字母,就置為1,這樣知道哪個件事壞的。當然前提是讀到換行為止,同時只要置為1就可以,壞鍵一般也就出現一次吧,兩次置為1也完全沒問題呀;
- 讀到第二個字串時,如果不是壞鍵(也就是值為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;
}