c语言 快速判断两个数是否相等_C语言入门——第二周笔记

木叶医院,一名婴儿在几名医疗忍者的努力下,缓缓睁开了眼睛。
”这,这孩子的眼睛?“
——《火影之雪殇》
做判断
还记得上周的内容当中,我们有这样一段。

如果
- 就用分别减的方案,然后判断有没有出现错位行不行?
- 错位的表现是,分钟减的结果小于0
int im = minute2-minute1;
if ( im <0 ){
…
}
虽然2点10分减1点40分(分钟减分钟,时钟减时钟)得到的1小时负30分,然我们都知道,其实这负30分钟应该加上1小时,也就是30分钟。
所以这里,我们需要做一个调整(当出现负数时),就是把那个小时数减一;然后分钟数做一个调整,比如10分钟减40分钟,减下来得到的是负30分,其实我们知道,那应该是60减30,正确的是过了30分钟,而不是负30分钟。所以,如果语言,有这么一种机制,它能够帮我们做这样的一种判断,根据某种条件决定做这件事情,还是不做这件事情 ,那,我们就有可能写出这样的一种代码来。
#include <stdio.h>
int main()
{
int hour1, minute1;
int hour2, minute2;
scanf("%d %d", &hour1, &minute1);
scanf("%d %d", &hour2, &minute2);
int ih = hour2 - hour1;
int im = minute2-minute1;
if ( im <0 ){
im=60+im;
ih --;
}
printf("时间差是%d小时%d分。n", ih, im);
return 0;
}
我们在这个当中,用了C语言的一种手段,叫做条件判断。 我们用的是这个叫做“if”的东西。如果im<0,我们要做的就是让60加上im,把那个复数给补回去,然后,我们还要让ih(小时)减一。如果im不小于0,我们就不需要做这样的一个调整了。所以,这是我们在C语言中的一种机制,叫做if语句,叫做判断机制。我们可以给定一个条件,判断一件事是做还是不做。
我们来试一下这几行代码是怎样运行的。

我们输入了,2个数,得到的是0小时40分。那么,在这个语句中,if是怎么起作用的呢?
如果条件满足,则做所有大括号里的语句,如果不满足,计算机则直接跳过这一大段语句。(具体 步骤可用“调试”功能查看)。
判断的条件
在上面的程序中有这么一段if( im <0){ im=60+im; ih --;},在这个圆括号里面出现了“<”,“<”是用来做比较的,除了“<”,我们当然还会有“>”,和判断他们是否相等的“=”。在if语句的圆括号里的东西,我们把他称为运算。这个运算,计算两个值之间的关系所以叫关系运算。

注意!这张图里,第一行是两个“=”号,而不是一个“=”。如果是一个“=”,我们就会用掉了,因为它代表赋值,只有当“==”,才表示相等;第二行的“!=”中的“!”在C语言中表示“否”、“非”,“不是”。
关系运算的结果
- 当两个值的关系符合关系运算符的预期时,关系运算的结果为整数1,否则为整数0
- printf(“%dn”,5==3);
- printf(“%dn”,5>3);
- printf(“%dn”,5<=3);
我们来看一下运行结果。

所以,比较运算的结果值,只有“0”和“1”这两种值,不会有其他值。
既然,它们都是运算符,那它们肯定有优先级。
优先级
- 所有的关系运算符的优先级比算术运算的低,但是比赋值运算的高。
- 7>=3+4
- Int r = a>0;
- 判断是否相等的==和!=的优先级比其他的低,而连续的关系运算是从左到右进行的
- 5>3==6>4
- 6>5>4
- a==b==6
- a==b>0
7>=3+4中,这里,我们按照运算法则,先算加法,再判断大小。我们用计算机看一下,是不是这样算的。

没错是这样计算的,结果为1,所以关系运算符的优先级比算术运算的低。
再看看6>5>4;

