C 控制流 之 条件判断

我恍然觉得,我低估了C语言中的知识量。想要用一篇文章解决控制流部分,文章就会变得很长,内容也显得很杂乱了。为了保证文章的条理清晰,我把控制流分解成了两篇:上篇介绍条件判断,下篇介绍循环。

那么就让我们开始吧!

什么是控制流

上回中,C语言里最基本的元素——变量闪亮登场。通过使用运算符,我们进行了简单的数学运算。接下来,为了使它能够完成更复杂的任务,我们要用到控制流。

什么是控制流?简单地说,控制流就是对程序运行流程的控制,它决定了什么时候程序会执行什么功能。在生活中,我们总是着面临多种可能性,例如,明天可能会下雨,也可能不下雨。如果不下雨,你需要给树苗浇水,但如果下雨就不浇了。想让程序能和人类一样处理多种情况,就需要控制流中的条件判断功能。

有些时候,你需要重复地做一些事情,一直到任务完成为止。例如你要吹个气球,在吹起来之前要重复吹气这个动作。吹的不够,气球就瘪瘪的,吹太多,气球就会爆炸,因此你需要在合适的时机停止。在计算机的工作中也有很多这样的任务,这需要循环语句来控制。

就像开头说的,为了让文章比较好读,我就专注于介绍条件判断了。

bool类型与逻辑运算符

在介绍条件判断的语句之前,我们需要了解一些基础知识:bool类型与逻辑运算符。

程序在不同的情况下采取不同的行为,我们可以理解为有一个开关控制着它。如果开关打开,它会做出A行为,如果开关关上了,他就会做出B行为。bool类型(译作布尔类型)就是用于描述开关状态的一种变量,它只有两个取值,true和false,对应于开关的打开和关上。定义和使用bool类型的方法与其他类型相同:

bool isSunny = true; //定义了一个bool变量,初始化为true
isSunny = false;     //下雨了,把它赋值为false,-v-

作用于bool类型的运算符称为逻辑运算符,正因为这个类型与程序的运行逻辑息息相关。逻辑运算符包括 ||、&&和!。

先把代码列出来,结合代码来看这些运算符的功能:

bool isMale = true;
bool isChild = false;
bool isHuman = isMale || isChild;
bool isBoy = isMale && isChld;
bool isFemale = !isMale;

|| 被称为“逻辑或”,代表了“或者”的功能,它的定义是这样的:如果isMale和isChild中有至少一个是true,那么isHuman将是true;只有当两者都是false时,isHuman才是false。这里的例子是,如果一个人是男人,或者是个孩子,他就满足了是人类的条件(当然这是充分条件,但是不是必要条件)。

&& 被称为“逻辑与”,代表了“并且”的功能,同样看上面的几行代码。只有isMale和isChild同时是true,isBoy才会是true;如果两者中至少有一个是false,那么isBoy就是false。解释就是,只有一个人同时是男性且是孩子时,他才是一个男孩。

! 被称为“逻辑非”,代表了“非”的功能。它只作用在单个操作数上,对true的运算结果是false,对false的运算结果是true。所以一个人如果不是男性,那么他就是女性。(啊不过,现实中是存在很多跨性别的人的,所以这里只是举个例子而已,不要太认真。)

这里还需要解释的一个概念是运算的优先级。在C语言中,会有这样的问题:

int c = 5 * 10 + 6;

与现实中的数学算式一样,乘法的优先级会大于加法。为了让加法先算,我们必须添加括号:

int c = 5 * (10 + 6);

对于逻辑运算符,它们的优先关系是这样的:

逻辑非 > 逻辑与 > 逻辑或

bool isGirl = !isMale && isChild; //先判定!,再判定&&
bool isFood = isBread || isMeat && isCooked; //先判定&&,再判定||

对于isGirl,只有isMale为false,isChild为true时,结果才是true。
对于isFood,不论isMeat和isCooked是什么值,只要isBread为true,结果就是true。

虽然优先关系不难理解,但是为了看着舒服,加些括号也是可以的。例如:

bool isGirl = (!isMale) && isChild; //先判定!,再判定&&
bool isFood = isBread || (isMeat && isCooked); //先判定&&,再判定||

但是如果括号加错了,结果就会变得很奇怪。

if 语句

