首页 > 其他分享 >DOTCPP_1468_蓝桥杯基础练习VIP-报时助手

DOTCPP_1468_蓝桥杯基础练习VIP-报时助手

时间:2022-10-20 08:55:26浏览次数:69  
标签:10 小时数 20 输出 VIP 蓝桥 DOTCPP printf timeword

1.题目链接

题目 1468: 蓝桥杯基础练习VIP-报时助手

2.解题思路

2.1 题意解析

本题的目的是要完成报时功能,即根据输入的小时数h和分钟数m的值,按照报时规则输出对应的英文输出。这里需要注意题目中关于输入的说明“非零的数字前没有前导0,h小于24,m小于60”,这意味着“21:05”对应的输入应该是“21 5”,这样规定实质上降低了编码解题的难度。我们再来看输出,构成输出的要素如下表所示,

数字 英文 数字 英文 数字 英文
0 zero 1 one 2 two
3 three 4 four 5 five
6 six 7 seven 8 eight
9 nine 10 ten 11 eleven
12 twelve 13 thirteen 14 fourteen
15 fifteen 16 sixteen 17 seventeen
18 eighteen 19 nineteen 20 twenty
30 thirty 40 forty 50 fifty
时刻 o'clock

本题期待的输出即为表中给出元素按规则的组合。

2.2 报时逻辑

弄清楚题意后,我们可以简单总结一下报时的基本规则,主要分为整点报时非整点报时两种情况,下面逐一说明:

  • 整点报时:当m为0表示整点报时,例如输入“3 0”表示的是“3:00”,程序应该输出“three o'clock”。
  • 非整点报时:当m不为0表示非整点报时,此时又分为两种情况考虑。
    • m小于20:此时m的取值可以是1、2、3、4、5、6、7、8、9、10、11、12、13、14、15、16、17、18、或19,我们应该采用one、two、three、four、five、six、seven、eight、nine、ten、eleven、twelve、thirteen、fourteen、fifteen、sixteen、seventeen、eighteen、nineteen。
    • m大于20且m为20、30、40或50等10的倍数时:我们应该采用twenty、thirty、forty或fifty。
    • m大于20且m的值无法被10整除的情况:这时我们要分别采用整除m / 10)和取余m % 10)确定十位和个位的数值,然后输出对应的英文表示。

3. 编程实现

3.1 实现过程

  1. 首先定义两个int型变量,实现小时数和分钟数这两个变量的输入。
//h保存小时数,m保存分钟数
int h, m;
  1. 这里我们考虑一下最复杂的情况,即小时数h不为0,分钟数m不为0,h大于20且小于24,m大于20且小于60,这种情况我们要分别确定h和m的十位数和个位数,所以我们定义四个int型变量来保存这些数。
//hshiwei保存小时数的十位,hgewei保存小时数的个位,mshiwei保存分钟数的十位,mgewei保存分钟数的个位
int hshiwei, hgewei, mshiwei, mgewei;
  1. 输入题目所给的两个变量。
//输入小时数和分钟数
scanf("%d%d", &h, &m);
  1. 为了方便后续的代码实现,这里我们将所有英文表示存放在数组中,这里也是本题的难点1:使用char型二维数组存储数据
  • 首先,我们评估一下,需要存储的英文单词包括zero、one、two、three、four、five、six、seven、eight、nine、ten、eleven、twelve、thirteen、fourteen、fifteen、sixteen、seventeen、eighteen、nineteen、twenty、thirty、forty、fifty和o'clock,一共有25个,因此我们确定char型二维数组的第一个维度是20。
  • 其次,我们再看这25个英文单词中,字符个数做多的是seventeen,一共有9个字符,我们如果想存放它需要定义一个可以容纳10个字符的数组,即char str[10] = "seventeen";。为什么数组空间要是10,而不是9呢,seventeen不是9个字符吗?因为在使用字符型数组存放字符串时,如果采用字符串常量来初始化字符数组的方式,系统对于字符串常量会自动加一个'\0'作为结束符,所以"seventeen"看起来是9个字符,其实是由's'、'e'、'v'、'e'、'n'、't'、'e'、'e'、'n'和'\0'共10个字符构成的,因此str这个字符型数组容量要设定为10才可以,否则会编译错误。那么如果我就想把数组容量设置为9呢,那么就要采用下面这两种比较繁琐的方式来初始化。这两种方式尽管语法没有错误,但是从代码编写简洁性和可读性的角度来说不可取。
