1
计算机程序设计基础
第二讲 逻辑判断
2
二、逻辑判断
清华附中有四位同学中的一位做了好事,不留名,
表扬信来了之后,校长问这四位是谁做的好事。
?A说:不是我。
?B说:是 C。
?C说:是 D。
?D说:他胡说 。
已知三个人说的是真话,一个人说的是假话。现
在要根据这些信息,找出做了好事的人。
问题:谁做的好事?
3
二、逻辑判断
为了解这道题,我们要学习逻辑思维与判
断,以及如何解这类问题的思路。
1、关系运算符和关系表达式
> 大于
< 小于
>= 大于等于
== 等于
!= 不等于
4
二、逻辑判断
请大家看如下程序
// 程序 s2_1.c
#include <math.h>
void main( )
{
int b,c; // 整型变量
b=3;c=2; // 对变量赋值
printf(“3> 2 是 %d\n”,(b>c)); // 输出逻辑值
printf(“3>=2 是 %d\n”,(b>=c));
printf(“3==2 是 %d\n”,(b==c));
printf(“3< 2 是 %d\n”,(b<c));
printf(“3!=2 是 %d\n”,(b!=c));
}
5
二、逻辑判断
输出结果是,
3> 2 是 1 说明 3> 2 是真
3>=2 是 1 3>=2 是真
3==2 是 0 3==2 是假
3< 2 是 0 3< 2 是假
3!=2 是 1 3!=2 是真
6
二、逻辑判断
关系表达式
<变量 1> 关系运算符 <变量 2>
例 b>c,测试 b>c这种关系是否成立,成立
为真,不成立为假。
?成 立 —— 关系表达式的值为 1;
?不成立 —— 关系表达式的值为 0。
7
二、逻辑判断
这时在内存中系统找到一个字节。
? 让, ==”的含义为, 是,
? 让, !=”的含义为, 不是,
下面,我们把四个人说的四句话写成关
系表达式。在声明变量时,让 thisman
表示要找的人,定义他是字符变量
char thisman;
Thisman
地址 xxxx
8
二、逻辑判断
A说:不是我。写成关系表达式为 ( thisman!=?A?)
B说:是 C。 写成关系表达式为 ( thisman==?C?)
C说:是 D。 写成关系表达式为 ( thisman==?D?)
D说:他胡说。写成关系表达式为 ( thisman!=?D?)
在 C语言中字符也是有数值的,这个数值就是字符
的 ASCII码值
字符 A B C D
ASCII码值 65 66 67 68
9
二、逻辑判断
字符存放在内存中是以 ASCII码的形式存放
的,因此,用赋值语句
thisman = ?A?;
thisman = 65;
两者是等效的,在内存中存的都是 65。
可以做实验,如下例所示
Thisman
65
地址 xxxx
10
二、逻辑判断
// 例 s2_2.c
#include <math.h> // 包含头文件
void main( ) // 主函数
{
char thisman; // 声明字符变量
thisman=?A?; // thisman 赋值为 ?A?
printf(“thisman=%c \n”,thisman); // 输出 thisman的值
printf(,65==?A? ----取值为 %d\n”,65==?A?); // 验证
// 65是否等于‘ A?,并输出结果
}
thisman=A
65==?A?----取值为 1
编译链接后运行,
输出结果为,
11
二、逻辑判断
1、如何找到该人,一定是, 先假设该人是做好事者,
然后到每句话中去测试看有几句是真话, 。, 有三
句是真话就确定是该人,否则换下一人再试,。
比如,先假定是 A同学,让
thisman='A'; 代入到四句话中
思路,
A说,thisman!='A'; 'A'!='A' 假,值为 0。
B说,thisman=='C'; 'A'=='C' 假,值为 0。
C说,thisman=='D'; 'A'=='D' 假,值为 0。
D说,thisman!='D'; 'A'!='D' 真,值为 1。
显然,不是 'A'做的好事(四个关系表达式值的和为 1)
12
二、逻辑判断
再试 B同学,让 thisman='B';
代入到四句话中
思路,
A说,thisman!='A'; 'B'!='A' 真,值为 1。
B说,thisman=='C'; 'B'=='C' 假,值为 0。
C说,thisman=='D'; 'B'=='D' 假,值为 0。
D说,thisman!='D'; 'B'!='D' 真,值为 1。
显然,不是 'B'所为(四个关系表达式值的和为 2)
13
二、逻辑判断
再试 C同学,让 thisman=?C';
代入到四句话中
思路,
A说,thisman!='A'; 'C'!='A' 真,值为 1。
B说,thisman=='C'; 'C'=='C' 真,值为 1。
C说,thisman=='D'; 'C'=='D' 假,值为 0。
D说,thisman!='D'; 'C'!='D' 真,值为 1。
显然,就是 ?C?做了好事(四个关系表达式值之和为 3)
这时,我们可以理出头绪,要用所谓枚举法,一个人
一个人地去试,四句话中有三句为真,该人即所求。
14
二、逻辑判断
2、从编写程序的角度看,实现枚举最好用循环结构
for(k=1; k<=4; k=k+1)
{ // 循环体,开始
thisman = 64+k; // 产生被试者,依次给
// thisman赋值为 'A','B','C','D'
sum = (thisman!='A')+ // 'A'的话是否为真
(thisman=='C')+ // 'B'的话是否为真
(thisman=='D')+ // 'C'的话是否为真
(thisman!='D'); // 'D'的话是否为真
……
} // 循环体,结束
15
二、逻辑判断
我们可以抽象画出下图 来表示循环结构
for (表达式 1;表达式 2;表达式 3)
{
循环体语句
}
表达式 1——初始化工作,只做一次
表达式 2——进入循环体的条件,成立则进入
表达式 3——每次循环结束所做的工作
16
二、逻辑判断
测试表达式 2
求解表达式 1
执行循环体语句
求解表达式 3
f or 的下一条语句