找零计算器
- 找零计算器需要用户做两个操作:输入购买的金额,输入支付的票面,而找零计算器则根据⽤用户的输入做出相应的动作:计算并打印找零,或告知用户余额不足以购买。
- 从计算机程序的角度看,这就是意味着程序需要读用户的两个输入,然后进行一些 计算和判断最后输出结果。
#include <stdio.h>
int main()
{
// 初始化
int price=0;
int bill=0;
// 读入金额和票面
printf("请输入金额:");
scanf("%d",&price);
printf("请输入票面:");
scanf("%d",&bill);
// 计算找零
printf("应该找您:%d",bill-price);
return 0;
}
这个找零程序,比以往多了一个注释 。那么,什么是注释,注释有什么用,怎么用?
注释
- 以两个斜杠“//”开头的语句把程序分成了 三个部分:
1. 初始化 2. 读入金额和票面 3. 计算并打印找零
注释(comment)插⼊入在程序代码中, 用来向读者提供解释信息。它们对于程序的功能没有任何影响,但是往往能使 得程序更容易被人类读者理解。
/* */注释
- 延续数行的注释,要用多行注释的格式来写。多行注释由⼀一对字符序列“/”开始, 而以“/”结束。
- 也可以用于一行内的注释
- int ak=47 /* 36*/, y=9;
比较

左边的程序会更加的让别人读懂和清爽。
if 语句
一个基本的if语句由一个关键字if开头,跟上在括号里的一个表示条件的逻辑表达式,然后是一对大括号“{}”之间的若干条语句。如果表示条件的逻辑表达式的结果不是零,那么就执行后面跟着的这对大括号中的语句,否则就跳过这些语句 不执行,而继续下面的其他语句。
判断票面够不够
#include <stdio.h>
int main()
{
// 初始化
int price=0;
int bill=0;
// 读入金额和票面
printf("请输入金额:");
scanf("%d",&price);
printf("请输入票面:");
scanf("%d",&bill);
// 计算找零
if (bill >= price){
printf("应该找您:%n",bill-price);}
return 0;
}

