题目描述
在大学里,很多单词都是一词多义,偶尔在文章里还要用引申义。
这困扰 Redraiment 很长的时间,他开始搜集那些单词的所有意义。
他发现了一些规律,例如 a 能用 e 来代替,c 能用 f来代替…… 现在他给出了字母的替换规则,如下所示,A 被 E 替换,B 被 C 替换,依次类推。
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z E C F A J K L B D G H I V W Z Y M N O P Q R S T U X a b c d e f g h i j k l m n o p q r s t u v w x y z e r w q t y g h b n u i o p s j k d l f a z x c v m输入
本题包括多组测试数据。每组测试数据为一行仅由字母和空格组成的字符串(空格不变)。 输入以单行#结束。
输出
对应每组测试数据,替换后输出它的引申义。
输入 Ilttabaje zaujljg # 输出 Different meaning#include <stdio.h> #include <string.h> int main() { // 大写字母映射表 char upper_map[26] = { 'E', 'C', 'F', 'A', 'J', 'K', 'L', 'B', 'D', 'G', 'H', 'I', 'V', 'W', 'Z', 'Y', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'X' }; // 小写字母映射表 char lower_map[26] = { 'e', 'r', 'w', 'q', 't', 'y', 'g', 'h', 'b', 'n', 'u', 'i', 'o', 'p', 's', 'j', 'k', 'd', 'l', 'f', 'a', 'z', 'x', 'c', 'v', 'm' }; char line[1000]; while (1) { // 读取一行,包括空格 if (fgets(line, sizeof(line), stdin) == NULL) break; // 去掉换行符 int len = strlen(line); if (len > 0 && line[len - 1] == '\n') { line[len - 1] = '\0'; len--; } // 检查是否结束(单行#) if (len == 1 && line[0] == '#') break; // 处理每个字符 for (int i = 0; i < len; i++) { char ch = line[i];//将输入的字符存储在ch中 if (ch >= 'A' && ch <= 'Z') { // 大写字母映射 line[i] = upper_map[ch - 'A'];//右侧数组下标,表示的是第几个映射字母 } else if (ch >= 'a' && ch <= 'z') { // 小写字母映射 line[i] = lower_map[ch - 'a']; } // 空格和其他字符不变 } // 输出结果 printf("%s\n", line); } return 0; }一. if (fgets(line, sizeof(line), stdin) == NULL) break;
用途是从标准输入中读取字符,直到遇到1.读取了sizeof(line)-1个字符2.遇到换行符'\n'3.遇到文件结束符。上述三个中的一个情况,就会结束输入。之后自动添加字符串结束符\0到末尾。但会保留换行符\n(如果读取到了)
示例:
假设输入:"Hello\n"
读取后 line 的内容:
索引: 0 1 2 3 4 5 6
字符: 'H' 'e' 'l' 'l' 'o' '\n' '\0'
所以 fgets 包括:
· ✅ 读取的字符(包括换行符 \n)
· ✅ 自动在末尾添加 \0
· ❌ 不读取字符串结束符本身,而是自动添加
上述代码中去掉换行符流程是基于上述fgets的读取原则:
处理流程:示例:
1. fgets 读取输入,例如:"test\n"
2. line 变成:"test\n\0"
3. strlen(line) 返回 5('t','e','s','t','\n')//返回字符串的长度不包括字符串结束符,但包括换行符
4. 检查最后一个字符是 \n,将其替换为 \0
5. line 现在:"test\0\0"(有两个\0,但第一个有效)
6. len 减为 4
在本题中fgets的运行过程:
读取的内容:"Ilttabaje zaujljg\n"
· 自动在末尾添加 \0
步骤2:读取后 line 的内容:
索引: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
字符: 'I' 'l' 't' 't' 'a' 'b' 'a' 'j' 'e' ' ' 'z' 'a' 'u' 'j' 'l' 'i' 'g' '\n' '\0'
步骤3:处理换行符
int len = strlen(line); // len = 18(包括换行符)
if (len > 0 && line[len - 1] == '\n') {
line[len - 1] = '\0'; // 去掉换行符
len--; // len = 17
}
现在 line 的内容:
"Illtabaje zaujlig\0"
长度:17个字符
二.if (len == 1 && line[0] == '#') break;
上述代码if条件语句有两个成立条件,和之前做过的题有些一样。第一个条件,只要len不等于1都不成立,都不会结束循环。会继续往下运行。只有#以单行形式出现时才会结束循环,结束程序。要想写出这个条件,只需要仔细看题目。
也可以用下面代码替换fgets
gets(line); int len = strlen(line); // 检查是否结束(单行#) if (len == 1 && line[0] == '#') break;gets()1.遇到换行符\n停止2.不存储换行符3.自动在末尾添加字符串换行符\0
上述gets()输入的刚好是fgets()去掉换行符后的字符串内容,所以刚好去掉处理换行符这一步骤。
示例输入:
输入:"Hello World\n"
gets() 读取后
索引: 0 1 2 3 4 5 6 7 8 9 10 11
字符: 'H' 'e' 'l' 'l' 'o' ' ' 'W' 'o' 'r' 'l' 'd' '\0'
三.看到字母肯定想到要找规律,但是在ASCII码上没有数学规律;根本找不出规律,所以考虑是固定的替换表,所以将映射大小写字母用数组表示出来,然后根据下标循环替换。