这些bool变量和逻辑运算符能够如此正确地表达事情的逻辑关系,真是挺不可思议的一件事。关于这个话题,还有专门的一个学科,叫做“数理逻辑”,但因为我也没有学过,所以没办法介绍了。嗯,不管了,来看看这些东西怎么应用在条件判断中吧。

条件判断的语句中,最常用的就是if 语句和switch 语句。先看代码:

int a = 5;

if(a == 0)
    printf("a is zero.\n");
else
    printf("a is not zero.\n");

printf("Oh, I am hungry.\n");

这就是一个典型的if语句。

if 后面跟一个括号,其中包含了一个表达式 a==0。== 是一个运算符,判断两边的值是否相等,结果是一个bool类型的值。如果是true,程序会选择执行下一行中,然后跳过else 的部分。但如果是false,程序就会选择执行else中的部分。如果不写else的部分,程序就会在false的情况下什么都不做。

如果需要处理很多种情况,就需要请出else if 了。

int age = 50;

if(age < 18) // < 表示判断是否小于,小于等于就用 <=
    printf("he is a teenager!");
else if(age > 50)  // > 表示判断是否大于,大于等于就用 >=
    printf("he is old!");
else
    printf("he is neither young nor old");

这里只出现了一个else if,实际上可以加入任意数量的else if,以处理各种各样的情况。要确保else if一定要在else之前出现。

条件表达式的一些琐碎

括号中的表达式,也可以用变量或者数值代替。

bool isPig = true;
if(isPig){
    printf("It is a pig.\n");
    printf("只是为了加一句话。\n");
    printf("别忘了用花括号!\n");
}

这里使用bool变量作为判断依据。其实也可以用整数类型的变量,0对应于false,值不为0的情况则都会被视为true。

另一个注意事项是花括号的使用,如果if或者else后面跟了多行代码,必须要用花括号包起来。如果不用花括号包起来,只有第一句会被当做特定条件下才会执行的语句,后面的代码不再属于if或者else。对于else if也是同理。

还有一点就是==是两个等于号连在一起,如果只写一个=,那就变成了赋值表达式。因为很重要所以再说一遍,在判断相等的场合,一定要确保自己真的写了“==”

switch语句

为了处理多种情况,我们还可以使用switch语句,用法如下:

int a = 0;
switch(a){
case -1:
    printf("a is -1.\n");
    a += 7; //a = a + 7的简写
    break;
case 7:
    a -= 7; //a = a - 7 的简写
    break;
case 20000:
    printf(" a is 20000!\n");
    break;
default:
    printf("a default case.\n");
    break;
}

switch关键字后面的括号中应包含一个变量,程序将根据这个变量的值执行不同的代码。为了处理某一情况,例如a等于-1,就在switch语句的花括号中添加一个对应的段落:

case -1: //case 需处理的数值:
    printf("a is -1.\n");
    a += 7; 
    break; //处理完毕,结束switch语句

程序会根据a的值寻找处理的代码,如果每个case都没遇到,就会执行default中的代码作为默认的处理方式。default这一段也可以不写,这样在默认的情况下,程序就会什么都不做。

break语句在这里非常重要,如果忘了写,程序就会继续执行下一个case中的代码,然后程序就乱了套了。

举个例子,如果在case -1中忘了写break,

...
case -1:
    printf("a is -1.\n");
    a += 7; 
    //忘了写break!
case 7:
    a -= 7;
    break;
default:
...

如果a恰好等于1,执行到了a加7,之后没有跳出switch语句,接着就会执行case 7中的printf语句。这肯定不是我们想要的结果。你可能要问了,那case 7:这一行到底是干嘛的?事实上,这一行只能被switch关键字用来定位,不能阻止程序从上一行运行下来。

switch语句的功能其实if也能做到,之所以存在这么一种写法,基本上是为了使程序更整齐、容易阅读。虽然对于计算机来说没什么分别,但是程序终究还是人类使用的语言,保证代码的易读性,能大大降低我们维护代码的难度。

小结

现在程序能根据不同情况选择不同的行为了。循环是在此基础上自然形成的另一种功能,它将机器强大的能力展露无遗。下一篇我们将认识这一功能,让计算机强大的力量开始为自己所用。

那么,就先写到这里吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容