( 画流程图来 看看)
不够怎么办?
这里我们可以使用if else来进行完整的判断。
#include <stdio.h>
int main()
{
// 初始化
int price=0;
int bill=0;
// 读入金额和票面
printf("请输入金额:");
scanf("%d",&price);
printf("请输入票面:");
scanf("%d",&bill);
// 计算找零
if (bill >= price){
printf("应该找您:%n",bill-price);
}
else{
printf("你的钱不够n");
}
return 0;

所以if else能够更好的输出判断的最终结果。
再举一个例子:比较数的大小
#include <stdio.h>
int main()
{
int a,b;
printf("请输入两个整数:");
scanf("%d %d",&a,&b);
int max =0;
if (a > b){
max = a ;
}else{
max = b;
}
printf("大的那个是%dn",max);
return 0;
}
结尾不带”;“的if 语句
计算薪水
#include <stdio.h>
int main()
{
const double RATE = 8.25;
const int STANDARD = 40;
double pay = 0.0;
int hours;
printf("请输入工作的小时数:");
scanf("%d",&hours);
printf("n");
if (hours > STANDARD)
pay = STANDARD*RATE+(hours-STANDARD)*(RATE*1.5);
else
pay = hours * RATE;
printf("应付工资:%fn",pay);
return 0;
}
i f语句这一行结束的时候并没有表示语句结束的“;”,而后面的赋值语句写在if的下一行,并且缩进了,在这一行结束的时候有一个表示语句结束的“;”。这表明这条赋值语句是if语句的一部分,if语句拥有和控制这条赋值语句,决定它是否要被执行。
总之,if语句是根据条件决定做还是不做,而加上else后能够给我们一个更清晰的结果。
我们现在又有这样的一个题目要做:给你一个整数(小于4位),判断它是几位数。
如:252 输出:3
我们知道人和计算机思维方式是不一样的。解决问题基本的办法是不一样的。人的方式是什么?眼睛一看就知道了。而计算机做不到这件事,计算机最不擅长的就是眼睛一看就知道了。那计算机的方式是什么?
有一个合理的方式:通过判断它的范围来判断它的位数,如2331∈(999,10000),所以,是4位;12∈(10,99),所以,是2位。而这个方式,是人类不擅长的,因为人对文字的处理能力优于对数字的处理能力。按照这个思路,我们来写出这样的一个程序。
#include <stdio.h>
int main()
{
int x;
int n =1 ;
scanf("%d",&x);
if (x > 999){
n=4;
} else if (x>99){
n=3;
} else if (x>9){
n=2;
} else{
n=1;
}
printf("%dn",n);
return 0;
}
我们来运行一下,看看输入不同的数,有什么情况。



结果没有问题。
在这个程序的写法中,经常有人把程序写成了下面这个样子(把if并联了起来),我们来看看对不对。
#include <stdio.h>
int main()
{
int x;
int n =1 ;
scanf("%d",&x);
if (x > 999){
n=4;
}
if (x>99){
n=3;
}
if (x>9){
n=2;
}
if (x>0){
n=1;
}
printf("%dn",n);
return 0;
}
这样写对不对呢?这样写描述了很多的关系 ,当大于99的时候输出3;大于9的时候输出2等等等。但是,计算机的程序不是描写关系的,计算机的程序描写的是步骤 。比如这里输入82,计算机先判断它大于9,然后确定n=2,但当进行一面一行判断的时候,发现它也大于0,所以,最后的输出是1,这样就出现了错误。所以写程序,我们一定要非常的清楚,我们写的是什么——是步骤,要让它一步一步地去做,你写的不是关系,也不是说明,而是步骤。
好,这是我第一个要清楚的事情。
另外一件事情就是,我们这个程序是从高处往下判断,所以不需要判断上限了。 我先判断它是不是大于999,不成立的话,那么判断大于99是不是对的,因为我已经判断过是否大于999了,这个else,我只要判断它是否大于99就ok了,我不用管它是不是小于1000,因为上面的一个条件,已经隐含的给满足了,所以我们需要从高处往下做判断;如果,我们把这件事情反过来做,从低处往高处判断,那么当一个数大于0时它就直接输出了,后面的else根本没什么用。所以,我们用大于来进行判断的时候,要从高处往低处走;当我们用小于号的时候,从低处往高处走。
再来看这个程序,它判断的范围是有限的,当我们判断的位数越多,程序所加的代码也就越多。(为了方便看,图片复制到下方,与上图相同)
#include <stdio.h>
int main()
{
int x;
int n =1 ;
scanf("%d",&x);
if (x > 999){
n=4;
} else if (x>99){
n=3;
} else if (x>9){
n=2;
} else{
n=1;
}
printf("%dn",n);
return 0;
}
所以,我们不可能不断的加if来判断。
那我们该怎么做?
我们换个方式想,当我们看到“321”这个数,我们会立刻反应到他是3位数。当我们看到“12312312312938927489237489123”我们会怎么办?我们会一个一个的数数。所以我们如何让计算机来数数?当我们数数的时候,我们会一个一个的去划掉,然后慢慢数,可是怎么让计算机划 呢?
还记得那个取余(%)运算符吗(在第一周的笔记里说到)
比如352%100=52,这样“3”就被我们给划 掉了,那么12312312123%10000000000=231231212123,这时候的问题是,我们怎么得到10000000000呢?所以,我们人和计算机还是不一样的,人擅长做的,计算机不一定擅长,所以计算机应该有他自己擅长做的事情。
那么,如果我们换一下,从右边开始划 ,比如123123123123/10=12312312312,这样就去掉了右边的数,然后不断地划,直到没有数划为止,也就是留下的那部分数为0 了。紧接着,每次划掉一个就记一次数,每划一次记一次,不断的计数,然后相加,最后就能判断出那是几位数了。
我们来试试这个代码。
#include <stdio.h>
int main()
{
int x;
int n =0;
scanf("%d",&x);
n++;
x/=10;
if ( x>0 ) {
n++;
x /= 10;
if ( x>0 ){
n++;
x/= 10;
if ...
}
}
printf("%dn",n);
return 0;
}
细细读来,发现它还是需要无限个if,那究竟该怎么做?
#include <stdio.h>
int main()
{
int x;
int n =0;
scanf("%d",&x);
n++;
x/=10;
while (x >0){
n++;
x/=10;
}
printf("%dn",n);
return 0;
}
我们来运行一下试试改进后的程序。


没有任何的问题。
所以,当我们需要循环加判断的时候就可以用到while。if和while的跟别根本区别在于,你要一次性还是反复多次性地去做,反复多次包括要反复多次地去判断那个条件。
单从C语言的语法上来看while非常的简单。但是,真正的难度在后面。
我们还是回过头来看上面的那个程序(代码同上)
#include <stdio.h>
int main()
{
int x;
int n =0;
scanf("%d",&x);
n++;
x/=10;
while (x >0){
n++;
x/=10;
}
printf("%dn",n);
return 0;
}
它的程序图为

程序中的while后面的花括号里的内容就是循环体。这里我们要特别小心,循环体里要有能够判断的数据,否则的话,就会出现我们常说的死循环。 比如说,我们把花括号里的x/=10去掉,看看会出现什么样的情况。

它会一直卡在这。
一小段总结。
while
- 如果我们把while翻译作“当”,那么一个while循环的意思就是:当条件满足时,不断地重复循环体内的语句。
- 循环执行之前判断是否继续循环,所以有可能循环一次也没有被执行;
- 条件成立时循环继续的条件。
再来想一下这个程序。

如果没有外面的运算会怎么样?此时又不给你电脑,你怎么写出这个程序输出的结果,并判断它的对错。此时没有电脑,只给你笔和纸。
我们可以用人脑模拟计算机的运行,在纸上列出所有的变量,随着程序的进展不断重复计算变量的值。当程序运行结束时,留在表格最下面的就是程序的最终结果。

当然,一个“352”是没办法验证程序的,我们需要不同种类型的数来验证。测试程序时,我们经常使用边界数据,如有效范围两端的数据、特殊的倍数等,还有个位数;10;0;负数。
比如,我们试试“10”

再试试“5”

再试试“0”

发现,“0”被认为0位数!那把少的那部分代码加回去,我们看看能不能完成这个任务。
#include <stdio.h>
int main()
{
int x;
int n =0;
scanf("%d",&x);
n++;
x/=10;
while (x >0){
n++;
x/=10;
}
printf("%dn",n);
return 0;
}

注:因为有的时候,在一些复杂的交互中,我们无法使用第一周里使用的“DEV调试”功能,来进行准确的判断,所以,必须要掌握在纸上写出变量的运行过程的方法。
除了在纸上写出变量的运行,判断输出,我们还有一个手段能够帮我们进行调试。在程序适当的地方插入printf来输出变量的内容。
举个例子:
#include <stdio.h>
int main()
{
int x;
int n =0;
scanf("%d",&x);
printf("%d",x);
while (x >0){
n++;
x/=10;
printf("x=%d,n=%dn",x,n);
}
printf("%dn",n);
return 0;
}

所以程序的输出,我们在每一行出现的情况就可以直接看到了!
我们来看一下个位的情况怎么样。

如果是“0”呢?

我们发现根本没有输出,也就是没有进入到花括号里。
当然有时,我们经常做这样的一件有趣的事情。加入“hr”(hr表示英文里的here)。比如“hr1”“hr2”分别指代变量在不同的位置。(经常用)
#include <stdio.h>
int main()
{
int x;
int n =0;
scanf("%d",&x);
printf("%d",x);
while (x >0){
printf("hrn");
n++;
x/=10;
printf("x=%d,n=%dn",x,n);
}
printf("%dn",n);
return 0;
}
最后可千万别忘记一点,当你把你写的程序交到PAT上去裁判的时候,千万不要忘记在调试的语句前加注释,把这句话给去掉。
回顾一下我们讲的这一大段内容,我们先看了数位数的源代码,又到if语句,再到,while语句的循环,还没看到它的算法。
我们现在来看一下数位数的算法。
- 用户输入x;
- 初始化n为0;
- x=x/10,去掉个位;
- n++;
- 如果x>0,回到3;
- 否则n就是结果。
这个算法就是先判断条件,再开始做事情,所以,我们之前也说到了,不能去掉“x/=10 n++”,我们有没有更好的算法或者结构,让他先做事情,最后进行判断。下面我们就来看看do while循环:
在进入循环的时候不做检查,而是在执行完一轮循环体的代码之后,再来检查循环的条件是否满足,如果满足则继续下一轮循环,不满足则结束循环。
do while的结构:
do
{
<循环体语句>
}while (<循环条件>);
小心:while结尾有个“;”
流程图:

把while和do while放在一起进行比较:

左边:do while 右边:while
他们最大的共同点就是循环体内的语句的内容是一样的!!!
do-while循环和while循环很像,区别是在循环体执行结束的时候才来判断条件。也就是说,无论如何,循环都会执行至少一遍,然后再来判断条件。与while循环相同的是,条件满足时执行循环,条件不满足时结束循环。
我们再把上面的程序改一下。
#include <stdio.h>
int main()
{
int x;
scanf("%d",&x);
int n =0;
do
{
x/=10;
n ++;
}while(x>0);
printf("%d",n);
return 0;
}
我们看一下把“0”输入的结果

前面我们分别说了while循环、do-while循环,下面我来看看for循环。
写一个程序,让用户输入n,然后计算输出n的阶乘。那么我们该怎么写?前面我们就提到过,我们想一个程序,我们从问题到程序,我们要想几件事情,首先,我们要有什么样的数据;我们在运算的过程中会得到什么数据,会产生什么数据;作为计算,我们还需要什么样的数据来辅助,也就是,在这个过程中,我们需要有什么样的变量呢?显然读用户的输入需要一个int的n,然后计算的结果需要用一个变量保存,可以是int的factor,在计算中需要有一个变量不断地从1递增到n,那可以是int的i。
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact =1;
int i =1;
while(i<=n){
fact *= i;
i++;
}
printf("%d!=%dn",n,fact);
return 0;
}
我们再用for循环来写一下。
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact =1;
int i =1;
for( i=1;i<=n;i++){
fact *= i;
}
printf("%d!=%dn",n,fact);
return 0;
}
for后面括号里的位置分别对应着(初始条件;循环继续的条件;循环每一轮要做的事情 )
for循环像一个计数循环:设定一个计数器,初始化它,然后在计数器到达某值之前,重复执行循环体,而每执行一轮循环,计数器以一定步进进行调整,比如加1或者减1 。
一般结构:
for(i=0;i<5;i=i+1){
printf("%d",i);
}
for = 对于。比如for(count = 10;count >0;count--)
我们就可以读成:“对于一开始的count=10,当count >0时,重复做循环体,每一轮循环在做完循环体内语句后,使得count--”
小套路:做求和的程序时,记录结果的变量应该初始化为0,而做求积的变量时,记录结果的变量应该初始化为1。
循环控制变量i只在循环里被使用了,在循环外面它没有任何用处。因此,我们可以把变量i的定义写到for语句里面去
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact =1;
for( int i=1;i<=n;i++){
fact *= i;
}
printf("%d!=%dn",n,fact);
return 0;
}
我们来运行一下。