char str[9];
str[0] = 's';
str[1] = 'e';
str[2] = 'v';
str[3] = 'e';
str[4] = 'n';
str[5] = 't';
str[6] = 'e';
str[7] = 'e';
str[8] = 'n';
char str[9] = {'s', 'e', 'v', 'e', 'n', 't', 'e', 'e', 'n'};
  • 综上所述,所有英文单词中,seventeen这个字符串的字符数量最多,需要至少10个空间,因此我们要定义的二维字符数组的第二个维度大小可以确定为10。这里我们给出字符型二维数组的定义和初始化代码如下。通过这种定义方式,我们就可以利用数组的索引来调用英文单词了。例如,timeword[0]就是zero,timeword[0][3]表示的就是'o'。
char timeword[25][10] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "thirty", "forty", "fifty", "o'clock"};`
  1. 上述准备工作完成后,就可以开始报时逻辑的编程模拟了。我们还是把问题分成两部分,先实现小时的输出。关于小时的输出,需要注意的是,它根据h的大小分为两种情况,我们先看h小于20的情况。
//如果小时数小于20
if(h < 20)
{
  printf("%s", timeword[h])
}

当h<20的时候,我们会发现timeword[h]的值正式h这个值对应的英文单词,那么将h可以作为数组的索引值,输出timeword[h]的值即可。

  1. 再看h大于20的情况,即h大于等于20且h小于60的时候,实现代码如下。
else //如果小时数在20-60之间
{
  //求小时数的十位和个位数字
  hshiwei = h / 10;
  hgewei = h % 10;

  //输出小时数的十位数字
  printf("%s", timeword[18 + hshiwei]);

  //如果小时数的个位数字不为0,则输出
  if(hgewei != 0)
  {
    printf(" %s", timeword[hgewei]);
  }
}
  • hshiwei = h / 10;:这里我们利用除法h / 10得到h的十位数字,注意h是整型,10是整形,那么h / 10的结果还是整型。大家可以尝试一下在Dev C++中运行printf("%d", 8 / 3);,结果是2,尽管8/3的真实结果是2.6,但是由于8和3都是整型,所以在程序中只返回整数部分,小数部分不会满五进一。所以h / 10的结果就是h在十位上的数字。
  • hgewei = h % 10;:这里我们利用取余操作,最终可以得到h在个位上的数字。
  • timeword[18 + hshiwei]:这里怎么出来个18呢?我们来看一个例子,假设此时h的值为23,那么根据上述两部可知变量hshiwei的值为2,hgewei的值为3。我们要输出十位上数字对应的英文单词,那么要确定数组的索引是什么。twenty在数组中的索引应该是20,而此时hshiwei的值为2,所以我们反推一下,即可得到要输出的字符串是timeword[18 + hshiwei]
  • 接下来要判断一下个位数字是否为0,如果不为0那就需要输出,如果为0,则不输出。各位数字可能的取值为1、2、3、4、5、6、7、8或9,那么这些数字的英文可以通过timeword[hgewei]来获得,hgewei可以刚好作为数组的索引来指定要取到的值。输出timeword[hgewei]的时候要注意,前面要有空格,不要忘记!直到这里,我们把小时数部分的报时功能已经完全实现了,接下来是分钟数。
  1. 如果分钟数m为0,上面处理完小时数后加上o'clcok即可,实现代码如下。
//如果分钟数为0,上面处理完小时数后加o'clcok即可
if(m == 0)
{
  printf(" %s\n", timeword[24]);
}

o'clock在timeword中放在索引为24的位置,所以timeword[24]的值就是o'clock。输出的时候要避免格式错误,上面小时输出完毕后,是没有任何空格或换行的。这里输出timeword[24]的值时,前面要加空格,后面加换行,这样的格式才是完整无误的,大家一定要注意这些细节,要不然就会PE。

  1. 如果分钟数m的值不为0,那么还需要再分成两种情况讨论,我们先看m小于20的这种情况,代码实现如下。
else //如果分钟数不为0,继续处理分钟数
{
  //如果分钟数小于20
  if(m < 20)
  {
    printf(" %s\n", timeword[m]);
  }

与小时数的值小于20的情况类似,这时m可以直接作为数组的索引,timeword[m]即为m这个数字的英文单词。需要注意的是,输出的时候要前面加空格,后面加换行。

  1. 再来看m大于等于20且小于60的情况。还是与小时数对于这种情况的处理类似,先分别利用整除和取余操作得到mshiweimgewei。接下来先输出十位的数字对应的英文单词,注意前面要加空格。然后判断个位数字是否为0,如果不为0,那么输出个位数字对应的英文单词,也是前面加空格,后面加换行。如果个位数字为0,那么直接输出换行即可,实现代码如下。
  else
  {
    //求分钟数的十位和个位数字
    mshiwei = m / 10;
    mgewei = m % 10;

    //输出分钟数的十位数字
    printf(" %s", timeword[18 + mshiwei]);

    //如果分钟数的个位数字不为0,则输出
    if(mgewei != 0)
    {
      printf(" %s\n", timeword[mgewei]);
    }
    else
    {
      printf("\n");
    }
  }
}

到这里全部的编程实现就结束了!

3.2 参考代码

#include<stdio.h>
int main()
{
  //h保存小时数,m保存分钟数
  int h, m;
	
  //hshiwei保存小时数的十位,hgewei保存小时数的个位,mshiwei保存分钟数的十位,mgewei保存分钟数的个位
  int hshiwei, hgewei, mshiwei, mgewei;
	
  //输入小时数和分钟数
  scanf("%d%d", &h, &m);
	
  //将所有用到的跟时间相关的英文单词用一个二维char型数组保存
  char timeword[25][10] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "thirty", "forty", "fifty", "o'clock"};
	
  //如果小时数小于20
  if(h < 20)
  {
    printf("%s", timeword[h]);
  }
  else //如果小时数在20-60之间
  {
    //求小时数的十位和个位数字
    hshiwei = h / 10;
    hgewei = h % 10;
	
    //输出小时数的十位数字
    printf("%s", timeword[18 + hshiwei]);
		
    //如果小时数的个位数字不为0,则输出
    if(hgewei != 0)
    {
      printf(" %s", timeword[hgewei]);
    }
  }
	
  //如果分钟数为0,上面处理完小时数后加o'clcok即可
  if(m == 0)
  {
    printf(" %s\n", timeword[24]);		
  }
  else //如果分钟数不为0,继续处理分钟数
  {
    //如果分钟数小于20
    if(m < 20)
    {
      printf(" %s\n", timeword[m]);
    }
    else
    {
      //求分钟数的十位和个位数字
      mshiwei = m / 10;
      mgewei = m % 10;
			
      //输出分钟数的十位数字
      printf(" %s", timeword[18 + mshiwei]);
      
      //如果分钟数的个位数字不为0,则输出
      if(mgewei != 0)
      {
        printf(" %s\n", timeword[mgewei]);
      }
      else
      {
        printf("\n");
      }			
    }
  }
  return 0;
}

4. 总结

4.1 考查的能力

  • 字符串的存储、初始化,特别是'\0'这个C语言入门学习时经常遇到的坑;
  • 数组以及二维数组的用法,包括定义、初始化和如何恰当地设计索引。
  • 输入输出格式,什么时候该加空格,什么时候该加换行。
  • 如何快速地读懂题意,将模拟的逻辑转换为if else这种分支结构。

4.2 解题技巧

  • 第一道题经常是整场比赛的坑,一定要谨慎阅读题目,判断它属于什么类型的题目再做。先做简单的题目,最后再做难的题目,A掉简单的题目一方面可以积累信心,另一方面可以热身,将自己的状态一点点调整到最好的状态,去挑战难题。
  • 一定要带草稿纸和笔,写下题目的关键点,将实现过程分为若干个步骤。逐部分实现,实现一部分,测试一部分。
  • 自己要做一些测试样例,多测试一下自己的程序,不要题目给的样例数据通过了就提交。在比赛中,罚时经常是压垮比赛排名的最后一根稻草!!!

标签:10,小时数,20,输出,VIP,蓝桥,DOTCPP,printf,timeword
From: https://www.cnblogs.com/code4infinity/p/16808503.html

相关文章