循环控制变量置初值
测试是否达到终值
让循环控制变量增值
17
二、逻辑判断
#include <stdio.h> // 预编译命令,将标准输入
// 输出加到源文件中
void main( ) // 主函数
{
int i,sum; // 声明 i,sum为整数变量
sum=0; // 对求和变量 sum清零
for(i=1;i<=100;i=i+1) // 循环
{
sum=sum+i; // 累加求和
}
printf(“sum=%d \n”,sum); // 输出累加结果
}
举例:求自然数 1- 100之和( s2_3.c)
18
二、逻辑判断
可以改变表达式,看看运行结果。
比如,
for (i=1; i<=1000; i=i+2)
为了能够看清每一步,将程序改造为 s2_4.c
19
二、逻辑判断
// s2_4.c ( 1~10的和)
……
for(i=1; i<=10; i=i+1) // 控制变量 i初值为 1,终值为 10
{
printf("i=%d",i); // 输出 i的值
sum=sum+i; // 累加 i 到 sum 中
printf("\tsum=%d\n",sum);
// \t跳到下一个 Tab位置
for(j=1;j<=5500;j=j+1) // 延时
for(k=1;k<=10000;k=k+1); // 延时
}
20
二、逻辑判断
#include <stdio.h> // 预编译命令,将标准输入输出加入源文件
void main( ) // 主函数
{ // 开始
int i,j,k; // 声明 i,j,k为整型变量
long sum; // 声明 sum为长整数
sum=1; // 对 sum赋初值
for(i=10;i>=1;i=i-1) // 控制变量 i初值为 10,终值为 1
{ // 循环体开始
printf("i=%d",i); // 输出 i的值
sum=sum*i; // 累乘 i,放入 sum
printf("\tsum=%d\n",sum);// 输出累乘值
for(j=1;j<=5500;j=j+1) // 延时
for(k=1;k<=10000;k=k+1); // 延时
}
printf(“sum=%d \n”,sum); // 输出最终结果
}
例:计算 10!( s2_5.c)
21
二、逻辑判断
从以上这两个例子可以看出 for循环是一种计数型
循环,可以递增,也可以递减,使用起来很方
便。一般用在已知循环次数的情况下使用。
for循环的 NS图
for (i=1; i<=100; i=i+2)
循环体
22
二、逻辑判断
if (sum == 3)
{
printf("This man is %c\n",thisman);
g=1;
}
读作:如果 sum真的为 3时,做下面两件事
? ( 1)输出做好事的人;
? ( 2)将有解标志置 1。
其中 (sum==)为条件判断语句,根据其真假使程序
分支。
分支语句
23
二、逻辑判断
NS图为
条件为真吗?

语句块 1 语句块 2