出现了错误!!!它提示我们必须在c99的模式下使用,所以我们必须加上“-std=c99”才行。 c99的标准虽然已经很多年了,但是有一些用法,在不同的编译器里,他的接受程度是不一样的。我们前面用过一些c99的东西,比如“const”用来表达一个常量的,可以直接用来编译,可是,当我们 想把变量的定义加到for循环里,仍然需要给我编译器一个特殊的选项。
如果这个程序的循环不需要从1开始,因为1×1还是1,所以程序的循环不需要从1开始,那么改成从多少开始合适呢?很明显,只能从2开始。这样修改后,程序对所有的n都正确吗?这样的改动有价值吗?
除了可以从1乘到n来计算n!,还可以从n乘到1来计算吧?试试把循环换个方向来计算n。这时候,还需要循环控制变量i吗?
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact =1;
for( int i=n;i>1;i--){
fact *= i;
}
printf("%d!=%dn",n,fact);
return 0;
}
当然,我们可不可以再改一下,我们不用i,我们直接让n×(n-1)........
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact =1;
int i=n;
for( int n=n;n>1;n--){
fact *= n;
}
printf("%d!=%dn",i,fact);
return 0;
}
此时,我们发现在for循环里,n没做什么事,也就是定不定义n都行,我们再变一下,把int n=n 去掉。
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact =1;
int i=n;
for( ;n>1;n--){
fact *= n;
}
printf("%d!=%dn",i,fact);
return 0;
}
这个在for循环里也是允许的。
我们还要看一个小的事情,我们经常拿for循环做这样的一种事情,比如for(i=0;i<n;i++),这个循环的次数是n。循环的控制变量i,是选择从0开始还是从1开始,是判断i<n还是判断i<=n,对循环的次数,循环结束后变量的值都有影响。我们来看一下代码。
#include <stdio.h>
int main()
{
int i;
for (i=0;i<5;i++){
printf("i=%d",i);
}
printf("n最后i=%dn",i);
return 0;
}

我们把i=0改为i=1;i<5改为i<=5看看会怎么样
#include <stdio.h>
int main()
{
int i;
for (i=1;i<=5;i++){
printf("i=%d",i);
}
printf("n最后i=%dn",i);
return 0;
}

说了这么多for循环,我们发现它可以等价于while循环,它们都需要先初始化,然后判断,接着进入循环体。
再来整理下for循环:
for(初试动作;条件;每轮的动作){
}
for中的每一个表达式都是可以省略的;其中for(;条件;)==while(条件)
我们讲了半天的循环,已经学了3种,那么我们究竟该怎么选呢?
- 如果有固定次数,用for
- 如果必须执行一次,用do-while
- 其他情况用while
最后附思维(记忆)导图:

