大侦探福尔摩斯接到一张奇怪的字条:我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm。大侦探很快就明白了,字条上奇怪的乱码实际上就是约会的时间星期四 14:04,因为前面两字符串中第 1 对相同的大写英文字母(大小写有区分)是第 4 个字母 D,代表星期四;第 2 对相同的字符是 E ,那是第 5 个英文字母,代表一天里的第 14 个钟头(于是一天的 0 点到 23 点由数字 0 到 9、以及大写字母 A 到 N 表示);后面两字符串第 1 对相同的英文字母 s 出现在第 4 个位置(从 0 开始计数)上,代表第 4 分钟。现给定两对字符串,请帮助福尔摩斯解码得到约会的时间。
输入格式:
输入在 4 行中分别给出 4 个非空、不包含空格、且长度不超过 60 的字符串。
输出格式:
在一行中输出约会的时间,格式为 DAY HH:MM,其中 DAY 是某星期的 3 字符缩写,即 MON 表示星期一,TUE 表示星期二,WED 表示星期三,THU 表示星期四,FRI 表示星期五,SAT 表示星期六,SUN 表示星期日。题目输入保证每个测试存在唯一解。
输入样例:
3485djDkxh4hhGE
2984akDfkkkkggEdsb
s&hgsfdk
d&Hyscvnm
输出样例:
THU 14:04
#include<stdio.h>
#include<string.h>
#define N 61
int isWord(char msg){
return msg >= 'a' && msg <= 'z' || msg >= 'A' && msg <= 'Z';
}
int main(){
char msg[4][N],day,hour;//day表示星期几,hour表示几点
int i,j,len1,len2,count = 1;//count用来判断是否为1,2个字符串中第一对相同的大写字母
for(i = 0; i < 4; i++)
gets(msg[i]);
//获取前两个字符串中第一对和第二对相同的大写英文字母
len1 = strlen(msg[0]);
len2 = strlen(msg[1]);
for(i = 0; i < len1 && i < len2; i++){
/*
如果当前的字符相同,我们并不能直接将其赋值给day,我们还需要判断当前
的字符是否是我们想要的(也就是各个信息对应的字符范围我们也需要考
虑),因为字符相同的时候,可能这些字符是其他的字符,比如'!',','之类
的
*/
if(msg[0][i] == msg[1][i]){
if(count == 1){
//如果count为1,并且当前的字符范围是再A~G,这是我们需要的,将其赋值给day
if(msg[0][i] >= 'A' && msg[0][i] <= 'G'){
day = msg[0][i];
count++;
}
}else{
/*如果count不为1,表明已经找到了第一队相同的大写字母,所以我
们开始寻找day了,由于day的范围是0~9,A~N,所以再字符相同的情
况下,我们只要直到其中一个字符msg[0][i]是否是再0~9,A~G的范
围就可以了,而不用再判断msg[1][i]是否也在这个范围了
*/
if(msg[0][i] >= '0' && msg[0][i] <= '9' || msg[0][i] >= 'A' && msg[0][i] <= 'N'){
hour = msg[0][i];
break;
}
}
}
}
len1 = strlen(msg[2]);
len2 = strlen(msg[3]);
for(i = 0; i < len1 && i < len2; i++){
if(msg[2][i] == msg[3][i] && isWord(msg[2][i])){
/*
如果当前的字符相同,并且msg[2][i]的范围是英文字母,那么我们就表明
当前字符的下标是我们想要的,直接退出循环
*/
break;
}
}
//利用switch语句,将星期/时间输出
switch(day){
case 'A': printf("MON ");break;
case 'B': printf("TUE ");break;
case 'C': printf("WED ");break;
case 'D': printf("THU ");break;
case 'E': printf("FRI ");break;
case 'F': printf("SAT ");break;
case 'G': printf("SUN ");break;
}
switch(hour){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
printf("0%c:",hour);
break;
case 'A': printf("10:");break;
case 'B': printf("11:");break;
case 'C': printf("12:");break;
case 'D': printf("13:");break;
case 'E': printf("14:");break;
case 'F': printf("15:");break;
case 'G': printf("16:");break;
case 'H': printf("17:");break;
case 'I': printf("18:");break;
case 'J': printf("19:");break;
case 'K': printf("20:");break;
case 'L': printf("21:");break;
case 'M': printf("22:");break;
case 'N': printf("23:");break;
}
printf("%02d\n",i);
return 0;
}
通过上面的代码,我们可以看到,使用了大量的switch结构,可不可以再找到这个字符之后,将其输出呢?所以请看下面的优化代码:
#include<stdio.h>
#include<string.h>
#define N 61
int isWord(char msg){
return msg >= 'A' && msg <= 'Z'|| msg >= 'a' && msg <= 'z';
}
int main(){
char msg[4][N],week[7][4] = {"MON","TUE","WED","THU","FRI","SAT","SUN"};
int i,len1,len2,count = 1;
for(i = 0; i < 4; i++)
gets(msg[i]);
//获取前两个字符串中第一对和第二对相同的大写英文字母
len1 = strlen(msg[0]);
len2 = strlen(msg[1]);
for(i = 0; i < len1 && i < len2; i++){
if(msg[0][i] == msg[1][i]){
//如果当前的字符相同,那么不可以直接就将器输出,因为有可能字符相同的是其他字符,比如'!',','这样的字符,所以我们需要避免这种情况
if(count == 1){
//count等于1表明的是第一对相同的字符
if(msg[0][i] >= 'A' && msg[0][i] <= 'G'){
//如果这个字符是A~G,那么这才是我们想要的,因为题目要求是A~G是星期的,同时这样我们也避免上面说到的其他字符相同的情况
如果msg[0][i]是A,那么再week数组种的下标为0,所以如果msg[0][i]是B,那么减去'A',刚好等于1,对应week种的下标为1,输出TUE
printf("%s ",week[msg[0][i] - 'A']);
count++;
}
}else{
//由于hour输出的时候,对应的字符是0~9,A~N,所以如果count!=1的时候我们需要判断当前的字符是否是这样的范围
//将对应的数字输出之后,我们就退出循环
if(msg[0][i] >= '0' && msg[0][i] <= '9'){
printf("0%c:",msg[0][i]);
break;
}else if(msg[0][i] >= 'A' && msg[0][i] <= 'N'){
//如果是A~G,那么我们需要输出的是数字,这时候我们假设当前的字符是A,那么输出的是msg[0][i] - 'A' + 10 = 10,
//同样的,如果当前的字符msg[0][i]是B,那么输出为msg[0][i] - 'A' + 10 = 11
printf("%d:",msg[0][i] - 'A' + 10);
break;
}
}
}
}
len1 = strlen(msg[2]);
len2 = strlen(msg[3]);
for(i = 0; i < len1 && i < len2; i++){
if( msg[2][i] == msg[3][i] && isWord(msg[2][i])){
//判断当前的字符相同,同时,我们还需要判断当前的字符是否是英文字符,如果是,那么就将其下标输出之后跳出循环,否则继续循环
printf("%02d\n",i);
break;
}
}
return 0;
}