iT邦幫忙

2021 iThome 鐵人賽

DAY 3
1
自我挑戰組

用 C & C++ 帶你手把手解 UVa 一顆星選集系列 第 3

Day 0x3 UVa10222 Decode the Mad man

Virtual Judge
ZeroJudge

題意

  • 輸入一加密過字串,解密方式為鍵盤上向左兩格,輸出解密結果
  • 需要注意的點:
    1. 只有一筆測資 (單行)
  • 隱藏要點:
    1. 不會有不合理的輸入
    2. 輸入都是小寫

      我看 ZOJ 題目寫的,原文好像沒看到,但大家好像都會特別轉小寫???

解法

  • 輸入可能是一或多個字元 (含空白),因此用 gets() 或其他可忽略空白之寫法來讀取,並存到字元陣列

    gets() 是個不安全的函式,但...反正解題嘛

    char str[999] = {0};
    gets(str);
    
  • 解密方法
    • for 迴圈去逐字元檢查 & 解密
    • 方式有很多,這邊簡單列舉幾個而已,有興趣的可以自己查一下其他大神精闢寫法
    • switch 工人智慧版
      • 反正一星題嘛,複製貼上應該也寫很快 (?
      for(i = 0; i < strlen(str); i++){
          switch(str[i]){
              case 32:
                  printf(" ");
                  break;
              case 'e':
                  printf("q");
                  break;
              case 'd':
                  printf("a");
                  break;
              case 'c':
                  printf("z");
                  break;
              case 'r':
                  printf("w");
                  break;
              case 'f':
                  printf("s");
                  break;
              case 'v':
                  printf("x");
                  break;
              case 't':
                  printf("e");
                  break;
              case 'g':
                  printf("d");
                  break;
              case 'b':
                  printf("c");
                  break;
              case 'y':
                  printf("r");
                  break;
              case 'h':
                  printf("f");
                  break;
              case 'n':
                  printf("v");
                  break;
              case 'u':
                  printf("t");
                  break;
              case 'j':
                  printf("g");
                  break;
              case 'm':
                  printf("b");
                  break;
              case 'i':
                  printf("y");
                  break;
              case 'k':
                  printf("h");
                  break;
              case ',':
                  printf("n");
                  break;
              case 'o':
                  printf("u");
                  break;
              case 'l':
                  printf("j");
                  break;
              case '.':
                  printf("m");
                  break;
              case 'p':
                  printf("i");
                  break;
              case ';':
                  printf("k");
                  break;
              case '/':
                  printf(",");
                  break;
              case '[':
                  printf("o");
                  break;
              case '\'':
                  printf("l");
                  break;
              case ']':
                  printf("p");
                  break;
              case '\\':
                  printf("[");
                  break;
              case '=':
                  printf("0");
                  break;
              case '-':
                  printf("9");
                  break;
              case '0':
                  printf("8");
                  break;
              case '9':
                  printf("7");
                  break;
              case '8':
                  printf("6");
                  break;
              case '7':
                  printf("5");
                  break;
              case '6':
                  printf("4");
                  break;
              case '5':
                  printf("3");
                  break;
              case '4':
                  printf("2");
                  break;
              case '3':
                  printf("1");
                  break;
              case '2':
                  printf("`");
                  break;
          }
      }
      
    • 建表法 ver. 1
      • 因為不會有不合理的輸入
      1. 把鍵盤上每個按鍵都先存到字元陣列裡
      2. 逐字檢查時先過濾掉空白字元
      3. 解密時便查找 1. 的表,找到就輸出往前第二個字元
      char table[ ] = "`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./";
      ...
      for(j = 0; j < strlen(table); j++){
          if(str[i] == table[j]){
              printf("%c", table[j - 2]);
              break;
          }
      }
      
    • 建表法 ver. 2
      • 建立兩張表,分別對應輸入與輸出,即為加密後與解密後的字串,因此兩陣列長度一樣,但建表時需小心鍵盤上每列起始與結束的不同
      • 陣列直接存入空白,因此處理字串時不用預先過濾
      char ct[ ] = " 234567890-=ertyuiop[]\\dfghjkl;'cvbnm,./";
      char pt[ ] = " `1234567890qwertyuiop[asdfghjklzxcvbnm,";
      
  • C Code
    #include<stdio.h>
    #include<string.h>
    
    int main(){
    
        char str[999] = {0};
        char ct[ ] = " 234567890-=ertyuiop[]\\dfghjkl;'cvbnm,./";
        char pt[ ] = " `1234567890qwertyuiop[asdfghjklzxcvbnm,";
        int i, j;
    
        gets(str);
    
        for(i = 0; i < strlen(str); i++){
            for(j = 0; j < strlen(ct); j++){
                if(str[i] == ct[j]){
                    printf("%c", pt[j]);
                }
            }
        }
    
        printf("\n");
    
        return 0;
    }
    
  • C++
    • 可以運用 string 來處理字串
    • 查找時用 string::find 更簡短
    • Reference
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
    
        string str;
        string table = "`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./";
    
        getline(cin, str);
    
        for(int i = 0; i < str.size(); i++){
            if(str[i]  == ' '){
                cout << " ";
            }
            else{
                cout << table[table.find(str[i]) - 2];
            }
        }
    
        cout << "\n";
    }
    

上一篇
Day 0x2 UVa11150 Cola
下一篇
Day 0x4 UVa10041 Vito's Family
系列文
用 C & C++ 帶你手把手解 UVa 一顆星選集30

尚未有邦友留言

立即登入留言