24
二、逻辑判断
一般格式
? 1 if (表达式 )语句 1; // 语句 1,只一句
如果表达式为真,执行语句 1;否则什么都不做
? 2 if (表达式 )
{
语句块 1;
}
如果表达式为真,做语句块 1的内容;否则什么都不做;
25
二、逻辑判断
一般格式
? 3 if (表达式 ) 语句 1;
else 语句 2;
如果表达式为真,执行语句 1;否则执行语句 2
? 4 if (表达式 )
{
语句块 1;
}
else
{
语句块 1;
}
26
二、逻辑判断
举例:实现如图函数
x
y
- 1
1
0
1,0
0,0
1,0
x
yx
x
??
?
???
? ??
?
是 否
是 否
x > 0
y= 0 y= - 1
y= 1
x = = 0
27
二、逻辑判断
// s2_6.c
#include <stdio.h> //预编译命令,将标准输入输出
//函数作为头文件
void main( ) //主函数
{ //开始
int x,y; //变量 x,y为整数类型
printf("x="); //提示信息
scanf("%d",&x); //键盘输入一个整数放入 x中
if(x>0)y=1; //如果 x>0,则将 1赋给 y
else if(x==0) y=0;//否则,如果 x==0,则将 0赋给 y
else y=-1; //否则,将 -1赋给 y
printf("y=%d\n",y); //输出 y的值
} //结束
28
二、逻辑判断
NS图
是 否
是 否
x> 0
y= 0 y= - 1
y = 1
x= = 0
提示 和 输入整数 x
输出 y
29
NS图
fo r (k = 1 ; k < = 4 ; k = k + 1 )
被试者 thi s m a n = 6 4 + k ;
s um = ( 被试者 th i s m a n != ? A ? )+
( 被试者 thism a n == ? C ? )+
( 被试者 thism a n == ? D ? )+
( 被试者 thism a n != ? D ? );
S um == 3
假 真
输出该被试者;
有解标志 g= 1;
g < > 1 假 真
输出无解信息;
有了上述了解之后,我们来看解“谁做的好事”
的程序框图
根据上述框图写出的程序见 s2_7.c
30
#include <stdio.h>
void main() // 主函数
{
int k,sum,g; // 声明变量为整数类型
for(k=1;k<=4;k=k+1) // 循环从 k为 1到 4,
// k取 1,2,3,4分别代表 A,B,C,D
{ // 循环,开始
sum=0; // 初始化,置 0
if (k!=1) sum=sum+1; // A说的话,如为真,则令 sum加 1;
if (k==3) sum=sum+1; // B说的话,如为真,则令 sum加 1;
if (k==4) sum=sum+1; // C说的话,如为真,则令 sum加 1;
if (k!=4) sum=sum+1; // D说的话,如为真,则令 sum加 1;
if (sum==3) // 若有三句话为真话,则做下列两件事
{
printf(“This man is %c \n”,64+k); // 输出
g=1; // 让有解标志置 1
}
}
if (g!=1) printf(“Can?t found!”); // 如 g不为 1,则输出无解信息
}
讨论:下面这个程序行不行,从思路上讨论
31
二、逻辑判断
上述程序可以简化为,
#include <stdio.h>
void main( )
{
int k,g; // 声明变量为整数类型
for (k=1; k<=4; k=k+1) // 这里 k既为循环控制变量,
// 也表示第 k个人
{
if (((k!=1)+(k==3)+(k==4)+(k!=4))==3)
{ // 如果 4句话有 3句为真,则输出该人
printf(“Thisman is %c \n”,64+k);
g=1;
}
}
if (g!=1) printf(“Can?t found!\n”); // 输出无解信息
}
32
二、逻辑判断
大家参与讨论的题
五位跳水高手将参加十米高台跳水决赛,有好事者让五
个人据实力预测比赛结果。
A选手说,B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说,C最后,我第三;
E选手说:我第四,A第一;
决赛成绩公布之后,每位选手的预测都只说对了一半,
即一对一错,请编程解出比赛的实际名次。
33
二、逻辑判断
思路,
1 首先是将五个人的预测写成逻辑表达式,
让关系运算符, ==” 的含义是, 是, 。
让数字 1,2,3,4,5分别表示名次第一、第二,…,
第五 。
让整型变量 A,B,C,D,E分别表示每个选手所得名次。
A选手说,B==2,A==3;
B选手说,B==2,E==4;
C选手说,C==1,D==2;
D选手说,C==5,D==3;
E选手说,E==4,A==1;
34
二、逻辑判断
2 考虑到每个人说的话是一对一错,即一真一假,比如 A
说的,如 B==2为真,则 A==3为假,为真取值为 1,为假
取值为 0,则两个关系表达式之和必为 1。即
(B==2)+(A==3)应该是 1
我们可以归纳出要同时满足五个人所说的话都符合一半对
一半错的条件是
ta=((B==2)+(A==3))==1; 符合 A选手的话,则 ta为 1
tb=((B==2)+(E==4))==1; 符合 B选手的话,则 tb为 1
tc=((C==1)+(D==2))==1; 符合 C选手的话,则 tc为 1
td=((C==5)+(D==3))==1; 符合 D选手的话,则 td为 1
te=((E==4)+(A==1))==1; 符合 E选手的话,则 te为 1
因为 ta,tb,…,te 非 1即 0,五个条件值都加在一起
05ta tb tc td te? ? ? ? ? ?
35
二、逻辑判断
3 只有等于 5时才都符合每个人所说的话,这仅只是符合
题意的一个必要条件,同时还得考虑 A,B,C,D,E
的取值不得有相同者
,,,,{ 1,2,3,4,5 }A B C D E
A B C D E
?
? ? ? ?且
可以考虑
* * * * 1 2 0A B C D E ??是一个条件
4 仍然可以用枚举的方法,让变量 A,B,C,D,E在
1~5中取值,形成满足上述条件的 A~E的组合,即是
所求。这时可用循环结构,如下所示
36
输出 A,B,C,D,E
t= = 5 假 真
ta = ( (B= = 2 )+ (A = = 3 )) = = 1 ;
tb= ((B = = 2 ) + (E= = 4 )) = = 1 ;
tc= ((C = = 1 )+ (D = = 2 )) = = 1 ;
td= ((C = = 5 )+ (D = = 3 )) = = 1 ;
te= ((E = = 4 ) + (A = = 1 ) ) = = 1 ;
t= ta + tb + tc + td+ te;
假 真 A * B* C * D * E = = 1 2 0
E= 1 5 - (A + B+ C + D );
f o r ( D = 1 ; D < = 5 ; D = D + 1 )
f o r ( C = 1 ; C < = 5 ; C = C + 1 )
f o r ( B = 1 ; B < = 5 ; B = B + 1 )
f o r ( A = 1 ; A < = 5 ; A = A + 1 )
37
二、逻辑判断
作业,
1 请你自己完成这个程序;
2 思考如何提高效率?
3 思考还有什么其它解法?
38
二、逻辑判断
逻辑表达式
某地刑侦大队涉及六个嫌疑人的一桩疑案进行分析,
? A,B至少有一人作案;
? A,E,F三人中有两人参与作案;
? A,D不可能是同案犯;
? B,C或同时作案,或与本案无关;
? C,D中有且仅有一人作案;
? 如果 D没有参与作案,则 E也不可能参与作案。
试编一程序,将作案人找出来。
39
二、逻辑判断
为了解这道题,我们要研究逻辑运算符与逻辑表达式。
1、逻辑与,运算符为 &&
如图电路
A—— 表示开关 A合上;
B—— 表示开关 B合上;
A&&B—— 表示灯亮;
B A
A && B
A B A&&B
1 1 1
1 0 0
0 1 0
0 0 0
1表示真,0表示假,这是逻辑变量的取值,非真即假
40
二、逻辑判断
2、逻辑或,运算符为 ||
如图电路
A—— 表示开关 A合上;
B—— 表示开关 B合上;
A||B—— 表示灯亮;
B A
A || B
A B A||B
1 1 1
1 0 1
0 1 1
0 0 0
1表示真,0表示假
41
二、逻辑判断
3、逻辑非,运算符为 !
两队比赛篮球,变量 A表示 A队到场,!A表示 A队不
到场,变量 B表示 B队到场,!B表示 B队不到场。
这场球赛能够赛成,得两队都到场。假定, 能
赛成, 用逻辑变量 C表示,则
C = A&&B
赛不成当然用 !C表示,让 D = !C,D表示赛不成则
D=!A||!B。
理解为 A不到场或 B不到场,球赛无法进行。
42
二、逻辑判断
1 案情分析:将案情的每一条写成逻辑表达式,第一条
用 CC1表示,第二条用 CC2表示,……
CC1,A和 B至少有一人作案
令 A变量表示 A作案
B变量表示 B作案
A B CC1
0 0 0
1 0 1
0 1 1
1 1 1
显然这是或的关系,因此有 CC1=(A||B)
思路,
43
二、逻辑判断
CC2,A和 D不可能是同案犯
可以分析为,
? A如果是案犯,D一定不是案犯,写成 A&&(!D)
? D如果是案犯,A一定不是案犯,写成 D&&(!A)
这两者之间是或的关系,因此有
CC2=((A&&(!D))||(D&&(!A)))
A !A D !D A&&(!D) D&&(!A) CC2
1 0 1 0 0 0 0
1 0 0 1 1 0 1
0 1 1 0 0 1 1
0 1 0 1 0 0 0
44
二、逻辑判断
在上表中先将 A,D和 CC2抽出
A D CC2
1 1 0
1 0 1
0 1 1
0 0 0
这叫, 异或, 运算,CC2=((A&&(!D))||(D&&(!A)))
在数字逻辑课中表示为
在计算机中是半加器(二进制) AD AD?1 0 1 0
1 1 0 0
0 1 1 0
45
二、逻辑判断
CC3,A,E,F中至少有两人涉嫌作案,分析有三种可能
? 第一种,A和 E作案,F不作案( A&&E&&(!F))
? 第二种,A和 F作案,E不作案( A&&F&&(!E))
? 第三种,E和 F作案,A不作案( E&&F&&(!A))
这三种可能性是或的关系,因此有
CC3= (A&&E&&(!F)) ||( A&&F&&(!E)) ||( E&&F&&(!A))
我们写出 CC3的真值表。
46
二、逻辑判断
A E F A&&E&&(!F) A&&F&&(!E) E&&F&&(!A) CC3
1 1 1 0 0 0 0
1 1 0 1 0 0 1
1 0 1 0 1 0 1
0 1 1 0 0 1 1
0 0 1 0 0 0 0
0 1 0 0 0 0 0
1 0 0 0 0 0 0
0 0 0 0 0 0 0
47
二、逻辑判断
CC4,B和 C或同时作案,或都与本案无关
第一种情况:同时作案( B&&C)
第二种情况:都与本案无关(! B&&! C)
两者为或的关系,因此有
CC4=(B&&C)||(!B&&!C)
B C !B !C B&&C !B&&!C CC3
1 1 0 0 1 0 1
1 0 0 1 0 0 0
0 1 1 0 0 0 0
0 0 1 1 0 1 1
CC5,C,D中有且仅有一人作案
CC5=(C&&!D)||(D&&!C)
48
二、逻辑判断
CC6,如果 D没有参与作案,则 E也不可能参与作案。
分析这一条比较麻烦一些,可以列出真值表再归纳
( ) ( )
( ) ( )
D E D E D E
D E D E D E D E
D E E E D D
DE
??
? ? ? ?
? ? ? ?
?? CC6=D||!E
1 0
1 1
以上是案情分析,已经化成了计算机可解的逻辑表达式
D E !E CC6 含义
1 1 0 1 D作案,E也作案 可能
1 0 1 1 D作案,E不作案 可能
0 0 1 1 D不作案,E也不可能作案 可能
0 1 0 0 D不作案,E却作案 不可能
DD
E
E
49
二、逻辑判断
2 采取枚举方法,枚举什么呢?枚举组合。
6个人每个人都有作案或不作案两种可能,因此有
种组合,从这些组合中挑出符合 6条分析的作案者。
定义 6个整数变量,分别表示 6个人 A,B,C,D,E,F。
枚举每个人的可能性
? 让 0表示不是罪犯;
? 让 1表示就是罪犯。
62
50
输出
C C 1+ C C 2+ C C 3+ C C 4+ C C 5+C C 6= =6
假 真
C C 1 = A || B;
C C 2 = (A& & (!D))|| ( D & & (!A));
C C 3 = (A& & E& & (!F))|| (A& & F & & (!E) )
|| (E&& F & & (!A));
C C 4 = (B&& C )|| (! B & & !C);
C C 5 = (C& & !D)||( D & & !C);
C C 6 = D || (!E );
fo r (F = 0 ; F < = 1 ; F = F + 1 )
fo r (E = 0 ; E< = 1 ; E = E+ 1 )
fo r (D = 0 ; D < = 1 ; D = D + 1 )
fo r (C = 0 ; C < = 1 ; C = C + 1 )
fo r (B = 0 ; B< = 1 ; B = B+ 1 )
fo r (A = 0 ; A < = 1 ; A = A + 1 )