第二篇連結:字串類習題、面試題詳解(第二篇)
1題:WERTYU(競賽基礎題)
把手放在鍵盤上時,稍不注意就會往右錯一位,這樣的話Q會變為W,J會變為K等。輸入一個錯位後敲出的字串,輸出打字員本來想打出的句子。
樣例輸入:O S, GOMR YPFSU/
樣例輸出:I AM FINE TODAY.
1 #include <stdio.h> 2 const char *str = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./"; 3 4 int main(void) 5 { 6 char c; 7 int i; 8 while ((c = getchar()) != EOF) 9 { 10 for (i = 0; str[i] && str[i] != c; i++); 11 if (str[i]) 12 putchar(str[i - 1]); 13 else 14 putchar(c); 15 } 16 17 return 0; 18 }
解析:本題注意兩點:(1)for迴圈終止條件的判斷,常量字串末尾自動補“\0”,因而可利用str[i]的取值判斷是否查詢到最後一個字元。(2)反斜線“\”是特殊字元,需要使用轉義序列或直接引用其ASCII碼。
2題:TeX括號(競賽基礎題)
在TeX中,左雙引號是``,右雙引號是’’。輸入一篇包含雙引號的文章,你的任務是把它轉換成TeX格式。
樣例輸入:
“To be or not to be,” quoth the Bard, “thatis the question”.
樣例輸出:
``To be or not to be,” quoth the Bard,``that is the question”.
1 #include <stdio.h> 2 3 int main(void) 4 { 5 char c; 6 int q = 1; 7 while ((c = getchar()) != EOF) 8 { 9 if (c == '"') 10 { 11 printf("%s", q ? "``" : "''"); 12 q = !q; 13 } 14 else 15 printf("%c", c); 16 } 17 18 return 0; 19 }
解析:本題的關鍵是如何判斷一個雙引號是左雙引號還是右雙引號。
3題:週期串(競賽基礎題)
如果一個字串可以由某個長度為k的字串重複多次得到,我們說該串以k為週期。例如,abcabcabcabc以3為週期(注意,它也以6和12為週期)。輸入一個長度不超過80的串,輸出它的最小週期。
樣例輸入:HoHoHo
樣例輸出:2
寫法1:
1 #include <stdio.h> 2 #include <string.h> 3 #define MAXLEN 80 4 int main(void) 5 { 6 char str[MAXLEN + 1] = {0}; 7 scanf("%s", str); 8 int len = strlen(str); 9 int result = len; 10 int i, j; 11 12 for (i = 1; i < len / 2 + 1; i++) //i為週期 13 { 14 for (j = 0; j < len - i; j++) 15 { 16 if (str[j] != str[j + i]) 17 break; 18 } 19 20 if (j == len - i) 21 { 22 result = i; 23 break; 24 } 25 } 26 printf("%d\n",result); 27 28 return 0; 29 }
寫法2:
1 #include <stdio.h> 2 #include <string.h> 3 int main(void) 4 { 5 char word[100]; 6 scanf("%s", word); 7 int len = strlen(word); 8 int i, j; 9 10 for (i = 1; i <= len; i++) 11 { 12 if (len % i == 0) 13 { 14 int ok = 1; 15 for (j = i; j < len; j++) 16 if (word[j] != word[j % i]) 17 { 18 ok = 0; 19 break; 20 } 21 if (ok) 22 { 23 printf("%d\n", i); 24 break; 25 } 26 } 27 } 28 29 return 0; 30 }
解析:本題兩種解法的思路是一致的。
4題:編寫一個函式,把一個char組成的字串迴圈右移n位。例如:原來是”abcdefghi”,如果n = 2,移位後應該是”hiabcdefg”。(面試題)
1 #include <stdio.h> 2 #include <string.h> 3 #define MAX_LEN 1024 4 5 void LoopMove_1(char *pStr, int steps) 6 { 7 int len = strlen(pStr) - steps; 8 char temp[MAX_LEN]; 9 10 strcpy(temp, pStr + len); 11 strcpy(temp + steps, pStr); 12 *(temp + steps + len) = '\0'; 13 strcpy(pStr, temp); 14 } 15 16 void LoopMove_2(char *pStr, int steps) 17 { 18 int len = strlen(pStr) - steps; 19 char temp[MAX_LEN]; 20 21 memcpy(temp, pStr + len, steps); 22 memcpy(temp + steps, pStr, len); 23 memcpy(pStr, temp, len + steps); 24 } 25 26 int main(void) 27 { 28 char str1[] = "abcdefghi"; 29 LoopMove_1(str1, 3); 30 printf("%s\n", str1); 31 32 char str2[] = "gklmnopqrst"; 33 LoopMove_1(str2, 3); 34 printf("%s\n", str2); 35 return 0; 36 }
解析:本題提供了兩種方法。
5題:編寫程式,從鍵盤輸入一組任意長度的字串,當輸入“#”符時結束輸入(字串不包括“#”),然後程式反向輸出該字串。(面試題)
方法1:將輸入的字串儲存在一個資料結構中,然後將其內容反向輸出。例如:首先申請一個棧,每輸入一個字元時都將該字元做入棧操作,直到入棧佇列中發現“#”為止(“#”不入棧)。然後再將棧中的元素順序出棧。
1 #include <stdio.h> 2 #define MAX_LEN 1024 3 4 int main(void) 5 { 6 char arr[MAX_LEN], c; 7 int i = 0, j; 8 while ((c = getchar()) != '#') 9 { 10 arr[i++] = c; 11 } 12 arr[i] = '\0'; 13 14 for (j = i - 1; j >= 0; j--) 15 { 16 printf("%c", arr[j]); 17 } 18 printf("\n"); 19 20 return 0; 21 }
方法2:題目沒要求儲存輸入的字串,因此可用遞迴解此題。遞迴演算法本身有棧的特性,每次遞迴地呼叫遞迴函式時,系統都會將現場儲存在棧中,待呼叫結束返回時再恢復現場的內容。
1 #include <stdio.h> 2 3 void StrRev() 4 { 5 char c; 6 scanf("%c", &c); 7 if ('#' == c) 8 { 9 printf("反轉後的字串:"); 10 return; 11 } 12 13 StrRev(); 14 printf("%c", c); 15 } 16 17 int main(void) 18 { 19 printf("請輸入英文字串(以#結束):"); 20 StrRev(); 21 printf("\n"); 22 return 0; 23 }