1、任意定义几个名字和年龄,找到年龄最大的人并输出
主要看19、20、21、22这四行,gets与scanf的爱恨情仇,其他内容有不懂得可以看我之前的文章
先来了解一下scanf和gets,它们都是从输入流中读取数据,但功能有很大差别:
1、操作类型不同
gets函数仅用于读入字符串
scanf为格式化输出函数,可以读入任意C语言基础类型的变量值,而不是仅限于字符串(char*)类型。
2、截止字符不同
gets函数固定的以换行符作为结尾,遇到换行符时结束输入
scanf函数默认以空白函数结尾,同时可以对截止函数进行修改
3、对截止字符处理不同
gets函数会读入截止字符\n, 同时将\n自动替换为\0.
scanf遇到截止字符时不会继续读取,截止字符将存储于输入缓冲中。
4 、返回值类型不同。
gets的返回值为char*型,当读入成功时会返回输入的字符串指针地址,出错时返回NULL。
scanf返回值为int型,返回实际成功赋值的变量个数,当遇到文件结尾标识时返回EOF。
(1)接收时都用scanf
接收名字用%s,接收age用%d,结果如图所示,是正常的
(2)接收时都用gets
因为age是int型的数据,但gets是接收字符串的,因此在第一次循环到接收age的时候就报错了
而下面这个,电话号码是字符串,因此不会报错,循环继续进行
(3)name用gets,age用scanf
第一次循环是正常的,然后又出错鸟,这是因为在name输入后,你敲的回车gets在读取后就删除了
然后开始输入age,再敲回车,scanf只读取了输入的数值,没有理那个回车截止字符,所以它还在那里
第二次循环时gets就把那个回车给读入了,所以你没输它就又轮到scanf了
因此会出现后两次循环的name你都没输就被跳过了
2、~ (~ 0<<4)和~(1<<4)分别等于多少
~按位取反
<<左移运算
0的二进制为00000000,那么~0就为11111111
【~ 0<<4 】就是将~0的二进制码向左移动4位,右边补0,即得11110000
【 ~ ( ~0<<4)】就是将上一步得到的二进制码(11110000)取反,得00001111
此时得到的这个值是个补码,但补码是给机器看的,原码是给人看的
而正数的原码、反码、补码是一样的,所以此处直接得知其值为15
若是负数则要注意转换,,,原码到补码:
例如:1111 1111,是负数首位为1不变(正数首位为0),到反码是1000 0000,+1到补码1000 0001,反过来计算补码1000 0001的原码,先 - 1 为1000 0000,再到原码为1111 1111
同理
1的二进制为00000001,1<<4为00010000,~(1<<4)为11101111
此时再将1110 1111转换成原码:先减一为1110 1110,再反为1001 0001其值为-17
3、continue和break
continue往上走就直接返回到if去循环再来一遍了
break往下走,完事了
4、inttypes.h
inttypes.h是标准C函数库的头文件,提供整数输入的各种转换宏。
PRIi8、PRIu8、PRIo8以及PRIx8,其中i为有符号,u为无符号,o为8进制以及x为16进制。
%hhd -----PRId8
%hd -----PRId16
%d -----PRId32
%lld -----PRId64------十进制输出64位整型
“ % ” “ hd ” = “ %hd ” = “ % ” PRId 16
sbyte型为有符号8位整数,占1个字节,取值范围在128~127之间。
bytet型为无符号16位整数,占2个字节,取值范围在0~255之间。
short型为有符号16位整数,占2个字节,取值范围在-32,768~32,767之间。
ushort型为无符号16位整数,占2个字节,取值范围在0~65,535之间。
float型为32位单精度实数,占4个字节,取值范围3.4E+10的负38次方~3.4E+10的38次方之间。
long型为有符号64位整数,占8个字节,取值范围在9,223,372,036,854,775,808~9,223,372,036,854,775,807之间。
ulong型为64位无符号整数,占8个字节,取值范围在0~18,446,744,073,709,551,615之间。
double型为64位实数,占8个字节,取值范围1.7E+10的负308次方~1.7E+10的正308次方。
5、判断练习
当标准输入为2000时,2000%4的余数为0,不符合第5行判断,所以执行第7行。2000%100的余数为0,不符合第7行判断,所以执行第9行,2000%400的余数为0,不符合第9行判断,所以执行第11行,输出YES
当标准输入为1992时,1992%4的余数为0,不符合第5行判断,所以执行第7行。1992%100的余数不为0,符合第7行判断,所以执行第7行,输出YES
当标准输入为800的倍数时,比如800,800%4的余数为0,不符合第5行判断,所以执行第7行。800%100的余数为0,不符合第7行判断,所以执行第9行,800%400的余数为0,不符合第9行判断,所以执行第11行,输出YES
当标准输入为2100时,2100%4的余数为0,不符合第5行判断,所以执行第7行。2100%100的余数为0,不符合第7行判断,所以执行第9行,2100%400的余数不为0,符合第9行判断,所以执行第9行,输出NO
当标准输入为2010时,2010%4的余数不为0,符合第5行判断,所以执行第5行,输出NO
【取反运算符 ! , 0 的取反结果 ! 0 是 1 , 1 的取反结果 ! 1 是 0】
6、特殊的运算符
(1)x = x + 1 可缩略为 x += 1 ; p = p - 2 可缩略为 p -= 2 ,类似的还有 *= 、/= 、%= 等
(2)printf(“%d\n”,a++);
假设a=5,此时输出a=5,因为a++是先被使用,后再将a值加一
printf(“%d\n”,++a);
假设a=5,此时输出a=6,因为++a是先将a值加一,后再被使用
7、循环 三两事
(1)
第一次外循环:
num=1<4,执行内循环,num2=0<num1=1,执行输出1 * 0=0【1】,num2+=2的结果为num2=2,其值不小于num1=1,故结束内循环
第二次外循环:
num1=2<4,执行内循环,num2=0<num1=2,执行输出2 * 0=0【2】,num2+=2的结果为num2=2,其值不小于num1=2,故结束内循环
第三次外循环:
num1=3<4,执行内循环,num2=0<num1=3,执行输出3 * 0=0【3】,num2+=2的结果为num2=2,其值小于num1=3,故执行输出3 * 2=6【4】,num2+=2的结果为num2=4,其值不小于num1=3,故结束内循环
第四次外循环:
num1=4<=4,执行内循环,num2=0<num1=4,执行输出4 * 0=0【5】,num2+=2的结果为num2=2,其值小于num1=4,故执行输出4 * 2=8【6】,num2+=2的结果为num2=4,其值不小于num1=4,故结束内循环
第五次外循环:
num1=5>4,所以没循环起来,结束程序。
【i】是输出的结果,共六次,分别为0,0,0,6,0,8
(2)