寒假到了,最近宅在家刷一刷C语言基础题,题目主要源自牛客网。刷题之前的我自以为C语言基础还不错,没想到做题的过程中还是有很多不会,一些细小的知识点之前都未接触到过,果然是“实践出真知”啊!在这里我想分享一下我在刷题过程中的一些收获,希望对大家有所帮助。
描述
将一个四位数,反向输出。
输入描述:
一行,输入一个整数n(1000 <= n <= 9999)。
输出描述:
针对每组输入,反向输出对应四位数。
示例1
输入:
1234
输出:
4321
非常经典的一道题,大学的期中期末考试经常要用到这种方法。通过出不断地取模和除法运算,把数字从后往前依次取出。代码如下:
#include
int main()
{
int n = 0;
scanf("%d", &n);
while (n)
{
printf("%d", n % 10);//把数字一个个打印
n /= 10;
}
return 0;
}
这里相当于打印了4个数字——1、2、3、4,最终打印结果是1234。如果你想要得到1234这个数字,只打印一次,也可以这样写:
#include
int main()
{
int n = 0;
int ret=0;
scanf("%d", &n);
while (n)
{
ret=10*ret+n%10;
n /= 10;
}
printf("%d",ret);
return 0;
描述
实现字母的大小写转换。多组输入输出。
输入描述:
多组输入,每一行输入大写字母。
输出描述:
针对每组输入输出对应的小写字母。
示例1
输入:
A
B
复制
输出:
a
b
这里地关键点在于多组输入
,怎么实现多组输入?之前我写过一篇用scanf实现多组输入的文章,有兴趣的可以去看看。这里介绍getchar的用法。
getchar的详细介绍
图片中我们可以看到,getchar这个函数的功能就是从屏幕上读取一个字符,如果读取成功,就会返回读取到的字符,如果读取失败,就会返回EOF
(end of file)。
根据我们以前使用scanf实现多组输入的经验,代码就会这样写:
#include
int main()
{
char ch = 0;
while ((ch = getchar()) != EOF)
{
putchar(ch + 32);
printf("\n");
}
return 0;
}
运行结果如下:
当我输入‘A’,按下回车后,屏幕上打印出了a和*;再次输入‘B’,按下回车,打印出b和*,显然这不是我们预期的结果。怎么回事呢?
原因在于,scanf与getchar的读取方式不同,scanf不会从缓冲区读取Enter
,而getchar会读取回车符,而回车符的ASCII码值加上32后对应的字符就是*
,所以会出现上述结果。
两者具体差别可参考这篇文章
所以代码可以做如下改进
#include
int main()
{
char ch = 0;
while ((ch = getchar()) != EOF)
{
putchar(ch + 32);
printf("\n");
getchar();
}
return 0;
}
在ch接收完getchar的返回值后,再次用getchar将回车符从缓冲区读取出来,这样ch就不会接收到回车符了。
描述
我们处理的整数通常用十进制表示,在计算机内存中是以二进制补码形式存储,但通常二进制表示的整数比较长,为了便于在程序设计过程中理解和处理数据,通常采用八进制和十六进制,缩短了二进制补码表示的整数,但保持了二进制数的表达特点。请输出十进制整数1234对应的八进制和十六进制。
输入描述:
无
输出描述:
十进制整数1234对应的八进制和十六进制(字母大写),用空格分开,并且要求,在八进制前显示前导0,在十六进制数前显示前导0X。
这道题主要考察我们printf函数的不同进制的打印格式,十进制%d
,八进制%o
,十六进制%x
(小写字母)或%X
(大写字母)。如果想在数字前加上前导标志,只需在%后加上#
代码如下:
#include
int main()
{
printf("%#o %#x", 1234, 1234);
return 0;
}
描述
bobo写了一个十六进制整数abcdef,他问kiki对应的十进制整数是多少。
输入描述:
无
输出描述:
十六进制整数abcdef对应的十进制整数,所占域宽为15。
这里主要考察域宽设置,代码如下:
#include
int main()
{
printf("%15d", 0xabcdef);
return 0;
}
描述
kiki写了一个输出“hello world!”的程序,bobo老师告诉他printf函数有返回值,你能帮他写个程序输出printf(“hello world!”)的返回值吗?
输入描述:
无
输出描述:
包括两行:
第一行为“hello world!”
第二行为printf(“hello world!”)调用后的返回值。
printf函数详细介绍
原来printf函数返回的值就是打印的字符个数。
代码如下:
#include
int main()
{
printf("\n%d",printf("hello world!")
return 0;
}
这里再给出一道经典的题目:
#include
int main()
{
printf(“%d”, printf(“%d”, printf(“%d”, 43)));
return 0;
}
上述代码的输出结果是什么?
答案是4321
。
描述
输入两个整数,范围 - 231~231 - 1,交换两个数并输出。
输入描述:
输入只有一行,按照格式输入两个整数,范围,中间用“, ”分隔。
输出描述:
把两个整数按格式输出,中间用“, ”分隔。
示例1
输入:
a = 1, b = 2
复制
输出:
a = 2, b = 1
交换两个数的值大家都很熟悉,只需创建一个临时变量,而这题考察的时scanf的输入格式。平常我们输入时一般只会输入数字,但这里它给我们规定了格式,所以必须保持一致。代码如下:
#include
int main()
{
int a = 0;
int b = 0;
scanf("a=%d,b=%d", &a, &b);
int ret = a;
a = b;
b = ret;
printf("a=%d,b=%d", a, b);
return 0;
}
描述
输入一个人的出生日期(包括年月日),将该生日中的年、月、日分别输出。
数据范围:年份满足 1990 <= year <=2015 ,月份满足 1 <= month <=12 ,日满足 1 <= date<=30
输入描述:
输入只有一行,出生日期,包括年月日,年月日之间的数字没有分隔符。
输出描述:
三行,第一行为出生年份,第二行为出生月份,第三行为出生日期。输出时如果月份或天数为1位数,需要在1位数前面补0。
示例:
输入:
20130225
复制
输出:
year=2013
month=02
date=25
本题关键点在于如何让scanf函数分多次读取一个数字以及如何再数字前补0。
前面我们学过printf可以设置域宽,而scanf同样可以设置读取的范围。代码如下:
#include
int main()
{
int year = 0;
int month = 0;
int date = 0;
scanf("%4d%2d%2d", &year, &month, &date);//依次读取4个,2个,2个字符
printf("year=%4d\n", year);
printf("month=%02d\n", month);//打印两位,位数不够在前面补0
printf("date=%02d", date);//打印两位,位数不够在前面补0
return 0;
}
例如我输入20130225
,scanf分三次读取,第一次读到2013,放到year里;第二次读到02,其实就是2,会把2放到month里;第三次读到25,放到date里。运行结果如下:
上述题目用到了这些知识: