牛客网编程初学者入门训练2
BC11 学生基本信息输入输出
描述
依次输入一个学生的学号,以及3科(C语言,数学,英语)成绩,在屏幕上输出该学生的学号,3科成绩(注:输出成绩时需进行四舍五入且保留2位小数)。
数据范围:学号满足 1 < = n < = 20000000 1 <= n <= 20000000 1<=n<=20000000 ,各科成绩使用百分制,且不可能出现负数
输入描述:
学号以及3科成绩,学号和成绩之间用英文分号隔开,成绩之间用英文逗号隔开。
输出描述:
学号,3科成绩,输出格式详见输出样例。
示例1
输入:
17140216;80.845,90.55,100.00
输出:
The each subject score of No. 17140216 is 80.85, 90.55, 100.00.
示例2
输入:
123456;93.33,99.99,81.20
输出:
The each subject score of No. 123456 is 93.33, 99.99, 81.20.
内心想法:
一眼看去,不就是输入输出嘛,有啥的,三两下交了代码就获得了一个WA······再仔细看看题才发现输入的数据是用英文分号和英文逗号分隔的,而不是以默认的空格、Tab、换行符作为分隔符,忽略这个问题会导致除了第一个输出结果外其余三个全为零。以前一直没注意这个问题,这次碰上了就得好好学学。
幸好这道题比较良心,输入的这组数据全是数字,我们可以取巧,用一个字符去接收分隔符。
至于其他情况,可以参考这篇博客:
代码实现如下:
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
int main()
{
int a;
double b,c,d;
char sep;
cin>>a>>sep>>b>>sep>>c>>sep>>d;
b=round(b*100)/100;
c=round(c*100)/100;
d=round(d*100)/100;
cout<<"The each subject score of No. "<<a<<" is ";
cout<<setprecision(2)<<fixed;
cout<<b<<", "<<c<<", "<<d<<"."<<endl;
}
这里还要注意两点:
一是输出成绩时要四舍五入。四舍五入的方法不一,在这里采用了 round() 函数,这个函数包含在这个头文件中:
#include<cmath>
至于小数的四舍五入可以看看这篇短小精悍的博客:
二是输出的成绩要保留两位小数。这要用到参数化的流操纵符 setprecision() ,程序中要包含这个头文件:
#include<iomanip>
在第 15 行后输出的数据都是保留两位小数的。
BC12 字符圣诞树
描述
输入一个字符,用它构造一个边长为5的三角形圣诞树。
数据范围:保证输入的字符是一个 char 类型的值
输入描述:
输入只有一行,一个字符。
输出描述:
该字符构成的三角形圣诞树。
示例1:
输入:
1
输出:
1
1 1
1 1 1
1 1 1 1
1 1 1 1 1
内心想法:
一眼看去觉得应该是比较常见且基础的类似棋盘格的题,思路也比较明确,以示例输入为例,就是把一个 1 和其后的一个空格看成一个整体,然后找到每行第一个 1 前的空格数与所属行数的关系。
观察此图可知,第 n 行有 n 个黄色块,此行第一个 1 之前空格数满足 5-n (此处所说 n 满足 1 < = n < = 5 1 <= n <= 5 1<=n<=5 )。很自然地,循环就出来了。代码实现如下:
#include<iostream>
using namespace std;
int main()
{
char ch;
cin>>ch;
for(int i = 0;i < 5;i++)
{
for(int n = 4-i;n > 0;n--)
{
cout<<" ";
}
for(int j = 0;j <= i;j++)
{
cout<<ch<<" ";
}
cout<<endl;
}
}
这个实现中的行数规定的是从 0 开始,无妨。这种题往往会因为没注意空格和换行导致PE,而且检查起来会浪费大量时间,非常不划算,应该在动手前就把这些考虑好。
BC13 ASCII码
描述
BoBo教KiKi字符常量或字符变量表示的字符在内存中以ASCII码形式存储。BoBo出了一个问题给KiKi,转换以下ASCII码为对应字符并输出他们。
73, 32, 99, 97, 110, 32, 100, 111, 32, 105, 116 , 33
输入描述:
无
输出描述:
转换输出题目中给出的所有ASCII到对应的字符。
内心想法:
试过把字符强制转为整型,但没试过把整型转为对应字符,我们合理推测一波,由于把字符强制转为整型是用 (int)ch (此处ch代指某个字符),所以有没有一种可能,把整型转为对应字符是用 (char)num (此处num代指某一字符的ASCII码)。试试再说。
由于有十二个ASCII码,一个个定义显得不太聪明的亚子,就用一下数组吧。代买实现如下:
#include<iostream>
using namespace std;
int main()
{
int arr[] = {73,32,99,97,110,32,100,111,32,105,116,33};
cout<<(char)arr[0]<<(char)arr[1]<<(char)arr[2]<<(char)arr[3]<<(char)arr[4]<<(char)arr[5]<<(char)arr[6]<<(char)arr[7]<<(char)arr[8]<<(char)arr[9]<<(char)arr[10]<<(char)arr[11]<<endl;
}
非常简单的一段,直接AC了。
其实还可以更简单,虽然这样会显得我的合理猜测很蠢······
#include<iostream>
using namespace std;
int main()
{
char arr[] = {73,32,99,97,110,32,100,111,32,105,116,33};
cout<<arr[0]<<arr[1]<<arr[2]<<arr[3]<<arr[4]<<arr[5]<<arr[6]<<arr[7]<<arr[8]<<arr[9]<<arr[10]<<arr[11]<<endl;
}
在定义数组的时候直接定义为 char 类型就可以直接输出了,直接躺······
在本地IDE上运行了一下,有点小惊喜······
这就是输出结果哈哈哈哈
BC14 出生日期输入输出
描述
输入一个人的出生日期(包括年月日),将该生日中的年、月、日分别输出。
数据范围:年份满足 1990 < = y < = 2015 1990 <= y <= 2015 1990<=y<=2015,月份满足 1 < = m < = 12 1 <= m <= 12 1<=m<=12,日满足 1 < = d < = 30 1 <= d <= 30 1<=d<=30
输入描述:
输入只有一行,出生日期,包括年月日,年月日之间的数字没有分隔符。
输出描述:
三行,第一行为出生年份,第二行为出生月份,第三行为出生日期。输出时如果月份或天数为1位数,需要在1位数前面补0。
示例1:
输入:
20130225
输出:
year=2013
month=02
date=25
备注:
通过scanf函数的%m格式控制可以指定输入域宽,输入数据域宽(列数),按此宽度截取所需数据;通过printf函数的%0格式控制符,输出数值时指定左面不使用的空位置自动填0。
内心想法:
又想让我用C来写是吧,不可能,我一定要用 cout 输出格式。
这道题有三个考点:
一是从没有分隔符的一串输入数据中截取每个部分下来。这个比较常见,无非就是一些取模、加减乘除的运算,有很多种方法,随便选一种即可;
二是控制域宽,也是很常见的,用参数化的流操纵符 setw() 即可,不要忘了头文件;
三是在 1 位数的月份或天数前补上 0 。这是我之前没注意过的,这里要用到 setfill() 来设置填充字符。
关于前后补零的知识可以参考这篇博客:
代码实现如下:
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int birth;
cin>>birth;
int year = birth / 10000;
int month = birth / 100 - year * 100;
int date = birth - birth / 100 * 100;
cout<<"year="<<year<<"\n"<<"month="<<setw(2)<<setfill('0')<<month<<"\n"<<"date="<<setw(2)<<setfill('0')<<date<<endl;
}
这里要注意一下,设置域宽和补零的语句只对其后的第一个输出数据有效,是一次性的。而且看 setfill() 中补零是用 单引号 (’ ')来指定 0 来填充的,所以这里换成其他字符,就会用其他字符来填充。