牛客网编程初学者入门训练1
BC2 我是大V
描述
每个人都想成为大V (VIP:Very Important Person),但要一点一点积累才行,先从小v做起。要求输出由小写字母v组成的大V。
输入描述:
无
输出描述:
备注:
换行使用转义字符‘\n’
(第一行两个v之间隔了三个空格,第二行两个v之间隔了一个空格,第三行v前有两个空格,第二行第一个v前有一个空格)
内心想法:
一眼看去就想直接暴力输出了,毕竟是一道很简单的题,也没啥要求······
于是把以下代码交了赶下一题
#include<iostream>
using namespace std;
int main()
{
cout<<"v v\n v v\n v"<<endl;
}
但转念一想,要是这个行数很大,或者是自己规定行数的,那不就寄了吗······
所以还是得搞个通法,至少有点底气······
以此题输出三行为例观察一下这种形式
不难发现,每一行(除最后一行外)v是对称的,最后一行的v居中,而且只看前三列的正方形,v恰好在对角线输出,看后三列也一样,于是就有了下面的解法(忽略题目备注):
#include<iostream>
using namespace std;
int main()
{
for(int i = 0;i < 3;i++)
{
for(int j = 0;j < 5;j++)
{
if(i == j || j == 4 - i)
{
cout<<"v";
}
else
{
cout<<" ";
}
}
cout<<endl;
}
}
外层循环条件表达式中的 3 是输出的行数,内层循环条件表达式中的 5 是第一行v和空格的个数和,if语句判断条件中的 4 是 5-1 ,因为我们把 j 定义为 0 了,所以这个数不是5。(细索之下我们发现如果要求输出 n 行,那么第一行v和空格的个数和满足 2n-1 ,2n-1 是个奇数,减去两个v的 2n-3 还是奇数,所以第一行两个v之间的空格数只能为奇数。)
如果这道题要求不定多次且完全随机输入行数,我们大可把这个循环写成一个函数,按照具体要求加上一些判断条件,然后在主函数中用while循环之类的引用即可。
BC7 缩短二进制
描述
我们处理的整数通常用十进制表示,在计算机内存中是以二进制补码形式存储,但通常二进制表示的整数比较长,为了便于在程序设计过程中理解和处理数据,通常采用八进制和十六进制,缩短了二进制补码表示的整数,但保持了二进制数的表达特点。请输出十进制整数1234对应的八进制和十六进制。
输入描述:
无
输出描述:
十进制整数1234对应的八进制和十六进制(字母大写),用空格分开,并且要求,在八进制前显示前导0,在十六进制数前显示前导0X。
备注:
printf可以使用使用格式控制串“%o”、“%X”分别输出八进制整数和十六进制整数,并使用修饰符“#”控制前导显示
内心想法:
看到这道题有点尴尬,一是因为发现自己好像几乎没做过进制转换,虽然这道题只是很基础的那种,还是让我懵了一下;二是我不习惯用 printf()函数,决定还是用cout格式输出。有时间还是得写一下各个进制转换的函数锻炼一下。
这道题要求了强制输出整数的基数(八进制以0打头,十六进制以0x打头),还要求了十六进制的字母要大写,所以要用到 cout.setf() 函数,而且格式标志要选 ios::showbase 和 ios::uppercase 。
关于 cout.setf() 函数以及C++中输入输出的知识,可以参考这两篇博客,写的很详细:
接下来的代码实现就比较简单了:
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int n = 1234;
cout.setf(ios::showbase | ios::uppercase);
cout<<oct<<n<<" "<<hex<<n;
}
这里要注意两点:
一是头文件。使用 cout.setf() 函数和控制符 oct 、hex ,要包含这个头文件:
#include<iomanip>
当然,如果想小偷个懒,可以直接祭上万能头文件:
#include <bits/stdc++.h>
但是呢,可能会有某些oj会不支持这个头文件,可能有些大型比赛会禁用,如果实在忘了或者赶时间可以用下,但本人还在学习的初期,还是先记一下。
关于这点可以看看这篇博客:
二是设置格式状态的格式标志。用 cout.setf() 函数设置格式状态时,可以包含两个或以上的格式标志,由于这些格式标志在ios类中被定义为枚举值,每一个格式标志以一个二进位代表,因此可以用位或运算符“|”组合多个格式标志,不必分成几行写。(在visual studio中用逗号隔开也可以,但在牛客网会WA,暂时还不太清楚)
BC8 十六进制转十进制
描述
BoBo写了一个十六进制整数ABCDEF,他问KiKi对应的十进制整数是多少。
输入描述:
无
输出描述:
十六进制整数ABCDEF对应的十进制整数,所占域宽为15。
备注:
printf可以使用使用格式控制串“%md”输出域宽为m的十进制整数。
内心想法:
老规矩,还是忽略备注继续用cout输出格式。
这题就考两个知识点:
一是C++中十六进制的表示方法,要用前缀“0x”和后面的十六进制数据,即 ABCDEF 要表示成 0xABCDEF 。
二是规定了输出值所占的域宽为15。规定域宽要用到参数化的流操纵符 setw() ,这个流操纵符在这个头文件中:
#include<iomanip>
剩下的代码实现就很简单了:
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int n = 0xABCDEF;
cout<<setw(15)<<dec<<n<<endl;
}
BC9 printf的返回值
描述
KiKi写了一个输出“Hello world!”的程序,BoBo老师告诉他printf函数有返回值,你能帮他写个程序输出printf(“Hello world!”)的返回值吗?
输入描述:
无
输出描述:
包括两行:
第一行为“Hello world!”
第二行为printf(“Hello world!”)调用后的返回值。
内心想法:
看到这道题就知道还是逃不过 printf() ,但是这个不是关键,关键是发现自己一直没注意过 printf() 函数的返回值!所以我们试着把输出的内容赋给一个整型,再输出这个整型看看。
#include<stdio.h>
#include<iostream>
using namespace std;
int main()
{
int n = printf("Hello world!");
printf("\n");
printf("%d",n);
return 0;
}
值得注意的有两点:
一是头文件。printf() 函数是包含在
二是第 6 行的赋值方式。这样既实现了一次输出,又记录了 printf() 的返回值。(第 8 行的 %d 表示的是规定以整型输出。)
在本地IDE上运行这段代码我们发现第二行输出结果是 12 ,恰好是 Hello world! 的字符串长度!于是回头看我们就能发现,在第 6 行的输出中万万不能加上 \n ,这会导致返回值比正确的返回值多 1 ,应该单独换行。