啊哈C语言逻辑的挑战修订版附答案.pdf
http://www.100md.com
2020年11月6日
![]() |
| 第1页 |
![]() |
| 第8页 |
![]() |
| 第11页 |
![]() |
| 第22页 |
![]() |
| 第50页 |
![]() |
| 第233页 |
参见附件(6134KB,378页)。
《啊哈C语言!逻辑的挑战(修订版)》从开始学习与计算机对话到自己独立制作一个游戏,由浅入深地讲述编程的思维。同时,与计算机展开的逻辑较量一定会让你觉得很有意思

内容简介
这是一本非常有趣的编程启蒙书,全书从中小学生的角度来讲述,没有生涩的内容,取而代之的是生动活泼的漫画和风趣幽默的文字。并配合超萌的编程软件,从开始学习与计算机对话到自己独立制作一个游戏,由浅入深地讲述编程的思维。同时,与计算机展开的逻辑较量一定会让你觉得很有意思。你可以在茶余饭后阅读本书,甚至蹲在马桶上时也可以看得津津有味。编程将会改变我们的思维,教会我们如何思考,让我们的思维插上计算机的翅膀,以一种全新的方式来看世界。现在就让我们一起走进计算机编程的神奇世界,探索和发现计算机编程的魔力吧!
作者简介
啊哈磊,原名纪磊,毕业于武汉大学。曾在中科院玩单片机,在微软亚洲研究院开发“爬虫”,在IEEE国际会议上发表论文,也做过老师,是全国青少年信息学奥林匹克金牌教练。著有《啊哈C!语言》和《啊哈!算法》系列编程科普丛书,并被引进至港澳台地区。非常喜欢小朋友,每天都过得很开心。为什么叫“啊哈磊”呢?因为这是一个很喜庆的名字。
精彩书评
百度移动云首席布道师张辉:学习编程能为自己打开一扇全新的窗户。本书可能是*通俗易懂、生动好玩的C语言教程,它不只是让你成为编程大师,更是帮你理解身边的种种奇妙。
chd9527:想学C,发现其他入门书的门槛挺高,看不懂。偶尔发现这本小学生都能读懂的C语言书籍,学习了一下,觉得写得很好,和“入门”一词真的很贴切。
阳光雨:不但教大家怎样去做,关键是告诉大家原理!语言幽默生动,有很亲切的感觉。比奥数有趣有意思,可以提升孩子的逻辑思考力。
家长100鱼小肥:通俗易懂,可以作为孩子的编程启蒙读物,是很好的科普书,能把复杂的知识用简单的方式表达出来,孩子看了很感兴趣。如果编程书都能写得如此风趣,自学将变得很轻松。
tingting:这本书从小朋友的角度和立场读起来一点都不费劲。跟同类的书籍比起来,更加通俗易懂,生动有趣。
mijianxing:我一直想通过学编程更好地了解这个世界,对照这本书,自己编一些小程序,亲自设计的感觉很奇妙。
jocal:推荐的啊哈C编程工具也挺好用的,简洁明了!小朋友看着书,自己跟着一步步操作,很有成就感!
目 录
第1章 编程改变思维 1
第1节 为什么要学习编程 1
第2节 本书是讲什么的,写给谁看的 4
第2章 梦想启航 7
第1节 编程的魔力 7
第2节 让计算机开口说话 9
第3节 多彩一点 18
第4节 让计算机做加法 21
第5节 数字的家――变量 26
第6节 数据输出――我说咋地就咋地 31
第7节 数据输入――我说算啥就算啥 33
第8节 究竟有多少种小房子 37
第9节 拨开云雾见月明 40
第10节 逻辑挑战1:交换小房子中的数 42
第11节 天啊!这怎么能看懂 45
第3章 较量才刚刚开始 49
第1节 大于、小于还是相等 49
第2节 判断正数 50
第3节 偶数判断 54
第4节 神器else 56
第5节 请告诉我谁大 59
第6节 逻辑挑战2:3个数怎么办 61
第7节 逻辑挑战3:我要排序 66
第8节 运算符总结 71
第9节 1>2究竟对不对 71
第10节 讨厌的嵌套 74
第11节 if-else语法总结 78
第4章 重量级选手登场 79
第1节 永不停止的哭声 79
第2节 我说几遍就几遍 83
第3节 if对while说:我对你很重要 88
第4节 求和!求和!!求和!!! 90
第5节 逻辑挑战4:60秒倒计时开始 95
第6节 这个有点晕――循环嵌套来了 99
第7节 逻辑挑战5:奔跑的字母 104
第8节 究竟循环了多少次 108
第9节 逻辑挑战6:奔跑的小人 110
第10节 for隆重登场 114
第5章 好戏在后面 118
第1节 程序的3种结构 118
第2节 嗦一下 119
第3节 逻辑挑战7:判读质数很简单 120
第4节 更快一点:break 125
第5节 continue 126
第6节 逻辑挑战8:验证哥德巴赫猜想 127
第7节 逻辑挑战9:水仙花数 130
第8节 逻辑挑战10:解决奥数难题 135
第9节 逻辑挑战11:猜数游戏 138
第10节 逻辑挑战12:你好坏,关机啦 142
第6章 天啊!一大串数正在接近 144
第1节 逆序输出 144
第2节 申请100个小房子怎么办 145
第3节 100个数的逆序 147
第4节 逻辑挑战13:陶陶摘苹果 148
第5节 逻辑挑战14:一个萝卜一个坑 151
第6节 逻辑挑战15:选择排序 156
第7节 二维数组 159
第8节 剩下的一些东西 161
第7章 有了它你能做更多的事 165
第1节 字符的妙用 165
第2节 多余的回车键 167
第3节 字符的本质 169
第4节 人名怎么存储呢 171
第5节 逻辑挑战16:字母的排序 176
第6节 逻辑挑战17:字典序 177
第7节 多行字符 179
第8节 存储一个迷宫 182
第8章 游戏时间到了 184
第1节 走迷宫 184
第2节 推箱子 194
附录A 标识符命名规则 197
附录B 运算符的优先级和结合性 199
啊哈C语言逻辑的挑战修订版截图




啊哈C语言!
逻辑的挑战
修订版
啊哈磊著
電子工業出版社 ·
Publishing House of Electronics Industry
北京·BEIJING内容简介
这是一本非常有趣的编程启蒙书,全书从中小学生的角度来讲述,没有生涩的内容,取而代之的是生动活泼的漫画和风趣幽默的文字。配
合超萌的编程软件,本书从开始学习与计算机对话到自己独立制作一个
游戏,由浅入深地讲述编程的思维。同时,与计算机展开的逻辑较量一
定会让你觉得很有意思。你可以在茶余饭后阅读本书,甚至坐在马桶上
也可以看得津津有味。编程将会改变我们的思维,教会我们如何思考,让我们的思维插上计算机的翅膀,以一种全新的方式来感知世界。未经许可,不得以任何方式复制或抄袭本书之部分或全部内容。
版权所有,侵权必究。
图书在版编目(CIP)数据
啊哈C语言!:逻辑的挑战啊哈磊著.—修订本. —北京:电子工业
出版社:2017.1
ISBN 978-7-121-30462-0
Ⅰ.①啊… Ⅱ.①啊… Ⅲ.①C语言-程序设计-青少年读物
Ⅳ.①TP312.8-49
中国版本图书馆CIP数据核字(2016)第284866号
责任编辑:徐津平
印 刷:中国电影出版社印刷厂
装 订:中国电影出版社印刷厂出版发行:电子工业出版社
北京市海淀区万寿路173信箱 邮编100036
开 本:787×980 116
印 张:13
字 数:255千字
版 次:2013年9月第1版
2017年1月第2版
印 次:2017年1月第1次印刷
印 数:4000册
定 价:49.00元
凡所购买电子工业出版社图书有缺损问题,请向购买书店调换。若书店
售缺,请与本社发行部联系,联系及邮购电话:(010)88254888,88258888。
质量投诉请发邮件至zlts@phei.com.cn,盗版侵权举报请发邮件至
dbqq@phei.com.cn。
本书咨询联系方式:(010)51260888-819, faq@phei.com.cn。修订版序
自《啊哈C》出版以来,我与编程爱好者们便有了更多的交流机
会。这些编程爱好者之中不乏大学生、中学生、老师、家长,更有小学
二、三年级的学生。令我惊喜的是,二、三年级的小读者们与我探讨的
并不是浅显的语法或BUG调试问题,更多的是他们通过独立思考发的书
中的错误,他们向我阐述自己的思想,与我交流游戏开发中遇到的逻
辑、算法等。还有一些读者留言说:“这本书不仅仅是小学生坐在马桶
上都能看懂的书,是连我妈妈或是我姥姥都能看懂的编程书!”这些读
者实在是太捧场了,有幸让我体验了一次漫卷诗书喜欲狂的感觉。也有
好多读者看完后直呼不过瘾,常常询问何时能有第二部。一晃已是三
年,借此《啊哈C语言!逻辑的挑战》修订之际,第二部《啊哈C语
言!游戏实验室》也如期而至,它景致依旧,故事常新,希望你能喜
欢!让我们再次共同探索编程与梦想的一切可能。
啊哈磊
2016年12月第一版序
我经常被问到一个问题:当初为什么会去学编程?我的回答是,因
为我很喜欢玩游戏。每一个喜欢玩游戏的人,都梦想着可以通过修改游
戏的程序使游戏中的自己变得非常强大,而这需要学习编程。其实每一
个喜欢玩游戏的人都曾有过创造游戏的梦想,那我们为什么不把这种梦
想变成学习的动力呢?我就是这样踏上编程之路的。
牛人肯·汤普逊(Kenneth Lane Thompson)自己编写了一个叫作“星
际旅行(Star Travel)”的游戏。而汤普逊为了能更顺畅地玩这个游戏,竟然自己动手用汇编写了UNIX操作系统。后来他觉得用汇编写UNIX操
作系统非常麻烦和辛苦,于是和另一个牛人丹尼斯·里奇一起创造了C语
言。没想到吧,C语言竟然是一个牛人为了玩自己写的游戏而创造的。
其实这在计算机界很正常,程序员们往往就是因为某个游戏或者软件的
现有功能不能满足自己的需求,才开发出了更加优秀的游戏和软件。本
书中超萌、超简洁的“啊哈C语言”编程软件也是这样来的。
我经常被问到的第二个问题:为什么普通人需要关心编程呢?我的
答案是,因为当下程序员几乎主宰了整个世界,控制着生活的方方面
面。我们住的房子、穿的衣服、吃的东西、用的各种电子产品,以及我
们去ATM取钱、坐电梯、开汽车、坐飞机、坐火车等,都离不开编
程。你坐火车时有没有想过,一条铁轨上同时运行的那么多列火车是如
何调度才没有导致它们相撞的。这个时代很难想象还有什么不是通过计
算机程序控制的。如果想理解这个时代,就必须理解计算机编程。编程
会让我们以一种全新的方式来看世界。当然,在学习编程的过程中还可以提高我们的逻辑推理能力、批判性思维和动手解决问题的能力。与计
算机展开的逻辑较量一定会让你觉得很有意思。
我还经常被问到第三个问题:什么样的人可以自学编程,学习编程
需要什么基础?答案是,你只需具有小学四年级以上文化程度,并且熟
练运用鼠标和键盘就可以。你若不信,那就从这本书开始吧。
编程很容易让我们实现梦想。如果我们觉得某个游戏玩得不爽想提
升体验,或者觉得某个软件不够好用想自己做一个,没问题,现在就可
以!而唯一的投入就是一台计算机。实现梦想从未变得如此简单。编程
世界里每天都上演着传奇,一大批热爱编程并且满怀梦想的人正在充满
激情地奋斗着。
编程将会改变我们的思维,教给我们如何思考,会编程的人总想改
变点什么。正如乔布斯所说“I think everybody in this country should learn
how to program a computer, should learn a computer language, because it
teaches you how to think.”
啊哈磊
2013年9月注:文中出现的“□”同原版纸书目 录
修订版序
第一版序
第1章 编程改变思维
第1节 为什么要学习编程
第2节 本书是讲什么的,写给谁看的
第2章 梦想启航
第1节 编程的魔力
第2节 让计算机开口说话
第3节 多彩一点
第4节 让计算机做加法
第5节 数字的家——变量
第6节 数据输出——我说咋地就咋地
第7节 数据输入——我说算啥就算啥
第8节 究竟有多少种小房子
第9节 拨开云雾见月明
第10节 逻辑挑战1:交换小房子中的数
第11节 天啊!这怎么能看懂
第3章 较量才刚刚开始
第1节 大于、小于还是相等
第2节 判断正数
第3节 偶数判断
第4节 神器else
第5节 请告诉我谁大
第6节 逻辑挑战2:3个数怎么办第7节 逻辑挑战3:我要排序
第8节 运算符总结
第9节 1>2究竟对不对
第10节 讨厌的嵌套
第11节 if-else语法总结
第4章 重量级选手登场
第1节 永不停止的哭声
第2节 我说几遍就几遍
第3节 if对while说:我对你很重要
第4节 求和!求和!!求和!!!
第5节 逻辑挑战4:60秒倒计时开始
第6节 这个有点晕——循环嵌套来了
第7节 逻辑挑战5:奔跑的字母
第8节 究竟循环了多少次
第9节 逻辑挑战6:奔跑的小人
第10节 for隆重登场
第5章 好戏在后面
第1节 程序的3种结构
第2节 啰嗦一下
第3节 逻辑挑战7:判读质数很简单
第4节 更快一点:break
第5节 continue
第6节 逻辑挑战8:验证哥德巴赫猜想
第7节 逻辑挑战9:水仙花数
第8节 逻辑挑战10:解决奥数难题
第9节 逻辑挑战11:猜数游戏
第10节 逻辑挑战12:你好坏,关机啦第6章 天啊!一大串数正在接近
第1节 逆序输出
第2节 申请100个小房子怎么办
第3节 100个数的逆序
第4节 逻辑挑战13:陶陶摘苹果
第5节 逻辑挑战14:一个萝卜一个坑
第6节 逻辑挑战15:选择排序
第7节 二维数组
第8节 剩下的一些东西
第7章 有了它你能做更多的事
第1节 字符的妙用
第2节 多余的回车键
第3节 字符的本质
第4节 人名怎么存储呢
第5节 逻辑挑战16:字母的排序
第6节 逻辑挑战17:字典序
第7节 多行字符
第8节 存储一个迷宫
第8章 游戏时间到了
第1节 走迷宫
第2节 推箱子
附录A 标识符命名规则
附录B 运算符的优先级和结合性第1章
编程改变思维
第1节 为什么要学习编程
你是否还在将计算机(电脑)当作上网、聊天和玩游戏的工具?没
错,大部分人是这样的。当你拿起本书阅读到这里的时候,太好了,你
又多了一个更好的选择,一个独特的机会!
在我们生活的这个时代,你会发现有这样一群人,他们对世界的影
响越来越大,电视、报纸和网络到处都充斥着他们的身影。比尔·盖茨
创立了微软,让计算机更容易被我们平常人所使用
[1];乔布斯创立了
苹果,iPhone、iPad和iPod每一样产品都在改变着我们的日常生活;谢
尔盖·布林和拉里·佩奇两个年轻的小伙创立了Google,使得获取知识变得前所未有的容易;马克·扎克伯格创立了Facebook,正在改变人与人
之间的关系……甚至12岁的小软件工程师托马斯·苏亚雷斯
[2]
都在改变
我们的世界。他们是怎样的一群人?他们为什么会创造奇迹?巧的是他
们都有一个共同的特点:在少年时都酷爱计算机编程。计算机编程究竟
具有怎样的非凡魔力?计算机编程是否给他们带来与常人不同的思维或
思考方式?是否是计算机编程为他们开启了不一样的人生道路?
为什么他们从小就开始接触计算机,不但没有沉迷于游戏,反而改
变了世界呢?12岁的托马斯说:“现在的孩子们不再只是爱玩游戏,他
们还想自己制作好玩的游戏,不过孩子们大多不知道去哪里学习计算机
编程,而懂得计算机编程的家长又很少。”
其实每个人在童年时期都曾经有创造游戏的梦想,我们为什么不把
这种梦想变成学习的动力呢?大部分孩子在面对计算机的时候都缺乏引
导,因为他们不知道计算机除了上网、聊天和玩游戏外还能做什么。即
使有人想深入地学习计算机,也不知道去哪里学,没有方向,更没有一
本简单易懂并且有趣的入门书。计算机从被发明的那一天起,其使命就是帮助我们提高学习和工作
的效率并且改变世界。利用计算机编程,你可以轻松解决数学难题。例
如,□3×6528=3□×8256,在两个□内填入相同的数字使得等式成立。你
觉得这样的题目太简单了?那么来个稍微复杂点的:□□□+□□□=□□□,请将1~9这9个阿拉伯数字分别填入9个□中使等式成立,每个数字只能
使用一次。计算机可以轻轻松松地解决。如果再复杂一点,我想知道上
面这个式子的所有解,通过笔算就很困难了,但如果使用计算机编程去
解决,就易如反掌,这正是计算机所擅长的。有时你甚至可以利用计算
机编程去验证世界性的数学难题,例如,在10 000以内去验证哥德巴赫
猜想,也都不成问题。当解决大质数、图论等问题时,计算机编程也是
最好的帮手。
那么学计算机究竟是学什么呢?答案是逻辑思维和编程思维。
早在20世纪50年代,美国教育界就开始重视计算机编程教学。20世
纪80年代后,计算机编程教学逐渐进入中小学校,以教程序设计语言为
主,目的是提高学生的逻辑推理、批判性思维和动手解决问题的能力。
实践证明,学习了计算机编程的中小学生,思考问题的方式变得非常逻
辑化,学会了严密的逻辑推理方法,并无形中把它应用到其他学科的学
习中。学习计算机编程本质上是在学习一种思维方式——编程思维,它
是一种思维体操。青少年本身对计算机有着浓厚的兴趣并且有超强的记
忆力,计算机编程将有助于开发其学习潜力,提高逻辑推理能力和解决
问题的能力。
学习计算机编程的过程充满乐趣。如果你有一个想法,马上就可以
通过编程来实现,并且可以立即看到效果。这种即时的反馈,会让你的
学习兴趣变得越来越浓厚,也会让你越来越有信心。这种超强的信心,是你在其他学科中难以感受到的。我还记得我的第一个程序运行成功时的那种兴奋,真是太棒了,你一定要去感受一下,这是你一辈子都不会
忘记的感觉。
最后,用笔者一个武汉二中的学生吕凯风
[3]
学习编程时的感受来
结束本小节。
“记得我那时学编程全凭兴趣,兴趣引导我前进。以前做完了作业
打游戏,如今写完了作业就编程。我觉得学会编程后最让自己激动的
是,我能用编程来解决几乎所有遇到的数学问题。学数学最强调技巧
性,比如7的2000次方除以3的余数是多少?21 212 157是不是质数?你
也许可以用一些小技巧把这两个问题解决掉,但是当我们遇到更难的问
题时,往往无能为力。比如214 125 315的123 719 857次方除以12 125
987的余数是多少?2 147 483 647是不是质数?很多实际问题并不像数
学中那么理想和美好,许多数学结论,尽管被证明得很巧妙,式子简
洁,但是归根结底,如果它只解决了一个特殊问题,则不具有什么实用
价值。所以我更喜欢信息学,它告诉我如何去解决一个一般化的问题而
不是一个特殊的有技巧性的问题。编程最让我感慨的是它无与伦比的唯
一性与严谨性。”
说到这里你是不是有点心动了?第2节 本书是讲什么的,写给谁看的
在写本书之前,我反复问了自己几个问题:这本书是讲什么的?这
本书是写给谁看的?这本书和一般的编程入门书有什么区别?为什么要
写这本书?选用哪一门编程语言入门呢?
第一个问题:这本书是讲什么的?
这是一本编程入门书。但是本书的重点并不是编程入门,而是向你
展示逻辑思维和编程思维的魅力,让你像程序员一样思考。
第二个问题:这本书是写给谁看的?
编程类图书给大众的印象一直是枯燥并且难懂的。究竟什么样的人
才能学习编程呢?大学生?高中生?初中生?……不会连小学生都可以
吧?!没错,只要有小学四年级的水平,我想你一定可以学习编程,并
且轻松读懂本书的全部内容。
如果你的情况恰好符合以下一点或几点,那么本书正是为你所写
的。
(1)如果你想自己制作好玩的游戏,而不是沉迷于别人的游戏
中。
(2)如果你曾对数学感兴趣,我想你一定会喜欢这本书。其实学
习编程并不需要精通数学,本书不会出现很复杂的数学公式。即使数学
不太好,甚至很糟糕,也完全可以阅读。(3)如果你对逻辑感兴趣,你一定更会喜欢这本书。与计算机展
开的逻辑较量一定会让你觉得非常有意思。因为计算机有时会显得不那
么听话,你让它向东可它却偏偏向西,这时候就一定是你编写的程序出
现了逻辑问题。而将你的思维清晰有条理地变成计算机程序,就如同一
场你与计算机之间的逻辑对决。学习计算机编程能够很好地锻炼你的逻
辑思维能力。
(4)如果你从小喜欢拆装玩具、改装小电器或是喜欢变废为宝,我想计算机编程会给你带来更多的创造机会。
(5)如果你正在读《高中数学必修三》的“算法”一章,那么你一
定要阅读本书,去了解计算机编程和算法的本质。
(6)正在学习C语言的理工科或者文科的大学生们。
(7)准备学习编程的爱好者,或者准备以此为工作的人。
(8)哦,对了,还有就是看了很多编程书籍但是一直没有看懂的
人,我想你一定可以轻松读懂本书。
(9)没有那么多原因,就是喜欢计算机。
第三个问题:为什么要写这本书呢?
正如前面所说,计算机是一门科学,如果你只是把它当成上网、聊
天和玩游戏的工具,那就太可惜了,你将可能失去一个发现自己才能的
机会。即使在计算机编程上有一些天赋,你也有可能失去这一机会。和
其他人一样,你必须去主动发现自己的天赋和兴趣,就好比你从来没有
吃过冰淇淋,就不可能知道自己喜欢吃冰淇淋。然而,如果学习了计算
机编程,你就会发现计算机编程就如同玩游戏一样有趣,充满活力的思考过程就如同一场比赛令人兴奋。在感受到了计算机编程给你带来的乐
趣后,你就再也不会沉迷于计算机游戏,计算机编程将成为你生活中不
可缺少的一部分,成为你的一种爱好,成为你的一种学习动力。我想有
更多人期待去了解计算机编程。
最后一个问题:选用哪一门编程语言入门呢?
学习编程的重点在于学习编程的逻辑和思维。本书选用较为简单的
C语言。你可能要问为什么不选C++、C、Java或者Python之类。因为
我觉得相比之下C语言最为单纯,没有那么多乱七八糟的东西,非常简
洁。即使以C语言为载体,我也尽量做到重点去讲解最有用的内容,而
不是C语言的高深语法或者我至今都没有用过的“奇怪”语句。这样就有
更多的时间去思考如何解决问题,去关注编程的逻辑和思维。
当然,说到底C语言仅仅是我们与计算机沟通的一门语言而已,相
信你在阅读完本书之后,可以很轻松地上手任何一门语言,因为其本质
都是一样的。根据TIOBE index的程序语言年度排名,2012年最流行的
编程语言正是有着40年历史的C语言,它战胜了Java语言位居TIOBE
index榜首,这或许也能说明C语言的重要性吧。以C语言为根本,将帮
助你更好地去理解编程的思想,而不仅仅是学会编程。
另外我想告诉你,编程真的是一件非常有趣的事。你就像是一个指
挥官,让计算机毫无怨言地为你工作。通过编程,你将体会到战胜困难
和挑战后的快乐与满足。编程的世界充满无限的可能,只有想不到,没
有做不到。当然在编程的时候也会遇到很多问题,我在书中也为你设置
了绊脚石,希望你能够顺利地把它找出来。尽信书,不如无书。学习不
但要细致,还要有思辨的能力,这样才会有创新,才能总结并创造出自
己的东西。现在开始自己动手编程,不要放弃曾经的梦想,大胆地创造你的作品。
艾伦·凯曾经这样说道:“在自然科学中,是大自然给出一个世界,而我们去探索其中的法则。对于计算机来说,却是我们自己来构建法
则,创造一个世界。”
当下,我们的学习不应该再忙碌于重复的计算、记忆等技能。阅
读、逻辑推理和主动思考等技能将成为学习的重点。我们应该使用计算
机来增强自己的智能,同时发挥人类独有的创造天赋,让我们的思维插
上计算机的翅膀。
最后,我保证本书一定不是那种枯燥无味的编程入门书,并且在此
之前你一定没有读过如此生动好玩的编程入门书。你可以在茶余饭后阅
读本书,或许蹲在马桶上时也可以看得津津有味。现在就让我们一起走
进计算机编程的神奇世界,探索和发现计算机编程的魔力吧!
[1] 1985年如果乔布斯没有被迫离开苹果,那这一功劳可能将归于苹果的麦金塔计算机。
[2] 被誉为“小乔布斯”的12岁少年托马斯是美国加利福尼亚州洛杉矶市南湾地区
一所学校的6年级学生。当大多数孩子还处在玩计算机或手机游戏的时候,托
马斯就已经是个能开发游戏程序的“软件工程师”了。托马斯不但为苹果公司
的手机操作系统编写了两个游戏程序,还创办了一家软件开发公司。
[3] 吕凯风(VFK)在14岁时以初中生身份获得NOIP(提高组)一等奖,初三
时以全省第一名的成绩入选湖北NOIP省队,高一时获得亚洲太平洋地区信息
学奥林匹克竞赛(APIO2013)国际金牌,高二时获得NOIP全国第二名,现被
保送到清华大学“姚班”。此外,他还独立创作了“对对棋”和“啊哈图”软
件。“对对棋”的启发来源于他的班级同学在课间玩的一个游戏,“啊哈图”则
是他在学习计算几何和图论知识时,为了方便解题和调试做的一个类似于“几
何画板”的软件。第2章
梦想启航
第1节 编程的魔力
从一个神奇的数字说起——2 147 483 647。
2 147 483 647是一个质数(也称为素数,即只能被1和其本身整除
的数)。发现这个质数的人是伟大的数学家欧拉。1722年,他在双目失
明的情况下,以惊人的毅力靠心算证明了2 147 483 647是一个质数,堪
称当时已知的世界上最大的质数,他也因此获得了“数学英雄”的美名。
现在你通过计算机只需要1秒就可以证明2 147 483 647是一个质数。
再来看一个经典的问题——八皇后问题。
如何能够在8×8的国际象棋棋盘上放置8个“皇后”,使得任何一
个“皇后”都无法直接吃掉其他“皇后”?为了达到这个目的,任意两个“皇后”都不能处于同一条横行、纵行或斜线上。下面就是一种解决方
案。没错,你可以自己拿出笔和纸画一画,看看还有没有其他方案。但
是,如果我想知道所有的方案该怎么办?
又轮到计算机出马了,一共有92种不同的解决方案,很棒吧!计算
机只需要1秒,就可以算出所有的解。
再来看一个很流行的益智游戏——数独。
在一个9×9格的大九宫格中有9个3×3的小九宫格,默认在其中填写
了一些数字,现在请在其他空格上填入数字1~9。每个数字在每个小九
宫格内只能出现一次,每个数字在每行每列也只能出现一次。请看下面
这个例子。
我想,你一定很快就找到了一种可行解,可是你知道上面这个数独
一共有多少种不同解吗?答案是99 410种!很难想象吧,计算机找到这些解仍然只需1秒!怎么样,计算机编程是不是很神奇,你甚至可以轻
而易举地在一定范围内去验证“哥德巴赫猜想”。
在接下来的内容里,你将学会如何与计算机对话,如何让计算机进
行数学计算和判断,如何让计算机永不停止地工作,以及如何让计算机
做一些很有意思的程序和游戏。一场有趣的逻辑思维大战即将开始,不
要走开,赶快进入第2节——让计算机开口说话!第2节 让计算机开口说话
为什么会有计算机的出现呢?伟大的人类发明的每一样东西都是为
了帮助我们改善生活。计算机同样是用来帮助我们的工具。想一想,假
如你现在希望让计算机帮助你做一件事情,你首先需要做什么?是不是
要先与计算机进行沟通?那么沟通就需要依赖于一门语言。人与人的沟
通,可以用肢体语言、汉语、英语、法语和德语等。你若要与计算机沟
通,就需要使用计算机能够听懂的语言。我们学习的“C语言”便是计算
机语言的一种,计算机语言除了C语言外,还有C++、Java、C等。C语
言是一门比较简单的计算机语言,更加适合初学者。所有的计算机语言
都是相通的,如果你能够熟练掌握C语言,那么再学习其他语言就会变
得易如反掌。
既然计算机是人类制造出来的帮助人类的工具,显然让它开口说话
并把它所知道的东西告诉我们是非常重要的。
下面我们就来解决第一个问题:如何让计算机开口说话?
回想当年,我们刚刚来到这个世界的时候,说的第一句话是什么?
应该不会是“你好!”、“吃了没?”……这样会把你爸爸妈妈吓坏的!
伴随着“wa wa wa”的一阵哭声,我们来到了这个精彩的世界,现在
我们也让计算机来“哭一次”。这个地方特别说一下,计算机若要
把“它”想说的告诉我们,有两种方法:一种是显示在显示器屏幕上;另
一种是通过喇叭发出声音。就如同我们有话想说时,一种是写在纸上,另一种是用嘴巴说出来。目前让计算机用音箱输出声音还比较麻烦,因
此采用另外一种方法,即用屏幕输出“wa wa wa”。 printf(wa wa wa);
这里有一个生疏单词叫作printf,不要被它吓坏了,目前不用搞清
楚它的本质意义是什么,只要记住它和中文里面的“说”,以及英文里面
的“say”是一个意思即可,它就是控制计算机说话的一个单词而已。在
printf后面紧跟的( ),是不是很像一个嘴巴,把要说的内容“放在”这
个“嘴巴”里。这里还有一处需要注意,在wa wa wa的两边还有,里
面就是计算机需要“说”的内容,这一点是不是很像我们的汉语?最后,一句话结束时要有一个结束的符号。汉语中用句号表示一句话的结束;
英语中用点号表示一句话的结束;计算机语言中用分号表示一个语句的
结束。
注:计算机的每一句话,就是一个语句。
那么,现在如果让你写一个语句,让计算机说“ni hao”,该怎么
办?
printf(ni hao);现在我们让计算机来运行这个语句。这里需要说明一下,仅仅输入
printf(ni hao);,计算机是识别不了的,需要加一个框架。完整的程
序如下:
include
include
int main
{
printf(ni hao);
return 0;
}
这里的
include
include
int main
{
return 0;
}
是所有C语言都必须要有的框架,现在你暂时不需要理解它,知道要有这个即可,以后再来详细地讲它的用途。但是有一点,我们今后写的所
有类似printf的语句都要写在{ }里才有效。
接下来需要让计算机运行我们刚才写的程序。
如果让计算机运行我们写的东西(其实我们写的就是一个C语言程
序),需要一个特殊的软件,它叫作“C语言编译器”
[1]
, “C语言编译
器”有很多种,这里介绍一种比较简单的软件,叫作“啊哈C”
[2]。
首先你需要到www.ahalei.com页面中下载“啊哈C”。下面就要进入
安装步骤啦,安装很简单,一共分7步(见图2-1~图2-7),每一步我都
截取了图片,你只需一口气将这7幅图片全部看完应该就可以。
图2-1 安装“啊哈C”图2-2 开始安装“啊哈C”
图2-3 设置“啊哈C”安装目录图2-4 创建桌面图标和启动栏图标
图2-5 确认安装信息
图2-6 安装正在进行图2-7 “啊哈C”安装成功
“啊哈C”安装完毕后,便可以看到如图2-8所示的“啊哈C”的界面,同时在你的桌面上也会多一个“啊哈C”图标。
图2-8 “啊哈C”的界面
“啊哈C”是一个很人性化的软件,你将会发现“啊哈C”已经帮你将C
语言代码框架的部分写好了。只需要将
printf(ni hao);
这条语句在“啊哈C”中输入就好,如图2-9所示。图2-9 输入printf(ni hao)
细心的同学可能会发现,“啊哈C”默认的C语言框架,比之前说的C
语言框架多了一句话:
system(pause);
这句话是什么意思呢?稍后我们再揭晓。先将这句话删除,删除后
的界面如图2-10所示。
图2-10 删除system(pause)图2-12 编译成
功的提示
好了,同学们请注意,到了最后一步,需要让代码运行起来。现在
只需单击“啊哈C”上的“运行”按钮 。
接下来需要为所写的程序起一个名字,我为这个程序起的名字
是“nihao”,当然你可以随便起名,中英文都可以。比如你可以称之
为“abc”或“我的第一个程序”,或者叫“1”都行,但是你最好别写火星文
或者特殊字符,也不能有英文的点号。将程序的名字输入在如图2-11所
示的文本框中之后再单击“保存”按钮,接下来就是见证奇迹的时刻。
图2-11 给程序起个名字
如果代码没有写错,那你的“啊哈C”将会弹出一
个对话框,提示“恭喜你编译成功”,如图2-12所示。
请同学们注意,在输入代码的时候,一定不要用中
文输入法,这里所有的符号都是英文的,一般也都
是小写。
下面当然就单击“确定”按钮。接下来,请注意:注视你的计算机屏
幕,一秒也不要走开,数秒之后,你将会发现计算机的屏幕上有一
个“黑影”闪过,如果你没有发现这个“黑影”,请重新单击“运行”按钮,并再次注视你的计算机屏幕。
此时,你可能想问,为什么屏幕上会出现这个“黑影”?我们是要在
屏幕上显示“ni hao”才对啊。其实刚才那个“黑影”就是“ni hao”,只不过
计算机的运行速度太快了,在屏幕上显示之后,就立即消失了。那应该
怎么办呢?这需要让计算机暂停一下。
system(pause);
上面这句话就是之前所删除的,其实它的作用就是让计算机“暂停
一下”。将这句话放在printf(ni hao);后面,完整的代码如下:
include
include
int main
{
printf(ni hao);
system(pause);
return 0;
}
好了,再次单击“运行”按钮吧。如果代码没有错误,你将看到如图
2-13所示的界面。图2-13 运行成功的结果
“请按任意键继续…”是system(pause);输出的一个提示,此时
只需按键盘上的任意一个键,这个小黑窗口就会关闭。
如果想让“ni hao”分两行显示,则只需要将printf(ni hao);改为
printf(ni \n hao);这里的“\n”表示让光标“换行”。注意,这里的“\”向
右下角斜,它在键盘上的位置,通常是在回车键的上方。好,赶快尝试
一下吧。运行结果如图2-14所示。
include
include
int main
{
printf(ni\nhao);
system(pause);
return 0;
}
图2-14 分行后的运行结果
当然也可以让“请按任意键继续...”在下一行显示,只需将printf(ni\nhao);改为printf(ni \n hao\n);即可,去试一试吧。
一起来找茬
下面这段代码是让计算机在屏幕上输出hi。其中有3个错误,快来
改正吧!
include
include
int main( )
{
print(hi)
system(pause);
return 0;
}
更进一步,动手试一试
1.尝试让计算机显示下面这些图形。
2.如何让计算机说中文呢?让计算机像下面一样说“早上好”,应
该怎么办?
3.尝试让计算机显示下面这个图形。
A
BC
DEF GHIJ
KLMNO
PQRSTU
V
W
X
Y
Z
这一节,你学到了什么
如何让计算机开口说话,以及让计算机开口说话的语句是什么?第3节 多彩一点
在本章第2节中,我们学习了让计算机开口说话应使用printf语句。
可以发现,计算机“说”出的话都是黑底白字,其实计算机的输出可以是
彩色的,我们一起来看看吧。
注意,此处代码只能在Windows操作系统下编译运行。如果你使用
的是本书推荐的C语言的软件“啊哈C”,那么你的代码肯定可以运行成
功。下面来看看如何让颜色出现。
请尝试输入以下代码并运行,看看会发生什么。
include
include
int main
{
system(color 5); printf(wa wa wa);
system(pause);
return 0 ;
}
运行之后你发现了什么?底色仍然是黑色。但是,文字的颜色已经
变为“紫色”了,奥秘就在下面这行代码中。
system(color 5);
在这句话中,“5”代表“紫色”,你可以尝试一下其他数字,看看分
别是什么颜色。
既然字的颜色可以变,那么背景色是否可以变呢?尝试下面这段代
码:
include
include
int main
{
system(color f5);
printf(wa wa wa);
system(pause);
return 0; }
运行成功后的界面如图2-15所示。
图2-15 运行成功后的界面(此时背景应该为白色,文字颜色应该为紫
色)
上面这段代码在原来的5前面加了一个f,这里的f代表背景色是白
色。
那么设置背景色和文字颜色的方法是,在color后面加上两个一位数
字,第一个数字表示背景色,第二个数字表示文字颜色。如果在color后
面只加了一个一位数字,则表示只设置文字颜色,背景色仍然使用默认
的颜色。
需要说明的是这里的一位数字其实是16进制的,它只能是0、1、2、3、4、5、6、7、8、9、a、b、c、d、e、f中的某一个。
[题外话]“不看,也无伤大雅”
这里学习一个新知识——进制。
在现代数学中,我们通常使用十进制,即使用数字0、1、2、3、4、5、6、7、8、9。9之后的数字便无法表示了,我们的解决方法是:
使用“进位”来表示。例如,由于阿拉伯数字只到9,于是我们便进一
位,当前这位用0表示,便产生了用10来表示“十”。因为是“逢十进一”,所以称为十进制。
而十六进制是“逢十六进一”,即使用0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F来表示。0~9与在十进制时相同,但
是“十”在十六进制时用大写字母A表示,以此类推,“十五”在十六进制
中用大写字母F来表示。F是“十六进制”中的最后一个,因此数字“十
六”就表示不了。于是我们又采用刚才在十进制中表示不了就进一位的
老办法,当前应该用0表示。“十六”在十六进制中表示为10。同理,“二
十七”在十六进制中表示为1B。
在中国古代,很多朝代都是用十六进制作为日常计数的,例如,成
语“半斤八两”的典故来源于十六进制;还有中国古代的算法是上面2颗
珠子,下面5颗珠子。若上面每颗珠子代表数字5,下面每颗珠子代表数
字1,那么每位的最大计数值是15, 15正是十六进制的最大基数。当使用
算盘计数遇到大于15的时候,我们就需要在算盘上“进位”了。
其实在我们现代的日常生活中,也不都是“十进制”,例如,60秒为
1分钟,60分钟为1小时,就是用的六十进制。
一起来找茬
下面这段代码是让计算机在屏幕上输出绿底白字的hi。其中有4个
错误,快来改正吧!
include
include
int main( )
{ system(color f2)
print(hi);
system(pause);
return 0;
}
更进一步,动手试一试
1.尝试让计算机打印这个小飞机图案(绿底白字)。
2.尝试让计算机打印这个小队旗图案(白底红字)。
A
I I
I
I
I
I
I
I
I
这一节,你学到了什么
让计算机打印出来的字符有不同颜色的语句是什么?第4节 让计算机做加法
通过之前的学习,我们了解到让计算机说话是用“printf”,运
用“printf”就可以让计算机想说什么就说什么了。在学会了“说话”之后,我们来看如何让计算机做数学运算,首先我们先让计算机做“加法”,就
先算1+2吧。
回想一下小时候爸爸妈妈是如何教我们算1+2的呢?
妈妈说:“左手给你一个苹果,右手给你两个苹果,现在一共有几
个苹果?”我们迅速地思考了一下,脱口而出:“3个苹果”。没错!我们
首先用大脑记住左手有几个苹果,再用大脑记住右手有几个苹果,妈妈
问一共有几个时,我们的大脑进行了非常快速的计算,将刚才记住的两
个数进行相加,得到结果,最后将计算出的结果说出来。仔细分析一
下,大致分为以下5个步骤。
(1)用大脑记住左手的苹果数量;
(2)用大脑记住右手的苹果数量;
(3)我们的大脑将两个数字进行相加;
(4)得到结果;
(5)将结果输出。
在这期间,我们大脑一共进行了以下4个动作。
(1)两次输入:分别是记录左手和右手中苹果的数量;(2)存储了3个值:分别是记录左手和右手中苹果的数量和相加的
结果;
(3)进行了一次计算:相加;
(4)进行了一次输出:把相加的结果输出。
如何让计算机做加法呢?同样也需要以上几个步骤。
首先来解决如何让计算机像我们的大脑一样记住一个数字。
其实计算机的大脑就像一个“摩天大厦”,有很多一间一间的“小房
子”,计算机就把需要记住的数放在“小房子”里面,一个“小房子”里只
能放一个数,这样计算机就可以记住很多数。好,我们来看一看,具体
怎样操作。
“=”赋值符号的作用就相当于一只手,把数字放到小房子中。
int a, b, c;这句话就代表在计算机的“摩天大厦”中申请三间分别叫作a、b和c
的小房子(注意:int和a之间有一个空格,a、b与c之间分别用逗号隔
开,末尾有一个分号表示结束)。
接下来,我们让小房子a和小房子b分别去记录两个数字1和2,具体
如下:
a=1;
b=2;
说明:此处有一个“=”,这可不是等于号,它叫作给予号(也称为
赋值号),类似于一个箭头“←”,意思是把“=”右边的内容赋给“=”左
边。例如,把1这个数给小房子a,这样一来计算机就知道小房子a里面
存储的是数字1了。
然后,把小房子a和小房子b里面的数相加,再将其结果放到小房子
c中。
c=a+b;
计算机会将这个式子分两步执行:第一步先将a+b算出来,第二步
再将a+b的值赋给“=”右边的c。至此,就差不多完成了,我们总结一下:
int a, b, c;
a=1;
b=2;
c=a+b;
很多同学是不是以为,现在已经全部完成了?你忘记了最重要的一
步,先别急着往下看,想一想忘记了什么?
啊!你忘记了把答案输出。
想一想如果妈妈问你一加二等于多少时,你说:“我算出来了,但
是不想告诉你!”的话,估计少不了挨一顿揍了,不要啊!
让我们回忆一下,如何让计算机把结果输出。
对,使用printf语句。那怎么把小房子c里面存储的数输出呢?根据
本章第2节学到的知识,只要把要输出的内容放在双引号里面就可以
了,代码如下:
printf(c);
猜一猜此时计算机会输出什么?对,无情地输出了一个c。
那怎样输出c里面的值呢?
这时我们要让另外一个角色出场了。
%d
“%d”其实是一个“讨债的”,或者也可以说是“要饭的”。它的专职工
作就是向别人“要钱”!那我们应该怎么使用它呢?
printf(%d, c);将“%d”放在双引号之间,把小房子c放在双引号后面,并且用逗号
隔开。
这时printf发现双引号里面是个“讨债的”,就知道此时需要输出一个
具体的数值,而不是符号,就会向双引号后面的小房子c索取具体的数
值了。
好了,最后加上C语言的代码框架,计算机进行加法运算的完整代
码如下:
include
include
int main
{
int a, b, c;
a=1;
b=2;
c=a+b;
printf(%d, c);
system(pause);
return 0;
}
现在赶紧去试一试吧。
一起来找茬下面这段代码是让计算机计算321-123的结果。其中有7个错误,快
来改正吧!
include
include
int mian( )
{
int a, b, c;
a=321
b=123
c=b-a
print(%d, c)
system(pause);
return 0;
}
更进一步,动手试一试
1.如果要进行3个数相加的运算,该怎样做呢?例如:5+3+1=?
我们可以把上面的程序进行简单地改变,申请4个小房子分别叫作
a、b、c和d。用a、b、c分别存放3个加数,用d存放它们的和。代码如
下:
include include
int main
{
int a, b, c, d;
a=5;
b=3;
c=1;
d=a+b+c;
printf(%d, d);
system(pause);
return 0;
}
如果要10个数相加岂不是得定义11个小房子?那也太麻烦了!对,目前我们只能这样,但是在后面的学习中,会有更为简单的方法。
2.用计算机算出下面3个算式。
123456789+43214321
70788712
321(123456+54321)
这一节,你学到了什么1.如何申请一个小房子来存储数值?
2.如何用printf输出小房子中的数值?第5节 数字的家——变量
从本章第4节中,我们了解到计算机使用一个个的小房子来记住数
字。计算机有很多不同种类的小房子。
int a;
代表向计算机申请一个小房子,用来存放数值,小房子的名字叫作a。
int和a之间有一个空格,a的末尾有一个分号,表示这句话结束。
如果要申请多个小房子,则要在a后面继续加上b和c,用逗号分
开。例如:
int a, b, c;
这里有一个小问题,就是给申请的“小房子”起名字。原则上可以随
便起:可以是单独的字母,如a、b或x;可以是多个字母的组合,如
aaa、abc或book;也可以是字母和数字的组合,如a1或abc123。当然也
有一些限制,如果你想知道,请看附录A。到这里,可能还有很多同学想问,int究竟是什么意思呢?
其实,int控制小房子用来存放的数的类型,表示你目前申请的小房
子只能存放整数。
int是英文单词integer(整数)的缩写。
如果要放小数该怎么办?
我们用float来申请一个小房子,用来存放小数,形式如下:
float a;
这样,小房子a就可以用来存放小数了,例如: float a;
a=1.5;
printf(%f, a);
就表示申请一个用来存放小数的小房子a,里面存放了小数1.5。
注意:在C语言中,小数称作浮点数,用float表示。
之前在用printf语句输出整数时,使用的是“%d”。此时需要输出小
数,要用“%f”。
好了,我们来总结一下,这里的“小房子”在我们C语言的专业术语
中称为变量。int和float说明小房子是用来存放何种类型的数,我们这里
将其称为“变量类型”或者“数据类型”。
类似int a;或者float a;的形式,我们称作“定义变量”,它们的语法
格式如下:
【口语】 小房子的类型 小房子的名称 , 小房子的名称 ;
【术语】 变量的类型 变量的名称 , 变量的名称 ;
【代码】 int a , b ;
现在我们知道,int a;表示申请一个用来存放一个整数的小房子a,即定义一个整型变量a来存放整数;而float a;则表示申请一个用来存放
一个小数的小房子a,即定义一个浮点型(实型)变量a来存放浮点数(小数)。
再来看另外一个有趣的问题,代码如下:
include
include
int main
{
int a;
a=1;
a=2;
printf(%d, a);
system(pause);
return 0;
}
请问计算机执行完上面的代码后,将会输出1还是2?尝试过后你会发现,计算机显示的是2,也就是说小房子a中的值最
终为2。通过观察代码可以发现,我们首先将1放入小房子a中,紧接着
又将2放入小房子a中,那么请问原来小房子中的1去哪里了呢?答案
是,被新来的2给覆盖了并且已经消失了。也就是说,小房子a中有且仅
能存放一个值,如果多次给小房子a赋值,小房子a中存放的将始终是最
后一次赋的值。例如:
include
include
int main
{
int a;
a=1;
a=2;
a=3; a=4;
a=5;
a=6;
printf(%d, a);
system(pause);
return 0;
}
计算机运行完上面这段代码后最终将输出6。也就是说小房子a中的
值最终为6,前5次的赋值全部被覆盖了。
一个更有意思的问题来了,请继续看下面的代码:
include
include
int main
{
int a;
a=7;
a=a+1;
printf(%d, a);
system(pause);
return 0; }
计算机运行完上面这段代码后最终将输出8。也就是说小房子a中的
值最终为8。计算机在执行完a=7这句话后,小房子a中存储的值为7,之
后计算机又紧接着运行了a=a+1。运行完a=a+1后,小房子a中的值就变
为8了。也就是说a=a+1的作用是把小房子a中的值在原来的基础上增加
1,我们来分析一下这句话。
对于a=a+1计算机分两步执行,这句话中有两个操作符,第一个
是“+”,另一个是“=”(赋值号),因为“+”的优先级要比“=”高,因此计
算机先执行a+1,此时小房子a中的值仍然为7,所以a+1的值为8。紧接
着计算机就会执行赋值语句,将计算出来的值8再赋值给a,此时a的值
就更新为8。
好啦,猜猜下面的程序,计算机最终会输出多少?
include
include
int main
{ int a;
a=10;
a=aa;
printf(%d, a);
system(pause);
return 0;
}
尝试过了吗?想一想为什么a最终的值为100。
注:所有运算符的优先级详见附录B。
一起来找茬
下面这段代码是让计算机计算1.2×1.5的值。其中有5个错误,快来
改正吧!
include
include
int main( )
{
int a, b, c
a=1.2;
b=1.5;
c=ab; print(%d, c)
system(pause);
return 0;
}
更进一步,动手试一试
1.进行两个小数的加法运算,例如:5.2+3.1=?代码如下:
include
include
int main
{
float a, b, c;
a=5.2;
b=3.1;
c=a+b;
printf(%f, c);
system(pause);
return 0;
}
请注意,之前在printf语句中输出整型变量的值时,使用的
是“%d”,此时需要输出的是实型变量的值,因此要用“%f”。2.通过计算机把下面3个式子算出来吧!
1.2+2.3+3.4+4.5
1.1100
10.1(1010)
这一节,你学到了什么
1.如何定义一个用来存放小数的变量?
2.如何让一个小房子a(变量a)中的值增加1?第6节 数据输出——我说咋地就咋地
在本章第4节中,我们已经学会了如何让计算机做加法运算,但是
计算机在输出的时候,只显示了一个结果,这样不够人性化。如果能将
整个算术等式输出就好了,例如:1+2=3。那应该怎么写呢?
新的代码:
include
include
int main
{
int a, b, c;
a=1;
b=2;
c=a+b;
printf(%d+%d=%d, a, b, c);
system(pause);
return 0;
}
原来的代码: include
include
int main
{
int a, b, c;
a=1;
b=2;
c=a+b;
printf(%d, c);
system(pause);
return 0;
}
仔细阅读这些代码你会发现,新的代码和原来的代码只有一个
printf语句不一样。好,我们现在来仔细分析一下printf(%d+%d=%d,a, b, c);。
printf语句只会输出双引号里面的部分,双引号之外的部分只是对
双引号内的部分起到补充说明的作用。
例如,printf(%d+%d=%d, a, b, c);这行语句,双引号里面的部
分是%d+%d=%d,那么计算机在输出的时候就严格按照%d+%d=%d来
执行,输出的形式必然是%d+%d=%d。
当计算机遇到第1个“%d”时,知道“讨债的”来了,于是它便向双引
号后面的变量讨债,排在第1个的是a,那么就向a讨债。a的值是1,于是第1个“%d”得到的便是1。
第2个是“+”,那么照样输出。
第3个又是“%d”,同样到双引号的后面去讨债,因为排在第1个的a
已经被讨过债了,因此向排在第2个的b讨债。b的值是2,于是这
个“%d”得到的便是2。
第4个是“=”,照样输出。
第5个还是“%d”,同样到双引号的后面去讨债,因为排在第1个的a
和排在第2个的b已经被讨过债了,因此向排在第3个的c讨债。c的值是
3,于是最后这个“%d”得到的便是3。
最后输出的内容是1+2=3。
请注意,通常双引号内部“%d”的个数,和后面变量的个数是相等
的,它们是一一对应的。如果没有一一对应,从C语言的语法角度来讲
是没有错误的,但这不合常理,最好避免这样的情况出现。
一起来找茬
下面这段代码是让计算机分别计算10-5与10+5的值,并分两行显
示,第一行显示差,第二行显示和。其中有3个错误,快来改正吧!
inlcude
include
int mian( )
{ int a, b, c;
a=10;
b=5;
c=a-b;
printf(%dn, c);
c=a+b;
printf(%d, c);
system(pause);
return 0;
}
更进一步,动手试一试
指定两个数,输出这两个数的和、差、积与商。例如,指定两个数
9和3,输出9+3=12、9-3=6、9×3=27、93=3。
include
include
int main
{
int a, b, c;
a=9;
b=3;
c=a+b;
printf(%d+%d=%d\n, a, b, c); c=a-b;
printf(%d-%d=%d\n, a, b, c);
c=ab;
printf(%d%d=%d\n, a, b, c);
c=ab;
printf(%d%d=%d\n, a, b, c);
system(pause);
return 0;
}第7节 数据输入——我说算啥就算啥
我们已经学会了如何做一个加法计算器,但是目前的加法计算器还
不够人性化,每次计算两个数的和时,都需要修改C语言代码,然后重
新编译运行才能得到结果,很显然这样的加法计算器是不会有人喜欢用
的,那如何让使用者自己任意输入两个数就可以直接得到结果呢?
我们知道,让计算机说话用printf,那么让计算机学会听用什么
呢?scanf将会把听到的内容告诉你的程序。
计算机“说话”的过程,我们称为“输出”,计算机“听”的过程,我们
则称为“读入”。好,下面来看看,计算机是如何读入的。
scanf的语法与printf语法类似,例如,我们要从键盘读入一个数,放在小房子a中,代码如下:
scanf(%d, a);
你瞧,与输出小房子a的语句printf(%d, a);是差不多的,只有
以下两处不同。
第一处是:读入是使用scanf这个词,而输出是使用printf这个词。
第二处是:读入比输出在a前面多了一个“”符号。
“”符号我们称为“取地址符”,简称“取址符”。它的作用是得到小房子a的地址。
scanf(%d, a);这句话可以理解为:我们要从外界向计算机的
内部传送一个数值,并需要将这个值存放到指定的“编号为a”的盒子
中。这样我们就需要知道小盒子a在计算机内部的地址。就像邮递员送
信一样,要传送的数据就是信件,小盒子a就是信箱编号。
那你可能要问,为什么在读入的时候要得到小房子a的地址,而输
出的时候却不需要呢?在读入数据的时候,计算机需要把读入的值存放
在小房子a(也就是变量a)中,此时需要知道你指定的这个小房子a的
地址,才能把值准确地放进其中;但是在输出的时候,值已经在小房子
a中了,因此可以直接输出到屏幕上。
打一个比方:假如你要去一个教室上课,那么在上课之前你需要知
道这个教室的地址,这样你才能去;但是如果下课了,你需要走出这个
教室,因为此时你已经在教室中,所以就不再需要这个教室的地址。
如果要从键盘读入两个数,分别给小房子a和小房子b呢?这里有以
下两种写法。第一种:
scanf(%d, a);
scanf(%d, b);
第二种:
scanf(%d%d, a, b);
第二种的写法较为简便,两个“%d”之间不需要空
格,“a”和“b”之间用逗号隔开。
从键盘读入两个数,输出这两个数的和的完整代码如下:
include
include
int main
{
int a, b, c;
scanf(%d%d, a, b);
c=a+b;
printf(%d+%d=%d, a, b, c); system(pause);
return 0;
}
好了,总结一下,在C语言中printf是计算机“说出去的”,也就是计
算机需要告诉你的;而scanf是计算机“听进来的”,也就是你需要告诉计
算机的。
接下来,我们要让“加法计算器”更加人性化——带有提示的读入和
输出。
include
include
int main
{
int a, b, c;
printf(这是一个加法计算器,欢迎您使用\n);
printf(--------------------------------\n);
printf(请输入第一个数(输入完毕后请按回车)\n);
scanf(%d, a);
printf(请输入第二个数(输入完毕后请按回车)\n);
scanf(%d, b);
c=a+b;
printf(它们的和是%d, c); system(pause);
return 0;
}
一起来找茬
下面这段代码是从键盘读入两个整数,并输出它们的和。其中有6
个错误,快来改正吧!
include
include
int main( )
{
int a, b, c;
scanf(%d, a, b)
c=a+b
printf(%dn, c);
system(pause);
return 0;
}
更进一步,动手试一试
从键盘读入两个数,并输出这个两个数的和、差、积与商。 include
include
int main
{
int a, b, c;
scanf(%d%d, a, b);
c=a+b;
printf(%d+%d=%d\n, a, b, c);
c=a-b;
printf(%d-%d=%d\n, a, b, c);
c=ab;
printf(%d%d=%d\n, a, b, c);
c=ab;
printf(%d%d=%d\n, a, b, c);
system(pause);
return 0;
}
请注意除法运算。在C语言中,当除号“”左右两边都是整数时,商
也只有整数部分。例如,53的商是1,23的商是0。
这一节,你学到了什么
如何从键盘读入一个数到小房子中?第8节 究竟有多少种小房子
在之前的几节中,我们已经知道计算机如果想“记住”某个值,就必
须在它的大脑“摩天大厦”中,申请一种小房子。例如:
int a, b, c ;
即申请3种小房子分别叫作a、b和c。这3种小房子只能用来存放整数
(整型数据)。
再例如:
float a, b, c ;
即申请3种小房子a、b和c。这三种小房子只能用来存放小数(浮点型数
据)。
也就是说在计算机中,不同类型的数据需要相应类型的小房子来存
储。那么计算机一共有多少种类型的小房子呢?我们来列举几种最常用
的,如表2-1所示。
表2-1 C语言常用的数据类型
数据类型名称 用来存放哪种数据 数据范围
int 用来存放整数 ?2147483648~
2147483647
float 用来存放浮点数 ±1.18×10?38 ~
±3.4×1038
double
用来存放极大和极小
的浮点数
±2.23×10?308 ~
±1.80×10308
char 用来存放字符 256种字符
double也是用来存放小数的,那float和double有什么区别呢?
请观察下面两段代码。
代码1:
include
include int main
{
float a;
a=3.1415926535897932;
printf(%.15f, a);
system(pause);
return 0;
}
代码2:
include
include
int main
{
double a;
a=3.1415926535897932;
printf(%.15f, a);
system(pause);
return 0;
}通过观察,我们发现代码1和代码2的不同之处只有一点。代码1中
是用float来申请小房子a,代码2中却是用double来申请小房子a。在输出
时,两段代码中printf里面所用的占位符都是“%f”。代码中“%”和“f”之
间的“.15”表示保留小数点后15位(四舍五入)。这里特别说明一下,在
用scanf读入double类型数据时所用的占位符是“%lf”(注意此处不是数字
1而是字母l)而不是“%f”。
它们的运行结果分别如图2-16和图2-17所示。
图2-16 代码1运行的结果
图2-17 代码2运行的结果
怎么样,发现问题了吧?!代码1运行后输出的是
3.141592741012573,显然从小数点后第7位开始就不对了,而代码2运
行后输出的是3.141592653589793,完全正确。因此我们可以发现double
可以比float表示得更精确。另外float和double表示的数的大小范围也不
同,请大家自己去尝试。
在表2-1中我们发现有一个新的数据类型char,用char申请的小房子
是用来存放字符的。 include
include
int main
{
char a;
scanf(%c, a);
printf(你刚才输入的字符是%c, a);
system(pause);
return 0;
}
我们输入一个字符x后按回车键,结果如图2-18所示,当然你也可
以尝试一下别的字符。
图2-18 输入一个字符并输出
想一想,对于上面这段代码,如果此时你输入的不是一个字母,而是一串字母,计算机会输出什么呢?很抱歉!计算机只会输出你输入的
第一个字母。
有的同学可能要问,如果想存储一大串字符该怎么办呢?不要着
急,我们将在后续章节中介绍如何存储一个字符串。
一起来找茬
下面这段代码是让计算机读入一个字符并把这个字符原样输出。其
中有3个错误,快来改正吧!
include
include
int main( )
{
char a;
scanf(%c, c);
printf(%d, c);
system(pause);
return 0;
}
更进一步,动手试一试
从键盘读入一个字符,输出这个字符后面的一个字符。例如,输入
字符a,输出字符b。 include
include
int main
{
char a;
scanf(%c, a);
printf(后面的一个字符是%c, a+1);
system(pause);
return 0;
}
思考一下,为什么一个字符后面的字符就是该字符加1呢?
这一节,你学到了什么
1.double是什么类型?
2.如何存储一个字符?第9节 拨开云雾见月明
通过前面的学习,我们已经知道计算机如果想“记住”某个值,就必
须在计算机的大脑“摩天大厦”中,申请一个小房子。例如,之前我们需
要计算任意两个数的和,程序是这样写的:
include
include
int main
{
int a, b, c;
scanf(%d%d, a, b) ;
c=a+b;
printf(%d+%d=%d, a, b, c);
system(pause);
return 0;
}
其实这个小房子c是多余的,可以直接写成:
printf(%d+%d=%d, a, b, a+b);代码如下:
include
include
int main
{
int a, b;
scanf(%d%d, a, b);
printf(%d+%d=%d, a, b, a+b);
system(pause);
return 0;
}
当然,如果你只想计算4+5的值,可以更简单:
include
include
int main
{
printf(%d,4+5);
system(pause);
return 0;
}如果希望计算4+(6-3)×7的值,可以直接这样写:
include
include
int main
{
printf(%d,4+(6-3)7);
system(pause);
return 0;
}第10节 逻辑挑战1:交换小房子中的数
假如在计算机中我们已经有两个小房子(变量)分别叫作a和b,并
且它们都已经有了一个初始值,但是现在希望将变量a和变量b中的值交
换,该怎么办呢?
先来看一段代码:
include
include
int main
{
int a, b;
scanf(%d%d, a, b);
printf(%d %d, a, b);
system(pause);
return 0;
}
上面这段代码是从键盘读入两个数,然后将这两个数输出。例如,如果你输入的是5和6,那么输出的也是5和6。可是,我们现在的需求是
将变量a和b中的数交换后输出,也就是说如果读入的是5和6,那么输出
的应该是6和5才对。应该怎么办呢?来看一段代码: include
include
int main
{
int a, b;
scanf(%d%d, a, b);
a=b;
b=a;
printf(%d %d, a, b);
system(pause);
return 0;
}
上面的代码企图通过a=b; b=a;语句将变量a和变量b中的值交换,如果你已经运行过上面的代码,就会发现交换并没有成功,变量b的值
没有变化,反而是变量a的值变成了变量b的值,这是为什么呢?
我们来模拟一下计算机运行的过程。
int a, b;指计算机会申请两个小房子(变量),分别叫作a和b。
scanf(%d%d, a, b);指从键盘读入两个数,分别赋值给变量
a和变量b。假如我们从键盘读入的两个数分别是5和6,那么变量a中的
值就是5,变量b中的值就是6。a=b;指计算机会将变量b中的值给变量a,变量a中的值也变成了
6。变量a中原来的5被新来的6给覆盖了,也就是说原来变量a中的5丢失
了。
b=a;指计算机会将此时变量a中的值给变量b,此时变量a中的已经
是6了,所以变量b的值其实还是6。
最终,变量a和变量b中的值都为6。那我们要怎么改呢?通过上面
我们对计算执行过程的模拟,我们发现,主要问题是:计算机在执行完
a=b;这个语句后,原先变量a中的值被弄丢失了。那我们只要在执行
a=b;这个语句之前,先将变量a的值保存在另外一个临时变量中就可以
了,例如,保存在变量t中。代码如下:
t=a;
a=b;
b=t;
先将变量a中的值给变量t,变量t中的值就变为5(假如原来变量a中是5,变量b中是6),然后再将变量b中的值给变量a,变量a中的值就变
为6,最后将变量t中的值给变量b,此时变量b中的值就变为5。成功!
通过一个变量t作为中转站,我们已经成功地将变量a和变量b中的值进
行了交换。
完整的代码如下:
include
include
int main
{
int a, b, t;
scanf(%d%d, a, b); t=a;
a=b;
b=t;
printf(%d %d, a, b);
system(pause);
return 0;
}
一起来找茬
下面这段代码是让计算机读入两个整数,分别放到变量a和变量b
中,并将变量a和变量b中的数交换。其中有两个错误,快来改正吧!
include
include
int main( )
{
int a, b;
scanf(%d%d, a, b);
t=a;
b=a;
b=t;
printf(%d %d, a, b);
system(pause); return 0;
}
更进一步,动手试一试
在本节我们介绍了如何将两个变量的值进行交换,方法是增加一个
临时变量来作为中转。你有没有想过,在不增加任何新变量的情况下是
否也可以完成呢?来看看下面的代码吧。
include
include
int main
{
int a, b;
scanf(%d%d, a, b);
a=b-a;
b=b-a;
a=b+a;
printf(%d %d, a, b);
system(pause);
return 0;
}
请思考一下,为什么通过a=b-a; b=b-a; a=b+a;也可以将变量a与变量b中的值交换呢?第11节 天啊!这怎么能看懂
先来看一段代码:
include include int main{ i
nt a, b, c;
scanf(%d%d, a, b); c=a+b; printf(%d, c); system(pause); return 0; }
怎么样,你看懂了吗?这段代码的意思其实就是从键盘读入两个整
数并且输出它们的和。不错,上面的这段代码从语法角度来讲没有任何
错误,编译器也可以对其编译运行,也就是说计算机可以准确无误
地“认识”这段代码,但是我们会看得比较吃力。一段优秀的代码,不仅
仅要让计算机“看懂”,也要让我们可以看懂。再来看看下面这段代码是
不是更容易让人们理解呢。
include
include
int main
{
int a, b, c;
scanf(%d%d, a, b);
c=a+b; printf(%d, c);
system(pause);
return 0;
}
这里需要指出的是,这里的int a, b, c;前面与上一行相比,多了4个
空格。其实我在输入代码的时候,并不是输入4个空格,而是输入了一
个Tab
[3]。使用Tab来调整你的代码格式,是一名优秀的程序员必须要
养成的习惯。
include
include
int main
{
int a;
a=1; 将变量a赋初始值
printf(%d, a);
system(pause);
return 0;
}
在上面的代码中,“”表示注释,它将告诉编译器从“”开始一直到
本行末尾的内容都是没有用的。注释的主要作用是给程序员看的,通常用来对一行代码进行解释说明或备注。
include
include
int main
{
int a;
a=1; 将变量a赋初始值
printf(%d, a);
system(pause);
return 0;
}
上面的代码有两处注释,第1处注释我们讲过,主要是用来解释说
明本行代码的作用。第2处的注释是将本来有用的代码printf(%d,a);给注释掉,可以理解为“临时性删除”,就是告诉编译器
printf(%d, a);没有用。你可能要问为什么不直接删除呢?因为有
时我们并不希望真正删除,只是暂时不需要,以后说不定还要再用,如
果删除了就找不回来了,如果我们合理地利用“”进行注释,那么计算
机就不会运行这句话,而是理解这句话是给程序员看的。如果我们以后
又要使用这句话,只需将这句话前面的“”去掉就可以了,这样是不是
很方便呢。
有效地在代码中添加注释,可以让你的程序更具可读性。
“”只能注释到本行末尾,如果要注释多行,就要在每行上写“”。其实注释还有另外一种,以“”开始一直到“”结束,中间的内容编译
器都不会理睬。使用“ ”的好处就是它可以跨行。
例如,下面两段代码的效果是相同的:
include
include
int main
{
int a;
a=1;
a=2;
a=3;
a=4;
a=5;
printf(%d, a);
system(pause);
return 0;
}
include
include
int main
{
int a; a=1;
a=2;
a=3;
a=4;
a=5;
printf(%d, a);
system(pause);
return 0;
}
上面两段代码中变量a的值最后还是1。
再来看一段代码:
int a;
a=1;
上面这段代码是定义一个整型变量(小房子)a,并且给变量a赋一
个初始值1。我们以后会经常遇到在定义一个变量(小房子)之后,给
其赋初始值的情况,可以简写如下:
int a=1;多个变量也类似:
int a=1, b=2, c=3;
浮点型和字符型也类似:
float a=1.1;
char c='x';
需要注意的是,在给浮点型变量赋初始值的时候必须是一个小数,也就是说必须有小数点。在给字符型变量赋初始值的时候,字符两边需
要加单引号,记住是单引号,不是双引号。在上面的代码中我们希望把
字符x赋值给字符变量c,所以我们在字符x的左右两边加上了单引号。
编程也是一门艺术,需要追求简洁、高效而且优美的代码,一名优
秀的程序员往往也是一名艺术家。
[1] “C语言编译器”的作用是把我们写的程序“变”成一个“exe”,即可以让计算机
直接运行的程序。这个“变”的专业术语称为“编译”。当你的程序“变”成一
个“exe”后,你就可以脱离“C语言编译器”直接运行你的程序。此时你就可以
把你写的“exe”发给你的朋友和同学,让他们一起来使用你编写的程序。这里
的程序从某种意义上来讲也可以称为“软件”。[2] “啊哈C”是一款非常容易上手的C语言编程软件,使用的是GCC内核。界面
简洁可爱,支持语法高亮、代码折叠、编译错误提示等。操作方便,上手
快,特别适合C语言入门的初学者使用。
[3] Tab表示一个制表符,在编程中用Tab来代替空格是一个很好的习惯,可以让
你的代码看起来更美。Tab键在字母Q键的左边,赶快试一试吧。第3章
较量才刚刚开始
第1节 大于、小于还是相等
和我们一样,计算机也可以判断大小。假如你告诉计算机有a和b两
个数,计算机除了可以告诉你这两个数的和、差、积和商,还可以告诉
你谁大、谁小。现在我们就来瞧瞧计算机是如何判断谁大谁小的。
在此之前,我们需要先说明一下在计算机中用来判断两个数的关系
的符号,即关系运算符,一共有如下6个:
== 相等
> 大于
< 小于 >= 大于等于
<= 小于等于!= 不等于
需要特别注意的是,在计算机中,一个等于号“=”表示赋值,两个
等于号“==”表示判断是否相等,同学们在编写代码的时候千万不要写
错。一个感叹号加一个等于号“!=”表示“不等于”。此外计算机只有大于
等于号“>=”和小于等于号“<=”,没有等于大于号和等于小于号,即不存
在“=>”和“=<”,这一点请一定要注意。
例如,以下写法是正确的:
5>=4
7! =8
a
c==d
以下写法是错误的:
4=<7
8=>3第2节 判断正数
假如你现在想让计算机判断一个整数是否为正数,如果是则显示
yes,不是则什么都不显示,应该怎么办呢?
下面方框中的内容,就是让计算机判断一个数是否为正数的“算
法”。
首先,计算机需要有一个小房子(即变量)来存储这个数。
然后,你需要告诉计算机这个数是什么?
接下来,计算机需要判断这个数是否为正数。
最后输出计算机的判断结果。
算法其实就是解决问题的方法(千万要被这个专业名词给吓住
了)。
我们每遇到一个问题,首先需要思考的是解决这个问题的算法,也
就是解决这个问题的方法和步骤。像上面一样一步一步地列出来,然后
再将算法的每一步通过C语言来实现。
下面,我们就用C语言来实现上面的算法。
首先,计算机需要有一个小房子(即变量)来存储这个数。可以用int a;来申请一个名字叫作a的小房子(即变量),来存
储需要判断的数。
然后,需要告诉计算机这个数是什么?
可以用scanf(%d, a);来读入一个数并将这个数存储在小房
子a中。
接下来,计算机需要判断这个数是否为正数。
这可怎么办?不要紧,待会儿再来分析。
最后输出计算机的判断结果。
如果是正数则显示yes,使用printf(yes);。
好,现在我们集中精力来解决刚才的第3步——判断存放在小房子a
中的数是否为正数。
想一想,我们是如何判断一个数是否为正数的?要从正数的定义出发,如果一个数大于0,就是正数。好,计算机也是这么想的,哈哈。
如果a大于0,则显示yes。
接下来,尝试用C语言来实现。
其中“如果”在C语言中用if来表示。代码如下:
if (a>0) { printf(yes); }
因为当a>0成立时候,这里只需要执行一条语句,此时{ }也可以省
略不写,如下:
if (a>0) printf(yes);
要注意的是,当且仅当条件成立时 只需要执行一条语句 ? ? ? ? ? ? ? ? ?
才能省略{
}。 为什么这么说?不要着急,等你看完本章的第七节就知道了。
当然,如果你觉得写在同一行很不爽,写成两行也是可以的:
if (a>0)
printf(yes);更好的写法应该是在printf(yes);前面空4个空格或者空1个
Tab,表示printf(yes);是if (a>0)的一部分,当a>0条件成立时才
执行printf(yes);这条语句。
if (a>0)
printf(yes);
完整的代码如下:
include
include
int main( )
{
int a;
scanf(%d, a); if (a>0) printf(yes);
system(pause);
return 0;
}
好了,赶快试一试吧。
假如我希望输入正数时显示yes,输入负数或0时显示no,应该怎么
办呢?
若要实现上述要求,第3部分应改为:
如果(a大于0)显示yes
如果(a小于等于0)显示no
对应的C语言代码是:
if (a>0) printf(yes);
if (a<=0) printf(no);
完整的代码如下: include
include
int main( )
{
int a;
scanf(%d, a) ;
if (a>0) printf(yes);
if (a<=0) printf(no);
system(pause);
return 0;
}
此外,if (a>0) printf(yes);
这句话更加完美的写法是:
if (a>0)
{
printf(yes);
}所以判断正数的代码更好的写法是:
include
include
int main( )
{
int a;
scanf(%d, a) ;
if (a>0)
{
printf(yes);
}
if (a<=0)
{
printf(no);
}
system(pause);
return 0;
}
最后,需要注意的是if ( )后面是没有分号的,像下面这些写法都
是不对的!
if (a>0) ; printf(yes); if (a>0);
printf(yes);
if (a>0);
{
printf(yes);
}
至于为什么呢?这句话的意思是“如果什么成立,就做什么”,很明
显“如果什么成立”这句话只说了一半,所以if ( )后面不能加分号,需
要特别注意!
if语句的语法格式为:
if (条件)
{
语句1;
语句2;
语句 ……
}
if后面一对圆括号中的内容是一个关系表达式,当表达式成立时执
行后面花括号中的语句。好了,赶快试一试吧。
一起来找茬
下面这段代码用来判断一个数是否小于或等于100,如果是则输出
yes。其中有3个错误,快来改正吧!
include
include
int main( )
{
int a;
scanf(%d, a) ;
if (a<100) ; printf(yes);
system(pause);
return 0;
}
更进一步,动手试一试
假如我希望输入正数时显示yes,输入负数时显示no,输入0时显示
0,应该怎么办呢?
这一节,你学到了什么
if语句的基本格式是什么?第3节 偶数判断
通过对本章第2节内容的学习,我们知道计算机是通过if语句来进行
判断的。现在来尝试一下判断一个数是否为偶数。首先,先写出算法。
(1)计算机需要有一个小房子(即变量)来存储这个数。
(2)你需要告诉计算机这个数是什么?
(3)计算机需要判断这个数是否为偶数。
(4)计算机输出判断结果。
其中,在第3步你可能遇到一点小麻烦。我们想一下,什么是偶数
呢?偶数就是能够被2整除的数,也就是说如果一个数除以2的余数为
0,那么这个数就是偶数。
那么我们现在只需要判断这个数除以2的余数是不是0,即:
如果a除以2的余数与0相等,则输出yes;
如果a除以2的余数与0不相等,则输出no。
C语言中求余数的运算符号是“%”,所以判断一个数是否为偶数的C
语言代码就是:完整的C语言代码如下:
include
include
int main( )
{
int a;
scanf(%d, a) ;
if (a%2==0)
{
printf(yes);
}
if (a%2! =0)
{
printf(no);
}
system(pause);
return 0;
}
好了,应该尝试一下了。 一起来找茬
下面这段代码用来判断一个数是否是7的倍数。其中有4个错误,快
来改正吧!
include
include
int main
{
int a;
scanf(%d%d, a) ;
if a%7=0
{
printf(yes);
}
system(pause);
return 0;
}
更进一步,动手试一试
如何判断一个数的末尾是不是0呢?如果是则输出yes(例如
120),不是则输出no(例如1 234)。第4节 神器else
在本章第3节中,我们使用了两个if语句让计算机判断一个数是否为
偶数,不出意外的话,我想你已经成功了。本节我们将学习另外一个语
句来简化之前的代码,那就是神奇的else。
else表示否则,只能和if配合使用。
现在回到如何让计算机判断一个数是否为偶数这个问题上,回顾一
下本章第3节的算法:
如果a除以2的余数与0相等,则输出yes;
如果a除以2的余数与0不相等,则输出no。
其实上面第2个“如果”中的条件“a除以2的余数和0不相等”正好就是
第1个“如果”中的条件,即“a除以2的余数和0相等”的相反情况,因此我
们用“否则”来代替,从而简化我们的代码。
如果a除以2的余数与0相等,则输出yes;
否则,输出no。这里的“如果”在C语言中仍然用if来表示,这里的“否则”就用else来
表示。好,转换为如下代码:
if (a % 2==0) printf(yes);
else printf(no);
其实,更漂亮的写法是下面这样的:
if (a % 2==0)
{
printf(yes);
}
else
{
printf(no);
}从键盘读入一个整数判断它是否为偶数的完整代码如下:
include
include
int main
{
int a;
scanf(%d, a);
if(a%2==0)
{
printf(yes);
}
else
{
printf(no);
}
system(pause);
return 0;
}
if-else语句的语法格式为:
if (条件)
{ 语句1;
语句2;
语句 ……;
}
else
{
语句1;
语句2;
语句 ……;
}
当条件为真的时候执行if后面的语句;当条件为假的时候执行else后
面的语句。
一起来找茬
下面这段代码用来判断一个数的末尾是否为7,例如:7、17、127……如果是则打印yes,不是则打印no。其中有6个错误,快来改正
吧。
include
include
int main
{
int a;
scanf(%d, a); if (a%10=7);
{
printf(yes)
}
else;
{
prinf(no)
}
system(pause);
return 0;
}
更进一步,动手试一试
从键盘输入一个正整数,让计算机判断这个数是否为一位数(1~
9)。如果是则输出yes,否则输出no。
这一节,你学到了什么
if-else语句的基本格式是什么?第5节 请告诉我谁大
在本章第4节中,我们学习了使用if-else语句来判断一个整数是否为
偶数的方法。本节我们将学习如何从键盘输入两个整数,让计算机来判
断哪一个整数较大,并把较大的那个整数输出来。例如,如果我们输入
的是5和8,那么计算机输出8。
在学习“如何让计算机判断两个数中,谁更大”这个问题之前,先回
顾一下第2章中如何从键盘读入两个整数并且算出它们的和的问题。
include
include
int main
{
int a, b, c;
scanf(%d%d, a, b);
c=a+b;
printf(%d+%d=%d, a, b, c);
}
在上面这段代码中,我们输出的是“和”。那如何让计算机输出较大
的一个数呢?我们仍然使用“如果”的方法。
首先还是定义3个变量:a和b用来存放输入的两个数,c用来存放a
和b中较大的那个。 int a, b, c;
然后读入从键盘输入的两个数,分别存放到变量a和b中。
scanf(%d%d, a, b);
接下来要注意了,我们将通过之前学过的“如果”和“否则”的方法,来分情况讨论并判断谁更大。
如果(a>b) c=a;
上面这两行代码是说明在a>b条件成立的情况下,我们将a的值赋给
c。但是a>b条件并不一定成立,所以我们还要告诉计算机在条件不成立的情况下,应该怎么办。
所以还要写:
否则 c=b;
那么完整的代码如下:
如果(a>b) c=a;
否则 c=b;
总结一下,如果a>b成立,就将a的值赋给c,执行c=a。如果不成
立,就执行“否则”部分,将b的值赋给c,执行c=b。
计算机通过“如果”和“否则”方法来分情况讨论。当a>b成立时,给
出一种解决方案即执行某一个语句,这里是c=a;。当假设不成立的时
候,给出另外一种解决方案即执行另外一个语句,这里是c=b;。
完整代码如下,赶快尝试一下吧。
include
include
int main
{ int a, b, c;
scanf(%d%d, a, b);
if(a>b)
{
c=a;
}
else
{
c=b;
}
printf(%d, c);
system(pause);
return 0;
}
一起来找茬
下面程序的功能是从键盘读入两个整数,判断它们是否相等,如果
相等则输出yes,不相等则输出no。其中有6个错误,快来改正吧!
include
include
int main
{
int a; scanf(%d, a, b) ;
if (a=b) ;
{
printf(yes) ;
}
else ;
{
prinf(no) ;
}
system(pause);
return 0;
}
更进一步,动手试一试
从键盘输入两个正整数,让计算机判断第2个数是不是第1个数的约
数。如果是则输出yes,不是则输出no。第6节 逻辑挑战2:3个数怎么办
在本章第5节中,我们学习了如何从两个数中找出较大的一个数,那么3个数该怎么办呢?
在解决这个问题之前,先回忆一下,我们是如何在任意3个数中找
出最大一个数的呢?例如,1322、4534、1201这3个数中哪个数最大?
怎么样,想出来了没有?千万不要告诉我,你是“一眼”就看出来
的,如果是这样的话,请你在下列各数中“一眼”找出最大的那个来并告
诉我。怎么样,你“一眼”就看出来了吗?最大的数是多少?如果你可以在
1秒内看出来,那你一定不是地球人,最大的数是1232。
现在回归正题,我们从一个数列中寻找最大的一个数的时候,大致
是从左到右、从上到下快速地扫描(当然,古代的中国人可能是从上到
下、从右到左),在快速扫描的过程中,我们首先会记住第1个数,然
后继续往下看,一直看到一个数比之前记住的最大的数还要大时,就转
为记住这个更大的数,然后一直快速扫描完毕,找出最大的一个。下面
来模拟这个过程。同理(我上学的时候最怕看到这个词语,没有办法,这里我也借用
一下,因为我一时半会儿也想不到更好的词语了),我们来找出3个数
中最大的数也是相同的原理。
计算机要想找出3个数中最大的数,其实就是模仿我们的思维过
程。
首先,用3个变量a、b、c分别存放从键盘读入的3个数。
然后,先比较变量a和b的值,将较大的值赋给变量d。
再比较变量d和c的值,如果变量c的值大于变量d的值,则把变量
c的值赋给变量d。
最后输出变量d的值。
完整的代码如下:
include
include
int main
{
int a, b, c, d;
scanf(%d %d %d, a, b, c); if(a>b)
{
d=a;
}
else
{
d=b;
}
if(d
{
d=c;
}
printf(%d, d);
system(pause);
return 0;
}
当然还有另外一种方法,就是分别比较变量a和b,以及变量a和c的
关系……思路如下:
如果a>=b并且a>=c,则输出a;如果b>a并且b>=c,则输出b;
如果c>a并且c>b,则输出c。
其中“并且”在C语言中用“”来表示,顺便说一下在C语言
中“或”用“||”表示。“||”这个符号可能在键盘上不太好找,它通常
在“Enter”键的上面。在英文输入法状态下,按住“Shift”键不要松手,再
按下“Enter”键上方的那个键,就会出现1个“|”,重复两次就可以啦。
“”表示逻辑“并且”
“||”表示逻辑“或”
想一想为什么不能像下面这样写?这样写会有什么问题?自己去探
索吧!
[1]
如果a>=b并且a>=c,输出a;
如果b>=a并且b>=c,输出b;
如果c>=a并且c>=b,输出c。
完整的代码如下: include
include
int main( )
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if (a>=b a>=c) printf(%d, a);
if (b>a b>=c) printf(%d, b);
if (c>a c>b) printf(%d, c);
system(pause);
return 0;
}
使用这种方法虽然代码比较简洁,但是在10个数中找出最大的数就
很麻烦了。而从介绍的第1种方法则可以很容易地扩展出在10个数中找
出最大的数的方法。
一起来找茬
下面这个程序的功能是从键盘读入一个整数,判断这个数是否为7
的倍数或者为末尾含7的数,例如:7、14、17、21、27、28……如果是
则输出yes,不是则输出no。其中有5个错误,快来改正吧。
include include
int main
{
int a;
scanf(%d, a) ;
if (a%7=0 | a%10=7) ;
printf(yes) ;
else
printf(no)
system(pause);
return 0;
}
更进一步,动手试一试
1.从键盘任意读入3个整数,如何从中找出最小的一个?
2.从键盘任意读入4个整数,如何从中找出最大的一个?
3.从键盘输入一个年份(整数),判断这个年份是否为闰年,是
则输出yes,不是则输出no。第7节 逻辑挑战3:我要排序
在本章第6节中,我们学习了如何从3个数中找出最大的一个,现在
有一个新的问题:如何从键盘输入任意3个数,并将这3个数从大到小排
序呢?例如,无论你输入2 1 3、3 2 1、1 2 3还是3 1 2,计算机都能够输
出3 2 1,这该怎么办呢?此时你先不要急着往下看,思考一下,通过我
们之前学习的内容,你应该可以独立完成,赶快打开“啊哈C”去尝试一
下吧!
怎么样?我想你应该已经做出来了,即使不是完全正确也应该有了
大概的思路。如果你还没有尝试过,请赶快再去尝试一下吧,这样会让
你更容易理解下面的内容,同时也可以比较一下你想的和我所讲的是否
一样。顺便说一下,要想学好编程,最重要的就是要多尝试。
要想把3个数从大到小排序,其实有很多种方法,这里我们主要讲
解两种方法。
下面来讲第1种方法,这是一种最直接的方法。
如果a>=b并且b>=c,打印a b c;
如果a>=c并且c>b,打印a c b;
如果b>a并且a>=c,打印b a c;
如果b>=c并且c>a,打印b c a;如果c>a并且a>=b,打印c a b;
如果c>b并且b>a,打印c b a。
完整的代码如下:
include
include
int main( )
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if (a>=b b>=c) printf(%d %d %d, a, b, c);
if (a>=c c>b) printf(%d %d %d, a, c, b);
if (b>a a>=c) printf(%d %d %d, b, a, c);
if (b>=c c>a) printf(%d %d %d, b, c, a);
if (c>a a>=b) printf(%d %d %d, c, a, b);
if (c>b b>a) printf(%d %d %d, c, b, a);
system(pause);
return 0;
}
第2种方法,我称之为“换位法”。一共有3个变量,也就是说分别有
3个小房子a、b和c。我们的目标是在小房子a中存储最大的变量,在小房子b中存储次大的变量,在小房子c中存储最小的变量。
首先,我们先将小房子a中的数与小房子b中的数做比较,如果小房
子a中的数小于小房子b中的数,则将小房子a和小房子b中的数交换。这
样我们就可以确定,在小房子a和小房子b中,一定是小房子a中存的是
比较大的数。关于如何交换两个变量的值,我们在第2章的第10节已经
讨论过了,需要借助另外一个小房子t作为中转,代码如下:
if (a
此时上面的这行语句不能简写为:
if (a
因为,当a
将这3条语句放在一对{ }括号中形成一个语句块,这样当条件a
时,计算机才会依次执行t=a; a=b; b=t;这3条语句。如果不加{ },当条
件a
如何都会执行。因为if语句后面只能跟随一条语句或者一个语句块,使
得a=b;和b=t;与if(a
易让你理解:
if (a
b=t;
所以当需要在if语句后面执行多条语句的时候,就必须要用{ }把所
有需要执行的语句括起来,形成一个语句块,这样,计算机就知道它们
是一起的了,要执行就一起执行,要么就都不执行。
接下来,需要再次比较小房子a和小房子c中的数。如果小房子a中
的数小于小房子c中的数,则将小房子a和小房子c中的数交换。这样就
可以确定,在小房子a和小房子c中,一定是小房子a中存的数的值比较
大。
if (a
经过将小房子a中的数分别与小房子b、小房子c中的数进行比较和
交换,我们可以确定小房子a中存储的数一定是3个数中最大的。至于目
前小房子b和小房子c中存的是什么值不重要,因为我们待会儿还要继续
比较小房子b和小房子c中的值。重要的是已经确定小房子a中存储的已
经是最大的数了。下面继续比较小房子b和小房子c中的值,将较大的值放在小房子b
中。
if (b
下面是完整的代码,赶快来试一试吧。
include
include
int main( )
{
int a, b, c, t;
scanf(%d %d %d, a, b, c);
if (a
if (a
if (b
printf(%d %d %d, a, b, c);
system(pause);
return 0;
}
在第6章,我们将会学习选择排序,它就是基于这种方法的扩展。
题外话:有时像这样的写法,显得过于紧凑。
if (a
if (a
{
t=a;
a=b;
b=t;
}
其完整的代码如下:
include
include
int main( )
{
int a, b, c, t;
scanf(%d %d %d, a, b, c);
if (a
{
t=a;
a=b;
b=t;
}
if (a
t=a;
a=c;
c=t;
}
if (b
{
t=b;
b=c;
c=t;
}
printf(%d %d %d, a, b, c);
system(pause);
return 0;
}
一起来找茬
下面程序的功能是从键盘读入1个整数,如果这个数是奇数就输出
这个数后面的3个数,如果这个数是偶数,就输出这个数前面的3个数。
例如,如果输入的整数是5,就输出678;如果输入的整数是4,就输出
321。其中有两个错误,快来改正吧。
include
include int main
{
int a;
scanf(%d, a) ;
if (a%2==1)
printf(%d , a+1) ;
printf(%d , a+2) ;
printf(%d , a+3) ;
else
printf(%d , a-1) ;
printf(%d , a-2) ;
printf(%d , a-3) ;
system(pause);
return 0;
}
更进一步,动手试一试
从键盘读入任意4个整数,将其从小到大输出。第8节 运算符总结
通过前面的学习,我们了解了C语言中的许多运算符,有算术运算
符“+”、关系运算符“==”和逻辑运算符“”、“||”。下面我们来总结一
下,如表3-1所示。
表3-1 运算符总结
名称 作用
+ 加
减
乘
除
> 大于
< 小于
== 等于
>= 大于等于
<= 小于等于!= 不等于
与
|| 或! 非第9节 1>2究竟对不对
幼儿园的小朋友大概都知道1>2这个关系表达式是不成立的。对C
语言来讲,1>2这个关系表达的写法并没有任何错误,只不过它是假的
关系表达式。如果喜欢,你也可以写11<10,相信你还可以写出很多这
样假的关系表达式。可是你千万不要以为类似于11<10这样的假的表达
式没有任何意义,在第4章你会发现它大有用途。
此外,2>=2这个关系表达式是真的,因为它表示的是2大于2或者2
等于2,只需满足其中任意一个条件就是真的关系表达式。类似于1<=2
这样的表达式也是真的。
请看下面这段代码:
if (1>2)
{
printf(yes);
}
else
{
printf(no);
}
上面这段代码表示,如果1>2成立,也就是说如果1>2这个关系表达
式是真的,则输出yes,否则输出no。很显然1>2是假的,计算机会输出no。这个应该很容易理解。但是看到下面这段代码你肯定会晕:
if (1)
{
printf(yes);
}
else
{
printf(no);
}
你猜计算机会输出什么?去试一试!
如果是下面这样呢?
if (-5)
{
printf(yes);
}
else
{
printf(no);
}你猜计算机输出了什么,去试一试吧。
如果是这样呢?代码如下:
if (0)
{
printf(yes);
}
else
{
printf(no);
}
计算机又输出了什么呢?
如果上面的3段代码你都尝试过,你会发现前两段代码都是输出
yes,也就是说,计算机认为前两个代码中if后面圆括号内的关系表达式
都是成立的,是真的。第3段代码输出的是no,即认为第3段if后面一对
圆括号内的关系表达式不成立,是假的。
这时你可能会觉得奇怪了,关系表达式不应该是一个式子吗,至少
也应该有一个“>”、“<”或“==”之类的运算符才对啊。为什么单独一个数
字也有真假呢?
这个确实很奇怪,计算机就是认为1和-5是真的,0是假的。其实在
C语言中,对于某一个数讨论真假时,只有0是假的,其余都被认为是真
的。很显然,如下3个程序都是打印yes: if (8)
{
printf(yes);
}
else
{
printf(no);
}
if (1000)
{
printf(yes);
}
else
{
printf(no);
}
if (-123)
{
printf(yes);
} else
{
printf(no);
}
只有下面这个程序才会打印no:
if (0)
{
printf(yes);
}
else
{
printf(no);
}第10节 讨厌的嵌套
if-else语句的“嵌套”就是在一个if-else语句中再“嵌套”另外一个if-
else语句。在讲“嵌套”之前我们先回忆一下本章第6节中的一个例子:如
何在三个数中找出最大的一个数。
include
include
int main( )
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if (a>=b a>=c) printf(%d, a);
if (b>a b>=c) printf(%d, b);
if (c>a c>b) printf(%d, c);
system(pause);
return 0;
}
在上面的代码中,我们使用了“”这个逻辑关系运算符号来解决
两个条件同时“满足”的需求。其实还有另外一种方法来解决这个问题。 if(a>=b a>=c)
printf(%d, a);
例如,上面这段代码,可以用“嵌套”的方式写成:
if(a>=b)
{
if(a>=c)
{
printf(%d, a);
}
}
其意思是:当a>=b条件满足时,再进一步讨论a与c的关系(如果
a>=c也成立的话,就打印a)。
接着往下想,如果此时a>=b已经成立,但是a>=c不成立的话,是不
是就意味着在a、b、c中,c是最大值呢?答案是肯定的。代码如下:
if(a>=b)
{
if(a>=c)
{ printf(%d, a);
}
else
{
printf(%d, c);
}
}
那如果第一个条件a>=b不成立呢?完整的代码如下:
include
include
int main
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if(a>=b) a>=b成立的情况
{
if(a>=c) 进一步讨论a与c的关系
{
printf(%d, a);
}
else
{
printf(%d, c); }
}
else a>=b不成立的情况
{
if(b>=c) 进一步讨论b与c的关系
{
printf(%d, b);
}
else
{
printf(%d, c);
}
}
system(pause);
return 0;
}
在上面的代码中所有的if-else语句都加了{ },这样看起来很臃肿,我们之前说过如果if和else后面只有一条语句的话,是可以省略{ }的。
代码如下:
include
include
int main {
int a, b, c;
scanf(%d %d %d, a, b, c);
if(a>=b)
{
if(a>=c)
printf(%d, a);
else
printf(%d, c);
}
else
{
if(b>=c)
printf(%d, b);
else
printf(%d, c);
}
system(pause);
return 0;
}
上面的代码其实还可以更简洁,如下:
include include
int main
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if(a>=b)
if(a>=c)
printf(%d, a);
else
printf(%d, c);
else
if(b>=c)
printf(%d, b);
else
printf(%d, c);
system(pause);
return 0;
}
你发现没有,在上面的代码中,我们把最外层if-else语句的{ }也去
掉了。有的同学可能就有问题要问了。我们先来解决问题2。问题2比较简单,else的匹配采用就近原则,离上方哪个if最近,就属于哪个if。所以问题2所指向的那个else是属于
if(b>=c)这个if。这样你就可以把if和else分别一一配对了吧,是不是
有点连连看的感觉。
问题1说起来比较麻烦,但是原理很简单,请听我慢慢道来。其实
上面虚线框中的代码是一个if-else语句,并且是一个很完整的if-else语
句,因为它不但有if部分还有else部分。只不过很特别的是,if部分和
else部分都分别有自己的子语句printf部分,所以看起来就显得很多了。
其本质上就是一条if-else语句,一个“复合语句”。不过在外层的
if(a>=b)看来,它就是一条if-else语句,至于这条语句内部长什么样
子,if(a>=b)并不关心,其实就像大盒子里面套小盒子一样,if(a>=b)是搞不清楚if(a>=c)里面是什么样子的。第11节 if-else语法总结
其实说起来很简单,当if( )括号内的关系表达式成立的时候,就
执行if( )后面的{ }中的内容,不成立的时候则执行else后面{ }中的内
容。当{ }内的语句只有一条的时候,{ }可以省略。
if(关系表达式)
{
语句;
语句;……
}
else
{
语句;
语句;……
}
当{ }内的语句只有一条的时候,可以省略{ }。
if(关系表达式)
语句; else
语句;
[1] 在写本书草稿的时候,我也没有注意到这个问题,感谢@滚雪球snow的提
醒。第4章
重量级选手登场
第1节 永不停止的哭声
通过第2章的学习,我们知道如果让计算机开口说话要使用printf语
句。例如,让计算机说“wa”,则使用printf(wa);。那如果让计算机
说10遍“wa”呢?你可以尝试这样写:
printf(wa wa wa wa wa wa wa wa wa wa);
或者你也可以这样写:
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa); printf(wa);
如果让计算机说10000遍“wa”呢?该怎么办呢?我想你肯定要疯了
吧。在本节我们就要学习如何让计算机做重复的事情。
好,首先我们学习如何让计算机“永无止境”地说“wa”。这很简单,代码如下:
while(1>0)
{
printf(wa);
}
赶快尝试一下,你是不是发现计算机开始无止境地说“wa”了呢。
完整的代码如下:
include
include
int main
{
while(1>0)
{
printf(wa); }
system(pause);
return 0;
}
一定要尝试啊,尝试后再往下看。
当然,你也可以让计算机无止境地说任何内容。例如:
while(1>0)
{
printf(bie wa);
}
回到正题。上面的代码中由两部分组成,一部分是while( )中的
内容,另一部分是{ }中的内容。它表示的意思是,当while后面( )中
的关系表达式为真时,即关系表达式成立时才执行{ }中的内容。
那么很显然,1>0这个关系是永远成立的,所以计算机会一直执行{
}中的内容,而上面的例子{ }中只是输出wa,所以计算机就会不停地输
出wa。这里顺便说一下,如果{ }中只有一条语句,那么{ }便可以省略。
也就是说可以简写成:
while(1>0)
printf(wa);
这时你可能要问了:while后面( )中的1>0是否可以写成2>1或者
3>0等?
当然可以,如果想让计算机永不停止地如此执行,你可以写任何一
个关系表达式为真的式子。甚至,你可以写while(1)。还记得吗,我
们在第3章说过,如果对某个数字判断真假,只要这个数不为0就是真
的。例如,下面这段代码也可以永不停止地在屏幕上打印wa:
while(1)
printf(wa);下面我来实现一个很炫的效果,“黑客帝国”来啦!
include
include
int main
{
while(1>0)
{
printf(0 1);
}
system(pause);
return 0;
}
执行上面的代码后计算机就会不停地在屏幕上打印0和1。
当然,你可以改变一下打印的背景与字的颜色,例如,改为黑色的
背景,绿色的字。
还记得吗?是使用system(color 0a);这个语句。 include
include
int main
{
system(color 0a);
while(1>0)
{
printf(0 1);
}
system(pause);
return 0;
}
是不是很像黑客帝国?
猜一猜,运行下面这段代码,计算机会有什么反应?
include
include
int main
{
while(1<0)
{
printf(wa);
} system(pause);
return 0;
}
我想你应该猜到了,计算机一句“wa”都没有说,这是为什么呢?因
为1<0这个关系表达式不成立,所以计算机没有执行后面{ }中的内容。
此时你会发现计算机要么打印无数遍都不停止,要么就一次都不打
印。如果想打印指定的次数该怎么办?例如,我们之前遗留下来的问
题:打印10000遍wa,一次也不多、一次也不少该怎么办?不要着急,让我们一起进入本章第2节。
一起来找茬
下面这段代码是让计算机“永无止境”地打印hello。其中有两个错
误,快来改正吧!
include
include
int main( )
{
while(1>0);
print(hello);
system(pause);
return 0;
} 更进一步,动手试一试
让计算机“永无止境”地在屏幕上显示中文汉字“你好”。
这一节,你学到了什么
在C语言中我们用什么语句来实现循环的功能?第2节 我说几遍就几遍
在本章第1节,我们学习了如何使用while循环来让计算机做重复的
事情,本节将揭晓如何让计算机重复指定的次数。
我们知道如果while后面( )中的关系表达式成立,计算机就会运
行{ }中的内容。如果( )中的关系表达式永远成立,那么计算机会“永
无止境”地去重复执行{ }中的内容。
假如让计算机打印100次“wa”,我们需要解决的就是如何让while中的关系表达式在前100次是成立的,然后在第101次的时候就不成立
了。想一想,根据我们之前学过的知识,你有没有什么方法?
很显然while后面的( )中的关系表达式,像2>1或者1<=100等都是
不适合的,因为像这样用固定的数字组合的关系表达式,一旦被写出,那么这个式子是否成立就已经是板上钉钉啦,非真即假,而且永远不会
改变。例如,1<=100这个关系表达式是永远成立的,这样并不符合我们
的要求。我们需要创造怎样一个新的关系表达式,才能让这个式子有时
成立,有时不成立?该怎么办呢?我猜你已经想到了!那就是——伟大的“变量”。
我们可以尝试一下带有变量的关系表达式,例如,a<=100。因为a
是一个变量,a这个小房子里面所装的数是可以变化的。当小房子a中的
数是1的时候,a<=100是成立的;当小房子a中的数是101时,a<=100就
不成立了,这正好满足了对于表达式a<=100有时成立有时不成立的要
求。对于a<=100这个关系表达式是否成立的关键就在于a这个变量所装
的数是多少,也就是变量a的值。
如果想让a<=100在前100次成立,在第101次不成立的话,只需将变
量a的值从1变化到101就可以了。那么如何让变量a的值从1变化到101
呢?我们只需在最开始的时候将变量a的值赋为1,然后while循环每循环
一次,就将变量a的值在原来的基础上再加1就可以了。当变量a的值加
到101时,a<=100就不成立了,就会结束循环。代码如下:
int a;
a=1;
while(a<=100)
{
printf(wa);
a=a+1;
}
再来分析一下上面的代码,a=a+1;这条语句的作用是把小房子a中
的值在原本的基础上增加1(在第2章第5节有详细解释,如果还没有搞
懂还是回去看看吧)。变量a最开始时值为1,每执行一次while循环,变量a的值就会在原来的基础上增加1,依次变成2、3、4、5、6、7、8、9,…,100、101。直到变量a的值为101时,a<=100的条件不成立,退出循
环。
完整的代码如下:
include
include
int main
{
int a;
a=1;
while(a<=100)
{
printf(wa);
a=a+1;
} system(pause);
return 0;
}
赶快尝试一下吧。如果输出10000个wa该怎么办?或者输出10个
hello呢?赶快去尝试一下吧。
接下来一个问题:如果要打印1~100该怎么办?
include
include
int main
{
int a;
a=1;
while(a<=100)
{
printf(wa);
a=a+1;
}
system(pause);
return 0;
}
在这段代码中,我们打印了100个wa,那么打印1~100也很简单,只需修改printf语句就可以了。该如何修改printf语句呢?之前printf语句
的作用是输出wa,现在需要输出1~100,正巧变量a的值就是从1一点点
增加到100的。我们只需在每次循环时把a的值输出即可,即把
printf(wa);改为printf(%d , a);。完整的代码如下:
include
include
int main
{
int a;
a=1;
while(a<=100)
{
printf(%d , a);
a=a+1;
}
system(pause);
return 0;
}
赶快尝试一下吧。
如果我们想倒序输出呢,就是让计算机先输出100再输出99接着输
出98、97、96、95、…、1,该怎么办?
我们刚刚学过的“让计算机输出1~100”,就是让变量a从1开始,通过while循环把变量a的值每次都输出来,并且每次循环的时候将变量a的
值增加1,这样就会打印出1~100。而此时的要求是从100打印到1。很
显然我们需要让变量a从100开始,通过while循环把变量a的值每次都输
出来,不过每次需要递减1,一直递减到1为止。代码如下:
include
include
int main
{
int a;
a=100; 初始值从100开始
while(a>=1) 请注意这里的循环条件变为a>=1
{
printf(%d , a);
a=a-1; 每循环一次将a的值递减1
}
system(pause);
return 0;
}
问题又来啦,如果希望打印的是1~100中的偶数呢?自己想一想
吧。
怎么样,有没有思路?其实要输出1~100中的偶数,有很多种方
法。比如之前变量a是从1开始的,之后每次在原有的基础上增加1,那么a就会从1到2再到3再到4……一直到101,当变量a的值增加到101时,不满足条件a<=100,就会退出while循环。现在我们可以改变一下思
路,让变量a的值从2开始,每次增加2,这样变量a就会从2增加到4再增
加到6……以此类推。代码如下:
include
include
int main
{
int a;
a=2;
while(a<=100)
{
printf(%d , a);
a=a+2;
}
system(pause);
return 0;
}
好了,又到了尝试的时候了。
如何让计算机打印1~100中能被3整除的数,你应该也会了,就是
先将变量a的初始值赋为3,然后每次增加3。赶快再尝试一下吧。
上面的写法虽然好,却不是万能的,假如不是输出1~100中能被3整除的数,而是输出1~100中所有不能被3整除的数呢?例如:1、2、4、5、7、8、10, …, 97、98、100,又该怎么办呢?不要着急,我们将
在本章第3节彻底解决这个问题。
一起来找茬
下面这段代码是让计算机从100打印到200。其中有3个错误,快来
改正吧!
include
include
int main
{
int a;
a=100;
while(a<200) ;
{
printf(%d , a);
}
system(pause);
return 0;
}
更进一步,动手试一试
让计算机从1打印到100再打印到1,例如:1 2 3 …… 98 99 100 9998 …… 3 2 1。第3节 if对while说:我对你很重要
在本章第2节中,我们学习了while循环的基本使用方法,但是遗留
了一个问题,即如何让计算机输出1~100中所有不能被3整除的数,例
如:1、2、4、5、7, …, 97、98、100。
通过本章第2节的学习,我们可以很容易地让计算机打印1、2、3,…,100,只需让变量a从1开始每次增加1就可以了。如果想每次遇到3的
倍数就不打印的话,我们只需在每次打印之前对变量a的值进行判断就
好了,即当变量a的值是3的倍数时就不输出,否则就输出。那怎么判断
变量a的值是否是为3的倍数呢?这就需要我们在第3章学习的if语句。我
们只需要通过if语句来判断变量a的值除以3的余数是否为0就可以了。如
果余数不为0,说明变量a中的值不是3的倍数,就将变量a中的值打印出
来;否则就说明变量a中的值是3的倍数,不能打印。
那么怎么判断变量a中的值除以3的余数是否为0呢?需要使用“%”这
个运算符。在第3章中我们介绍过,“%”读作mod,也可以称之为“取
模”,作用就是获取余数。另外说一下“%”这个运算符的左右两边必须为
整数。而“”这个符号表示除号,作用是获取商,“”运算符的左右两边
既可以是整数也可以是小数。代码如下:
include
include
int main
{ int a;
a=1;
while(a<=100)
{
if(a%3! =0)
printf(%d , a);
a=a+1;
}
system(pause);
return 0;
}
赶快尝试一下吧。如果要输出1~100中能被3整除但是不能被5整除的所有数,又该怎
么办?
这个数是3的倍数但不是5的倍数,也就是需要变量a除以3的余数为
0并且除以5的余数不为0。这里的逻辑关系“并且”在C语言中的表示方法
我们在第3章已经学习过,用“”表示,代码如下:
include
include
int main
{
int a;
a=1;
while(a<=100)
{
if(a%3==0 a%5! =0)
printf(%d , a);
a=a+1;
}
system(pause);
return 0;
}
更复杂的来啦!
你有没有和同学玩过一个游戏——大家围成一圈,从1开始报数,但是每逢遇到7的倍数或者末尾含7的数,例如7、14、17、21、27、28
等,就要拍手并且不能报出,谁出错了,谁就要受到惩罚。
现在我想知道1~100中有多少这样的数,请你写这样一个程序,输
出1~100中所有7的倍数和末尾含7的数。
很简单,我们先参照以往的程序,利用while循环,让变量a从1递增
到100,不过我们每次在输出变量a的值之前需要对变量a进行判断。根
据题目的要求,如果变量a的值是7的倍数或者末尾含有7就打印出来。
判断一个变量是否为7的倍数我们已经很熟悉了,只需要判断变量a除以
7的余数是否为0就可以,即如果a%7==0这个关系表达式成立就输出。
那怎么判断变量a的值末尾是否含7呢?我们仔细想一想就会发现,末尾
含7的数其实就是这个数的个位为7,也就是这个数除以10的余数为7。
发现这个规律就好办了,即在a%10==7这个关系表达式成立时输出就可
以啦。
好了,现在有两个关系表达式a%7==0和a%10==7,分别表示这个
数是否为7的倍数以及末尾是否含7。这两个式子是“或者”的关系,即只
要有一个成立,就将这个数输出。这里的逻辑关系“或者”在C语言中的
表示方法我们在第3章也学习过,用“||”表示,代码如下:
include
include
int main
{
int a;
a=1; while(a<=100)
{
if(a%7==0 || a%10==7)
printf(%d , a);
a=a+1;
}
system(pause);
return 0;
}第4节 求和!求和!!求和!!!
在本章第2节中,我们已经学习了如何让计算机打印1~100,那如
何让计算机求1~100中所有数的和呢?
你可能会说,首项加尾项的和乘以项数然后再除以2,就可以了。
没错,你可以这样做,但是如果求1~100中所有7的倍数或者末尾含7的
数的总和,又该怎么办呢?
在求1~100的和之前,我们先来解决如何求1+2+3的值。
没错,你可以这样写:
include
include
int main
{
int a;
a=1+2+3;
printf(%d, a);
system(pause);
return 0;
}
但是如果计算1~100中所有数的和也这样写的话,是不是太麻烦了呢?我们可以尝试另一种写法,代码如下:
include
include
int main
{
int a;
a=0; 想一想为什么a的初始值要为0呢?
a=a+1;
a=a+2;
a=a+3;
printf(%d, a);
system(pause);
return 0;
}
你可能会说这样写岂不是更麻烦……但是我们发现在上面的这段代
码中,a=a+1;a=a+2; a=a+3;这三句话,基本思想是相同的,第一次加
1,第二次加2,第三次加3。我们可以把这三个语句用a=a+i;来表示。
然后让变量i从1到3循环就可以了。代码如下:
include
include
int main {
int a, i;
a=0;
i=1;
while(i<=3)
{
a=a+i;
i=i+1;
}
printf(%d, a);
system(pause);
return 0;
}
如果需要计算1~100的和,我们只需将上面代码中i<=3修改为
i<=100就可以了,赶快去尝试一下吧。
如果求1~100中所有7的倍数或者末尾含7的数的总和,又该怎么办
呢?先来回顾一下刚刚才学会的求1~100中所有数的和的方法,代码如
下:
include
include
int main
{ int a, i;
a=0;
i=1;
while(i<=100)
{
a=a+i;
i=i+1;
}
printf(%d, a);
system(pause);
return 0;
}
在上面的代码中,变量i会从1到100每次递增1,然后每次将变量i的
值累加到变量a上。这个变量i就像是一个搬运苹果的工人,刚开始只拿
1个苹果,之后拿2个苹果,再之后又拿3个苹果……最后一次一下拿了
100个苹果。
变量a就像是一个很大很大的水果篮子,用来装这些苹果。每次拿
来的苹果统统被装进篮子里面,第一次放1个苹果进去,第二次放2个苹
果,第三次放3个苹果进去……最后一次放100个苹果进去。最后篮子a
中苹果的总数就是1~100的和。所以我们最后输出了变量a的值,这就
是答案。那么求1 ......
逻辑的挑战
修订版
啊哈磊著
電子工業出版社 ·
Publishing House of Electronics Industry
北京·BEIJING内容简介
这是一本非常有趣的编程启蒙书,全书从中小学生的角度来讲述,没有生涩的内容,取而代之的是生动活泼的漫画和风趣幽默的文字。配
合超萌的编程软件,本书从开始学习与计算机对话到自己独立制作一个
游戏,由浅入深地讲述编程的思维。同时,与计算机展开的逻辑较量一
定会让你觉得很有意思。你可以在茶余饭后阅读本书,甚至坐在马桶上
也可以看得津津有味。编程将会改变我们的思维,教会我们如何思考,让我们的思维插上计算机的翅膀,以一种全新的方式来感知世界。未经许可,不得以任何方式复制或抄袭本书之部分或全部内容。
版权所有,侵权必究。
图书在版编目(CIP)数据
啊哈C语言!:逻辑的挑战啊哈磊著.—修订本. —北京:电子工业
出版社:2017.1
ISBN 978-7-121-30462-0
Ⅰ.①啊… Ⅱ.①啊… Ⅲ.①C语言-程序设计-青少年读物
Ⅳ.①TP312.8-49
中国版本图书馆CIP数据核字(2016)第284866号
责任编辑:徐津平
印 刷:中国电影出版社印刷厂
装 订:中国电影出版社印刷厂出版发行:电子工业出版社
北京市海淀区万寿路173信箱 邮编100036
开 本:787×980 116
印 张:13
字 数:255千字
版 次:2013年9月第1版
2017年1月第2版
印 次:2017年1月第1次印刷
印 数:4000册
定 价:49.00元
凡所购买电子工业出版社图书有缺损问题,请向购买书店调换。若书店
售缺,请与本社发行部联系,联系及邮购电话:(010)88254888,88258888。
质量投诉请发邮件至zlts@phei.com.cn,盗版侵权举报请发邮件至
dbqq@phei.com.cn。
本书咨询联系方式:(010)51260888-819, faq@phei.com.cn。修订版序
自《啊哈C》出版以来,我与编程爱好者们便有了更多的交流机
会。这些编程爱好者之中不乏大学生、中学生、老师、家长,更有小学
二、三年级的学生。令我惊喜的是,二、三年级的小读者们与我探讨的
并不是浅显的语法或BUG调试问题,更多的是他们通过独立思考发的书
中的错误,他们向我阐述自己的思想,与我交流游戏开发中遇到的逻
辑、算法等。还有一些读者留言说:“这本书不仅仅是小学生坐在马桶
上都能看懂的书,是连我妈妈或是我姥姥都能看懂的编程书!”这些读
者实在是太捧场了,有幸让我体验了一次漫卷诗书喜欲狂的感觉。也有
好多读者看完后直呼不过瘾,常常询问何时能有第二部。一晃已是三
年,借此《啊哈C语言!逻辑的挑战》修订之际,第二部《啊哈C语
言!游戏实验室》也如期而至,它景致依旧,故事常新,希望你能喜
欢!让我们再次共同探索编程与梦想的一切可能。
啊哈磊
2016年12月第一版序
我经常被问到一个问题:当初为什么会去学编程?我的回答是,因
为我很喜欢玩游戏。每一个喜欢玩游戏的人,都梦想着可以通过修改游
戏的程序使游戏中的自己变得非常强大,而这需要学习编程。其实每一
个喜欢玩游戏的人都曾有过创造游戏的梦想,那我们为什么不把这种梦
想变成学习的动力呢?我就是这样踏上编程之路的。
牛人肯·汤普逊(Kenneth Lane Thompson)自己编写了一个叫作“星
际旅行(Star Travel)”的游戏。而汤普逊为了能更顺畅地玩这个游戏,竟然自己动手用汇编写了UNIX操作系统。后来他觉得用汇编写UNIX操
作系统非常麻烦和辛苦,于是和另一个牛人丹尼斯·里奇一起创造了C语
言。没想到吧,C语言竟然是一个牛人为了玩自己写的游戏而创造的。
其实这在计算机界很正常,程序员们往往就是因为某个游戏或者软件的
现有功能不能满足自己的需求,才开发出了更加优秀的游戏和软件。本
书中超萌、超简洁的“啊哈C语言”编程软件也是这样来的。
我经常被问到的第二个问题:为什么普通人需要关心编程呢?我的
答案是,因为当下程序员几乎主宰了整个世界,控制着生活的方方面
面。我们住的房子、穿的衣服、吃的东西、用的各种电子产品,以及我
们去ATM取钱、坐电梯、开汽车、坐飞机、坐火车等,都离不开编
程。你坐火车时有没有想过,一条铁轨上同时运行的那么多列火车是如
何调度才没有导致它们相撞的。这个时代很难想象还有什么不是通过计
算机程序控制的。如果想理解这个时代,就必须理解计算机编程。编程
会让我们以一种全新的方式来看世界。当然,在学习编程的过程中还可以提高我们的逻辑推理能力、批判性思维和动手解决问题的能力。与计
算机展开的逻辑较量一定会让你觉得很有意思。
我还经常被问到第三个问题:什么样的人可以自学编程,学习编程
需要什么基础?答案是,你只需具有小学四年级以上文化程度,并且熟
练运用鼠标和键盘就可以。你若不信,那就从这本书开始吧。
编程很容易让我们实现梦想。如果我们觉得某个游戏玩得不爽想提
升体验,或者觉得某个软件不够好用想自己做一个,没问题,现在就可
以!而唯一的投入就是一台计算机。实现梦想从未变得如此简单。编程
世界里每天都上演着传奇,一大批热爱编程并且满怀梦想的人正在充满
激情地奋斗着。
编程将会改变我们的思维,教给我们如何思考,会编程的人总想改
变点什么。正如乔布斯所说“I think everybody in this country should learn
how to program a computer, should learn a computer language, because it
teaches you how to think.”
啊哈磊
2013年9月注:文中出现的“□”同原版纸书目 录
修订版序
第一版序
第1章 编程改变思维
第1节 为什么要学习编程
第2节 本书是讲什么的,写给谁看的
第2章 梦想启航
第1节 编程的魔力
第2节 让计算机开口说话
第3节 多彩一点
第4节 让计算机做加法
第5节 数字的家——变量
第6节 数据输出——我说咋地就咋地
第7节 数据输入——我说算啥就算啥
第8节 究竟有多少种小房子
第9节 拨开云雾见月明
第10节 逻辑挑战1:交换小房子中的数
第11节 天啊!这怎么能看懂
第3章 较量才刚刚开始
第1节 大于、小于还是相等
第2节 判断正数
第3节 偶数判断
第4节 神器else
第5节 请告诉我谁大
第6节 逻辑挑战2:3个数怎么办第7节 逻辑挑战3:我要排序
第8节 运算符总结
第9节 1>2究竟对不对
第10节 讨厌的嵌套
第11节 if-else语法总结
第4章 重量级选手登场
第1节 永不停止的哭声
第2节 我说几遍就几遍
第3节 if对while说:我对你很重要
第4节 求和!求和!!求和!!!
第5节 逻辑挑战4:60秒倒计时开始
第6节 这个有点晕——循环嵌套来了
第7节 逻辑挑战5:奔跑的字母
第8节 究竟循环了多少次
第9节 逻辑挑战6:奔跑的小人
第10节 for隆重登场
第5章 好戏在后面
第1节 程序的3种结构
第2节 啰嗦一下
第3节 逻辑挑战7:判读质数很简单
第4节 更快一点:break
第5节 continue
第6节 逻辑挑战8:验证哥德巴赫猜想
第7节 逻辑挑战9:水仙花数
第8节 逻辑挑战10:解决奥数难题
第9节 逻辑挑战11:猜数游戏
第10节 逻辑挑战12:你好坏,关机啦第6章 天啊!一大串数正在接近
第1节 逆序输出
第2节 申请100个小房子怎么办
第3节 100个数的逆序
第4节 逻辑挑战13:陶陶摘苹果
第5节 逻辑挑战14:一个萝卜一个坑
第6节 逻辑挑战15:选择排序
第7节 二维数组
第8节 剩下的一些东西
第7章 有了它你能做更多的事
第1节 字符的妙用
第2节 多余的回车键
第3节 字符的本质
第4节 人名怎么存储呢
第5节 逻辑挑战16:字母的排序
第6节 逻辑挑战17:字典序
第7节 多行字符
第8节 存储一个迷宫
第8章 游戏时间到了
第1节 走迷宫
第2节 推箱子
附录A 标识符命名规则
附录B 运算符的优先级和结合性第1章
编程改变思维
第1节 为什么要学习编程
你是否还在将计算机(电脑)当作上网、聊天和玩游戏的工具?没
错,大部分人是这样的。当你拿起本书阅读到这里的时候,太好了,你
又多了一个更好的选择,一个独特的机会!
在我们生活的这个时代,你会发现有这样一群人,他们对世界的影
响越来越大,电视、报纸和网络到处都充斥着他们的身影。比尔·盖茨
创立了微软,让计算机更容易被我们平常人所使用
[1];乔布斯创立了
苹果,iPhone、iPad和iPod每一样产品都在改变着我们的日常生活;谢
尔盖·布林和拉里·佩奇两个年轻的小伙创立了Google,使得获取知识变得前所未有的容易;马克·扎克伯格创立了Facebook,正在改变人与人
之间的关系……甚至12岁的小软件工程师托马斯·苏亚雷斯
[2]
都在改变
我们的世界。他们是怎样的一群人?他们为什么会创造奇迹?巧的是他
们都有一个共同的特点:在少年时都酷爱计算机编程。计算机编程究竟
具有怎样的非凡魔力?计算机编程是否给他们带来与常人不同的思维或
思考方式?是否是计算机编程为他们开启了不一样的人生道路?
为什么他们从小就开始接触计算机,不但没有沉迷于游戏,反而改
变了世界呢?12岁的托马斯说:“现在的孩子们不再只是爱玩游戏,他
们还想自己制作好玩的游戏,不过孩子们大多不知道去哪里学习计算机
编程,而懂得计算机编程的家长又很少。”
其实每个人在童年时期都曾经有创造游戏的梦想,我们为什么不把
这种梦想变成学习的动力呢?大部分孩子在面对计算机的时候都缺乏引
导,因为他们不知道计算机除了上网、聊天和玩游戏外还能做什么。即
使有人想深入地学习计算机,也不知道去哪里学,没有方向,更没有一
本简单易懂并且有趣的入门书。计算机从被发明的那一天起,其使命就是帮助我们提高学习和工作
的效率并且改变世界。利用计算机编程,你可以轻松解决数学难题。例
如,□3×6528=3□×8256,在两个□内填入相同的数字使得等式成立。你
觉得这样的题目太简单了?那么来个稍微复杂点的:□□□+□□□=□□□,请将1~9这9个阿拉伯数字分别填入9个□中使等式成立,每个数字只能
使用一次。计算机可以轻轻松松地解决。如果再复杂一点,我想知道上
面这个式子的所有解,通过笔算就很困难了,但如果使用计算机编程去
解决,就易如反掌,这正是计算机所擅长的。有时你甚至可以利用计算
机编程去验证世界性的数学难题,例如,在10 000以内去验证哥德巴赫
猜想,也都不成问题。当解决大质数、图论等问题时,计算机编程也是
最好的帮手。
那么学计算机究竟是学什么呢?答案是逻辑思维和编程思维。
早在20世纪50年代,美国教育界就开始重视计算机编程教学。20世
纪80年代后,计算机编程教学逐渐进入中小学校,以教程序设计语言为
主,目的是提高学生的逻辑推理、批判性思维和动手解决问题的能力。
实践证明,学习了计算机编程的中小学生,思考问题的方式变得非常逻
辑化,学会了严密的逻辑推理方法,并无形中把它应用到其他学科的学
习中。学习计算机编程本质上是在学习一种思维方式——编程思维,它
是一种思维体操。青少年本身对计算机有着浓厚的兴趣并且有超强的记
忆力,计算机编程将有助于开发其学习潜力,提高逻辑推理能力和解决
问题的能力。
学习计算机编程的过程充满乐趣。如果你有一个想法,马上就可以
通过编程来实现,并且可以立即看到效果。这种即时的反馈,会让你的
学习兴趣变得越来越浓厚,也会让你越来越有信心。这种超强的信心,是你在其他学科中难以感受到的。我还记得我的第一个程序运行成功时的那种兴奋,真是太棒了,你一定要去感受一下,这是你一辈子都不会
忘记的感觉。
最后,用笔者一个武汉二中的学生吕凯风
[3]
学习编程时的感受来
结束本小节。
“记得我那时学编程全凭兴趣,兴趣引导我前进。以前做完了作业
打游戏,如今写完了作业就编程。我觉得学会编程后最让自己激动的
是,我能用编程来解决几乎所有遇到的数学问题。学数学最强调技巧
性,比如7的2000次方除以3的余数是多少?21 212 157是不是质数?你
也许可以用一些小技巧把这两个问题解决掉,但是当我们遇到更难的问
题时,往往无能为力。比如214 125 315的123 719 857次方除以12 125
987的余数是多少?2 147 483 647是不是质数?很多实际问题并不像数
学中那么理想和美好,许多数学结论,尽管被证明得很巧妙,式子简
洁,但是归根结底,如果它只解决了一个特殊问题,则不具有什么实用
价值。所以我更喜欢信息学,它告诉我如何去解决一个一般化的问题而
不是一个特殊的有技巧性的问题。编程最让我感慨的是它无与伦比的唯
一性与严谨性。”
说到这里你是不是有点心动了?第2节 本书是讲什么的,写给谁看的
在写本书之前,我反复问了自己几个问题:这本书是讲什么的?这
本书是写给谁看的?这本书和一般的编程入门书有什么区别?为什么要
写这本书?选用哪一门编程语言入门呢?
第一个问题:这本书是讲什么的?
这是一本编程入门书。但是本书的重点并不是编程入门,而是向你
展示逻辑思维和编程思维的魅力,让你像程序员一样思考。
第二个问题:这本书是写给谁看的?
编程类图书给大众的印象一直是枯燥并且难懂的。究竟什么样的人
才能学习编程呢?大学生?高中生?初中生?……不会连小学生都可以
吧?!没错,只要有小学四年级的水平,我想你一定可以学习编程,并
且轻松读懂本书的全部内容。
如果你的情况恰好符合以下一点或几点,那么本书正是为你所写
的。
(1)如果你想自己制作好玩的游戏,而不是沉迷于别人的游戏
中。
(2)如果你曾对数学感兴趣,我想你一定会喜欢这本书。其实学
习编程并不需要精通数学,本书不会出现很复杂的数学公式。即使数学
不太好,甚至很糟糕,也完全可以阅读。(3)如果你对逻辑感兴趣,你一定更会喜欢这本书。与计算机展
开的逻辑较量一定会让你觉得非常有意思。因为计算机有时会显得不那
么听话,你让它向东可它却偏偏向西,这时候就一定是你编写的程序出
现了逻辑问题。而将你的思维清晰有条理地变成计算机程序,就如同一
场你与计算机之间的逻辑对决。学习计算机编程能够很好地锻炼你的逻
辑思维能力。
(4)如果你从小喜欢拆装玩具、改装小电器或是喜欢变废为宝,我想计算机编程会给你带来更多的创造机会。
(5)如果你正在读《高中数学必修三》的“算法”一章,那么你一
定要阅读本书,去了解计算机编程和算法的本质。
(6)正在学习C语言的理工科或者文科的大学生们。
(7)准备学习编程的爱好者,或者准备以此为工作的人。
(8)哦,对了,还有就是看了很多编程书籍但是一直没有看懂的
人,我想你一定可以轻松读懂本书。
(9)没有那么多原因,就是喜欢计算机。
第三个问题:为什么要写这本书呢?
正如前面所说,计算机是一门科学,如果你只是把它当成上网、聊
天和玩游戏的工具,那就太可惜了,你将可能失去一个发现自己才能的
机会。即使在计算机编程上有一些天赋,你也有可能失去这一机会。和
其他人一样,你必须去主动发现自己的天赋和兴趣,就好比你从来没有
吃过冰淇淋,就不可能知道自己喜欢吃冰淇淋。然而,如果学习了计算
机编程,你就会发现计算机编程就如同玩游戏一样有趣,充满活力的思考过程就如同一场比赛令人兴奋。在感受到了计算机编程给你带来的乐
趣后,你就再也不会沉迷于计算机游戏,计算机编程将成为你生活中不
可缺少的一部分,成为你的一种爱好,成为你的一种学习动力。我想有
更多人期待去了解计算机编程。
最后一个问题:选用哪一门编程语言入门呢?
学习编程的重点在于学习编程的逻辑和思维。本书选用较为简单的
C语言。你可能要问为什么不选C++、C、Java或者Python之类。因为
我觉得相比之下C语言最为单纯,没有那么多乱七八糟的东西,非常简
洁。即使以C语言为载体,我也尽量做到重点去讲解最有用的内容,而
不是C语言的高深语法或者我至今都没有用过的“奇怪”语句。这样就有
更多的时间去思考如何解决问题,去关注编程的逻辑和思维。
当然,说到底C语言仅仅是我们与计算机沟通的一门语言而已,相
信你在阅读完本书之后,可以很轻松地上手任何一门语言,因为其本质
都是一样的。根据TIOBE index的程序语言年度排名,2012年最流行的
编程语言正是有着40年历史的C语言,它战胜了Java语言位居TIOBE
index榜首,这或许也能说明C语言的重要性吧。以C语言为根本,将帮
助你更好地去理解编程的思想,而不仅仅是学会编程。
另外我想告诉你,编程真的是一件非常有趣的事。你就像是一个指
挥官,让计算机毫无怨言地为你工作。通过编程,你将体会到战胜困难
和挑战后的快乐与满足。编程的世界充满无限的可能,只有想不到,没
有做不到。当然在编程的时候也会遇到很多问题,我在书中也为你设置
了绊脚石,希望你能够顺利地把它找出来。尽信书,不如无书。学习不
但要细致,还要有思辨的能力,这样才会有创新,才能总结并创造出自
己的东西。现在开始自己动手编程,不要放弃曾经的梦想,大胆地创造你的作品。
艾伦·凯曾经这样说道:“在自然科学中,是大自然给出一个世界,而我们去探索其中的法则。对于计算机来说,却是我们自己来构建法
则,创造一个世界。”
当下,我们的学习不应该再忙碌于重复的计算、记忆等技能。阅
读、逻辑推理和主动思考等技能将成为学习的重点。我们应该使用计算
机来增强自己的智能,同时发挥人类独有的创造天赋,让我们的思维插
上计算机的翅膀。
最后,我保证本书一定不是那种枯燥无味的编程入门书,并且在此
之前你一定没有读过如此生动好玩的编程入门书。你可以在茶余饭后阅
读本书,或许蹲在马桶上时也可以看得津津有味。现在就让我们一起走
进计算机编程的神奇世界,探索和发现计算机编程的魔力吧!
[1] 1985年如果乔布斯没有被迫离开苹果,那这一功劳可能将归于苹果的麦金塔计算机。
[2] 被誉为“小乔布斯”的12岁少年托马斯是美国加利福尼亚州洛杉矶市南湾地区
一所学校的6年级学生。当大多数孩子还处在玩计算机或手机游戏的时候,托
马斯就已经是个能开发游戏程序的“软件工程师”了。托马斯不但为苹果公司
的手机操作系统编写了两个游戏程序,还创办了一家软件开发公司。
[3] 吕凯风(VFK)在14岁时以初中生身份获得NOIP(提高组)一等奖,初三
时以全省第一名的成绩入选湖北NOIP省队,高一时获得亚洲太平洋地区信息
学奥林匹克竞赛(APIO2013)国际金牌,高二时获得NOIP全国第二名,现被
保送到清华大学“姚班”。此外,他还独立创作了“对对棋”和“啊哈图”软
件。“对对棋”的启发来源于他的班级同学在课间玩的一个游戏,“啊哈图”则
是他在学习计算几何和图论知识时,为了方便解题和调试做的一个类似于“几
何画板”的软件。第2章
梦想启航
第1节 编程的魔力
从一个神奇的数字说起——2 147 483 647。
2 147 483 647是一个质数(也称为素数,即只能被1和其本身整除
的数)。发现这个质数的人是伟大的数学家欧拉。1722年,他在双目失
明的情况下,以惊人的毅力靠心算证明了2 147 483 647是一个质数,堪
称当时已知的世界上最大的质数,他也因此获得了“数学英雄”的美名。
现在你通过计算机只需要1秒就可以证明2 147 483 647是一个质数。
再来看一个经典的问题——八皇后问题。
如何能够在8×8的国际象棋棋盘上放置8个“皇后”,使得任何一
个“皇后”都无法直接吃掉其他“皇后”?为了达到这个目的,任意两个“皇后”都不能处于同一条横行、纵行或斜线上。下面就是一种解决方
案。没错,你可以自己拿出笔和纸画一画,看看还有没有其他方案。但
是,如果我想知道所有的方案该怎么办?
又轮到计算机出马了,一共有92种不同的解决方案,很棒吧!计算
机只需要1秒,就可以算出所有的解。
再来看一个很流行的益智游戏——数独。
在一个9×9格的大九宫格中有9个3×3的小九宫格,默认在其中填写
了一些数字,现在请在其他空格上填入数字1~9。每个数字在每个小九
宫格内只能出现一次,每个数字在每行每列也只能出现一次。请看下面
这个例子。
我想,你一定很快就找到了一种可行解,可是你知道上面这个数独
一共有多少种不同解吗?答案是99 410种!很难想象吧,计算机找到这些解仍然只需1秒!怎么样,计算机编程是不是很神奇,你甚至可以轻
而易举地在一定范围内去验证“哥德巴赫猜想”。
在接下来的内容里,你将学会如何与计算机对话,如何让计算机进
行数学计算和判断,如何让计算机永不停止地工作,以及如何让计算机
做一些很有意思的程序和游戏。一场有趣的逻辑思维大战即将开始,不
要走开,赶快进入第2节——让计算机开口说话!第2节 让计算机开口说话
为什么会有计算机的出现呢?伟大的人类发明的每一样东西都是为
了帮助我们改善生活。计算机同样是用来帮助我们的工具。想一想,假
如你现在希望让计算机帮助你做一件事情,你首先需要做什么?是不是
要先与计算机进行沟通?那么沟通就需要依赖于一门语言。人与人的沟
通,可以用肢体语言、汉语、英语、法语和德语等。你若要与计算机沟
通,就需要使用计算机能够听懂的语言。我们学习的“C语言”便是计算
机语言的一种,计算机语言除了C语言外,还有C++、Java、C等。C语
言是一门比较简单的计算机语言,更加适合初学者。所有的计算机语言
都是相通的,如果你能够熟练掌握C语言,那么再学习其他语言就会变
得易如反掌。
既然计算机是人类制造出来的帮助人类的工具,显然让它开口说话
并把它所知道的东西告诉我们是非常重要的。
下面我们就来解决第一个问题:如何让计算机开口说话?
回想当年,我们刚刚来到这个世界的时候,说的第一句话是什么?
应该不会是“你好!”、“吃了没?”……这样会把你爸爸妈妈吓坏的!
伴随着“wa wa wa”的一阵哭声,我们来到了这个精彩的世界,现在
我们也让计算机来“哭一次”。这个地方特别说一下,计算机若要
把“它”想说的告诉我们,有两种方法:一种是显示在显示器屏幕上;另
一种是通过喇叭发出声音。就如同我们有话想说时,一种是写在纸上,另一种是用嘴巴说出来。目前让计算机用音箱输出声音还比较麻烦,因
此采用另外一种方法,即用屏幕输出“wa wa wa”。 printf(wa wa wa);
这里有一个生疏单词叫作printf,不要被它吓坏了,目前不用搞清
楚它的本质意义是什么,只要记住它和中文里面的“说”,以及英文里面
的“say”是一个意思即可,它就是控制计算机说话的一个单词而已。在
printf后面紧跟的( ),是不是很像一个嘴巴,把要说的内容“放在”这
个“嘴巴”里。这里还有一处需要注意,在wa wa wa的两边还有,里
面就是计算机需要“说”的内容,这一点是不是很像我们的汉语?最后,一句话结束时要有一个结束的符号。汉语中用句号表示一句话的结束;
英语中用点号表示一句话的结束;计算机语言中用分号表示一个语句的
结束。
注:计算机的每一句话,就是一个语句。
那么,现在如果让你写一个语句,让计算机说“ni hao”,该怎么
办?
printf(ni hao);现在我们让计算机来运行这个语句。这里需要说明一下,仅仅输入
printf(ni hao);,计算机是识别不了的,需要加一个框架。完整的程
序如下:
include
include
int main
{
printf(ni hao);
return 0;
}
这里的
include
include
int main
{
return 0;
}
是所有C语言都必须要有的框架,现在你暂时不需要理解它,知道要有这个即可,以后再来详细地讲它的用途。但是有一点,我们今后写的所
有类似printf的语句都要写在{ }里才有效。
接下来需要让计算机运行我们刚才写的程序。
如果让计算机运行我们写的东西(其实我们写的就是一个C语言程
序),需要一个特殊的软件,它叫作“C语言编译器”
[1]
, “C语言编译
器”有很多种,这里介绍一种比较简单的软件,叫作“啊哈C”
[2]。
首先你需要到www.ahalei.com页面中下载“啊哈C”。下面就要进入
安装步骤啦,安装很简单,一共分7步(见图2-1~图2-7),每一步我都
截取了图片,你只需一口气将这7幅图片全部看完应该就可以。
图2-1 安装“啊哈C”图2-2 开始安装“啊哈C”
图2-3 设置“啊哈C”安装目录图2-4 创建桌面图标和启动栏图标
图2-5 确认安装信息
图2-6 安装正在进行图2-7 “啊哈C”安装成功
“啊哈C”安装完毕后,便可以看到如图2-8所示的“啊哈C”的界面,同时在你的桌面上也会多一个“啊哈C”图标。
图2-8 “啊哈C”的界面
“啊哈C”是一个很人性化的软件,你将会发现“啊哈C”已经帮你将C
语言代码框架的部分写好了。只需要将
printf(ni hao);
这条语句在“啊哈C”中输入就好,如图2-9所示。图2-9 输入printf(ni hao)
细心的同学可能会发现,“啊哈C”默认的C语言框架,比之前说的C
语言框架多了一句话:
system(pause);
这句话是什么意思呢?稍后我们再揭晓。先将这句话删除,删除后
的界面如图2-10所示。
图2-10 删除system(pause)图2-12 编译成
功的提示
好了,同学们请注意,到了最后一步,需要让代码运行起来。现在
只需单击“啊哈C”上的“运行”按钮 。
接下来需要为所写的程序起一个名字,我为这个程序起的名字
是“nihao”,当然你可以随便起名,中英文都可以。比如你可以称之
为“abc”或“我的第一个程序”,或者叫“1”都行,但是你最好别写火星文
或者特殊字符,也不能有英文的点号。将程序的名字输入在如图2-11所
示的文本框中之后再单击“保存”按钮,接下来就是见证奇迹的时刻。
图2-11 给程序起个名字
如果代码没有写错,那你的“啊哈C”将会弹出一
个对话框,提示“恭喜你编译成功”,如图2-12所示。
请同学们注意,在输入代码的时候,一定不要用中
文输入法,这里所有的符号都是英文的,一般也都
是小写。
下面当然就单击“确定”按钮。接下来,请注意:注视你的计算机屏
幕,一秒也不要走开,数秒之后,你将会发现计算机的屏幕上有一
个“黑影”闪过,如果你没有发现这个“黑影”,请重新单击“运行”按钮,并再次注视你的计算机屏幕。
此时,你可能想问,为什么屏幕上会出现这个“黑影”?我们是要在
屏幕上显示“ni hao”才对啊。其实刚才那个“黑影”就是“ni hao”,只不过
计算机的运行速度太快了,在屏幕上显示之后,就立即消失了。那应该
怎么办呢?这需要让计算机暂停一下。
system(pause);
上面这句话就是之前所删除的,其实它的作用就是让计算机“暂停
一下”。将这句话放在printf(ni hao);后面,完整的代码如下:
include
include
int main
{
printf(ni hao);
system(pause);
return 0;
}
好了,再次单击“运行”按钮吧。如果代码没有错误,你将看到如图
2-13所示的界面。图2-13 运行成功的结果
“请按任意键继续…”是system(pause);输出的一个提示,此时
只需按键盘上的任意一个键,这个小黑窗口就会关闭。
如果想让“ni hao”分两行显示,则只需要将printf(ni hao);改为
printf(ni \n hao);这里的“\n”表示让光标“换行”。注意,这里的“\”向
右下角斜,它在键盘上的位置,通常是在回车键的上方。好,赶快尝试
一下吧。运行结果如图2-14所示。
include
include
int main
{
printf(ni\nhao);
system(pause);
return 0;
}
图2-14 分行后的运行结果
当然也可以让“请按任意键继续...”在下一行显示,只需将printf(ni\nhao);改为printf(ni \n hao\n);即可,去试一试吧。
一起来找茬
下面这段代码是让计算机在屏幕上输出hi。其中有3个错误,快来
改正吧!
include
include
int main( )
{
print(hi)
system(pause);
return 0;
}
更进一步,动手试一试
1.尝试让计算机显示下面这些图形。
2.如何让计算机说中文呢?让计算机像下面一样说“早上好”,应
该怎么办?
3.尝试让计算机显示下面这个图形。
A
BC
DEF GHIJ
KLMNO
PQRSTU
V
W
X
Y
Z
这一节,你学到了什么
如何让计算机开口说话,以及让计算机开口说话的语句是什么?第3节 多彩一点
在本章第2节中,我们学习了让计算机开口说话应使用printf语句。
可以发现,计算机“说”出的话都是黑底白字,其实计算机的输出可以是
彩色的,我们一起来看看吧。
注意,此处代码只能在Windows操作系统下编译运行。如果你使用
的是本书推荐的C语言的软件“啊哈C”,那么你的代码肯定可以运行成
功。下面来看看如何让颜色出现。
请尝试输入以下代码并运行,看看会发生什么。
include
include
int main
{
system(color 5); printf(wa wa wa);
system(pause);
return 0 ;
}
运行之后你发现了什么?底色仍然是黑色。但是,文字的颜色已经
变为“紫色”了,奥秘就在下面这行代码中。
system(color 5);
在这句话中,“5”代表“紫色”,你可以尝试一下其他数字,看看分
别是什么颜色。
既然字的颜色可以变,那么背景色是否可以变呢?尝试下面这段代
码:
include
include
int main
{
system(color f5);
printf(wa wa wa);
system(pause);
return 0; }
运行成功后的界面如图2-15所示。
图2-15 运行成功后的界面(此时背景应该为白色,文字颜色应该为紫
色)
上面这段代码在原来的5前面加了一个f,这里的f代表背景色是白
色。
那么设置背景色和文字颜色的方法是,在color后面加上两个一位数
字,第一个数字表示背景色,第二个数字表示文字颜色。如果在color后
面只加了一个一位数字,则表示只设置文字颜色,背景色仍然使用默认
的颜色。
需要说明的是这里的一位数字其实是16进制的,它只能是0、1、2、3、4、5、6、7、8、9、a、b、c、d、e、f中的某一个。
[题外话]“不看,也无伤大雅”
这里学习一个新知识——进制。
在现代数学中,我们通常使用十进制,即使用数字0、1、2、3、4、5、6、7、8、9。9之后的数字便无法表示了,我们的解决方法是:
使用“进位”来表示。例如,由于阿拉伯数字只到9,于是我们便进一
位,当前这位用0表示,便产生了用10来表示“十”。因为是“逢十进一”,所以称为十进制。
而十六进制是“逢十六进一”,即使用0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F来表示。0~9与在十进制时相同,但
是“十”在十六进制时用大写字母A表示,以此类推,“十五”在十六进制
中用大写字母F来表示。F是“十六进制”中的最后一个,因此数字“十
六”就表示不了。于是我们又采用刚才在十进制中表示不了就进一位的
老办法,当前应该用0表示。“十六”在十六进制中表示为10。同理,“二
十七”在十六进制中表示为1B。
在中国古代,很多朝代都是用十六进制作为日常计数的,例如,成
语“半斤八两”的典故来源于十六进制;还有中国古代的算法是上面2颗
珠子,下面5颗珠子。若上面每颗珠子代表数字5,下面每颗珠子代表数
字1,那么每位的最大计数值是15, 15正是十六进制的最大基数。当使用
算盘计数遇到大于15的时候,我们就需要在算盘上“进位”了。
其实在我们现代的日常生活中,也不都是“十进制”,例如,60秒为
1分钟,60分钟为1小时,就是用的六十进制。
一起来找茬
下面这段代码是让计算机在屏幕上输出绿底白字的hi。其中有4个
错误,快来改正吧!
include
include
int main( )
{ system(color f2)
print(hi);
system(pause);
return 0;
}
更进一步,动手试一试
1.尝试让计算机打印这个小飞机图案(绿底白字)。
2.尝试让计算机打印这个小队旗图案(白底红字)。
A
I I
I
I
I
I
I
I
I
这一节,你学到了什么
让计算机打印出来的字符有不同颜色的语句是什么?第4节 让计算机做加法
通过之前的学习,我们了解到让计算机说话是用“printf”,运
用“printf”就可以让计算机想说什么就说什么了。在学会了“说话”之后,我们来看如何让计算机做数学运算,首先我们先让计算机做“加法”,就
先算1+2吧。
回想一下小时候爸爸妈妈是如何教我们算1+2的呢?
妈妈说:“左手给你一个苹果,右手给你两个苹果,现在一共有几
个苹果?”我们迅速地思考了一下,脱口而出:“3个苹果”。没错!我们
首先用大脑记住左手有几个苹果,再用大脑记住右手有几个苹果,妈妈
问一共有几个时,我们的大脑进行了非常快速的计算,将刚才记住的两
个数进行相加,得到结果,最后将计算出的结果说出来。仔细分析一
下,大致分为以下5个步骤。
(1)用大脑记住左手的苹果数量;
(2)用大脑记住右手的苹果数量;
(3)我们的大脑将两个数字进行相加;
(4)得到结果;
(5)将结果输出。
在这期间,我们大脑一共进行了以下4个动作。
(1)两次输入:分别是记录左手和右手中苹果的数量;(2)存储了3个值:分别是记录左手和右手中苹果的数量和相加的
结果;
(3)进行了一次计算:相加;
(4)进行了一次输出:把相加的结果输出。
如何让计算机做加法呢?同样也需要以上几个步骤。
首先来解决如何让计算机像我们的大脑一样记住一个数字。
其实计算机的大脑就像一个“摩天大厦”,有很多一间一间的“小房
子”,计算机就把需要记住的数放在“小房子”里面,一个“小房子”里只
能放一个数,这样计算机就可以记住很多数。好,我们来看一看,具体
怎样操作。
“=”赋值符号的作用就相当于一只手,把数字放到小房子中。
int a, b, c;这句话就代表在计算机的“摩天大厦”中申请三间分别叫作a、b和c
的小房子(注意:int和a之间有一个空格,a、b与c之间分别用逗号隔
开,末尾有一个分号表示结束)。
接下来,我们让小房子a和小房子b分别去记录两个数字1和2,具体
如下:
a=1;
b=2;
说明:此处有一个“=”,这可不是等于号,它叫作给予号(也称为
赋值号),类似于一个箭头“←”,意思是把“=”右边的内容赋给“=”左
边。例如,把1这个数给小房子a,这样一来计算机就知道小房子a里面
存储的是数字1了。
然后,把小房子a和小房子b里面的数相加,再将其结果放到小房子
c中。
c=a+b;
计算机会将这个式子分两步执行:第一步先将a+b算出来,第二步
再将a+b的值赋给“=”右边的c。至此,就差不多完成了,我们总结一下:
int a, b, c;
a=1;
b=2;
c=a+b;
很多同学是不是以为,现在已经全部完成了?你忘记了最重要的一
步,先别急着往下看,想一想忘记了什么?
啊!你忘记了把答案输出。
想一想如果妈妈问你一加二等于多少时,你说:“我算出来了,但
是不想告诉你!”的话,估计少不了挨一顿揍了,不要啊!
让我们回忆一下,如何让计算机把结果输出。
对,使用printf语句。那怎么把小房子c里面存储的数输出呢?根据
本章第2节学到的知识,只要把要输出的内容放在双引号里面就可以
了,代码如下:
printf(c);
猜一猜此时计算机会输出什么?对,无情地输出了一个c。
那怎样输出c里面的值呢?
这时我们要让另外一个角色出场了。
%d
“%d”其实是一个“讨债的”,或者也可以说是“要饭的”。它的专职工
作就是向别人“要钱”!那我们应该怎么使用它呢?
printf(%d, c);将“%d”放在双引号之间,把小房子c放在双引号后面,并且用逗号
隔开。
这时printf发现双引号里面是个“讨债的”,就知道此时需要输出一个
具体的数值,而不是符号,就会向双引号后面的小房子c索取具体的数
值了。
好了,最后加上C语言的代码框架,计算机进行加法运算的完整代
码如下:
include
include
int main
{
int a, b, c;
a=1;
b=2;
c=a+b;
printf(%d, c);
system(pause);
return 0;
}
现在赶紧去试一试吧。
一起来找茬下面这段代码是让计算机计算321-123的结果。其中有7个错误,快
来改正吧!
include
include
int mian( )
{
int a, b, c;
a=321
b=123
c=b-a
print(%d, c)
system(pause);
return 0;
}
更进一步,动手试一试
1.如果要进行3个数相加的运算,该怎样做呢?例如:5+3+1=?
我们可以把上面的程序进行简单地改变,申请4个小房子分别叫作
a、b、c和d。用a、b、c分别存放3个加数,用d存放它们的和。代码如
下:
include
int main
{
int a, b, c, d;
a=5;
b=3;
c=1;
d=a+b+c;
printf(%d, d);
system(pause);
return 0;
}
如果要10个数相加岂不是得定义11个小房子?那也太麻烦了!对,目前我们只能这样,但是在后面的学习中,会有更为简单的方法。
2.用计算机算出下面3个算式。
123456789+43214321
70788712
321(123456+54321)
这一节,你学到了什么1.如何申请一个小房子来存储数值?
2.如何用printf输出小房子中的数值?第5节 数字的家——变量
从本章第4节中,我们了解到计算机使用一个个的小房子来记住数
字。计算机有很多不同种类的小房子。
int a;
代表向计算机申请一个小房子,用来存放数值,小房子的名字叫作a。
int和a之间有一个空格,a的末尾有一个分号,表示这句话结束。
如果要申请多个小房子,则要在a后面继续加上b和c,用逗号分
开。例如:
int a, b, c;
这里有一个小问题,就是给申请的“小房子”起名字。原则上可以随
便起:可以是单独的字母,如a、b或x;可以是多个字母的组合,如
aaa、abc或book;也可以是字母和数字的组合,如a1或abc123。当然也
有一些限制,如果你想知道,请看附录A。到这里,可能还有很多同学想问,int究竟是什么意思呢?
其实,int控制小房子用来存放的数的类型,表示你目前申请的小房
子只能存放整数。
int是英文单词integer(整数)的缩写。
如果要放小数该怎么办?
我们用float来申请一个小房子,用来存放小数,形式如下:
float a;
这样,小房子a就可以用来存放小数了,例如: float a;
a=1.5;
printf(%f, a);
就表示申请一个用来存放小数的小房子a,里面存放了小数1.5。
注意:在C语言中,小数称作浮点数,用float表示。
之前在用printf语句输出整数时,使用的是“%d”。此时需要输出小
数,要用“%f”。
好了,我们来总结一下,这里的“小房子”在我们C语言的专业术语
中称为变量。int和float说明小房子是用来存放何种类型的数,我们这里
将其称为“变量类型”或者“数据类型”。
类似int a;或者float a;的形式,我们称作“定义变量”,它们的语法
格式如下:
【口语】 小房子的类型 小房子的名称 , 小房子的名称 ;
【术语】 变量的类型 变量的名称 , 变量的名称 ;
【代码】 int a , b ;
现在我们知道,int a;表示申请一个用来存放一个整数的小房子a,即定义一个整型变量a来存放整数;而float a;则表示申请一个用来存放
一个小数的小房子a,即定义一个浮点型(实型)变量a来存放浮点数(小数)。
再来看另外一个有趣的问题,代码如下:
include
include
int main
{
int a;
a=1;
a=2;
printf(%d, a);
system(pause);
return 0;
}
请问计算机执行完上面的代码后,将会输出1还是2?尝试过后你会发现,计算机显示的是2,也就是说小房子a中的值最
终为2。通过观察代码可以发现,我们首先将1放入小房子a中,紧接着
又将2放入小房子a中,那么请问原来小房子中的1去哪里了呢?答案
是,被新来的2给覆盖了并且已经消失了。也就是说,小房子a中有且仅
能存放一个值,如果多次给小房子a赋值,小房子a中存放的将始终是最
后一次赋的值。例如:
include
include
int main
{
int a;
a=1;
a=2;
a=3; a=4;
a=5;
a=6;
printf(%d, a);
system(pause);
return 0;
}
计算机运行完上面这段代码后最终将输出6。也就是说小房子a中的
值最终为6,前5次的赋值全部被覆盖了。
一个更有意思的问题来了,请继续看下面的代码:
include
include
int main
{
int a;
a=7;
a=a+1;
printf(%d, a);
system(pause);
return 0; }
计算机运行完上面这段代码后最终将输出8。也就是说小房子a中的
值最终为8。计算机在执行完a=7这句话后,小房子a中存储的值为7,之
后计算机又紧接着运行了a=a+1。运行完a=a+1后,小房子a中的值就变
为8了。也就是说a=a+1的作用是把小房子a中的值在原来的基础上增加
1,我们来分析一下这句话。
对于a=a+1计算机分两步执行,这句话中有两个操作符,第一个
是“+”,另一个是“=”(赋值号),因为“+”的优先级要比“=”高,因此计
算机先执行a+1,此时小房子a中的值仍然为7,所以a+1的值为8。紧接
着计算机就会执行赋值语句,将计算出来的值8再赋值给a,此时a的值
就更新为8。
好啦,猜猜下面的程序,计算机最终会输出多少?
include
include
int main
{ int a;
a=10;
a=aa;
printf(%d, a);
system(pause);
return 0;
}
尝试过了吗?想一想为什么a最终的值为100。
注:所有运算符的优先级详见附录B。
一起来找茬
下面这段代码是让计算机计算1.2×1.5的值。其中有5个错误,快来
改正吧!
include
include
int main( )
{
int a, b, c
a=1.2;
b=1.5;
c=ab; print(%d, c)
system(pause);
return 0;
}
更进一步,动手试一试
1.进行两个小数的加法运算,例如:5.2+3.1=?代码如下:
include
include
int main
{
float a, b, c;
a=5.2;
b=3.1;
c=a+b;
printf(%f, c);
system(pause);
return 0;
}
请注意,之前在printf语句中输出整型变量的值时,使用的
是“%d”,此时需要输出的是实型变量的值,因此要用“%f”。2.通过计算机把下面3个式子算出来吧!
1.2+2.3+3.4+4.5
1.1100
10.1(1010)
这一节,你学到了什么
1.如何定义一个用来存放小数的变量?
2.如何让一个小房子a(变量a)中的值增加1?第6节 数据输出——我说咋地就咋地
在本章第4节中,我们已经学会了如何让计算机做加法运算,但是
计算机在输出的时候,只显示了一个结果,这样不够人性化。如果能将
整个算术等式输出就好了,例如:1+2=3。那应该怎么写呢?
新的代码:
include
include
int main
{
int a, b, c;
a=1;
b=2;
c=a+b;
printf(%d+%d=%d, a, b, c);
system(pause);
return 0;
}
原来的代码: include
include
int main
{
int a, b, c;
a=1;
b=2;
c=a+b;
printf(%d, c);
system(pause);
return 0;
}
仔细阅读这些代码你会发现,新的代码和原来的代码只有一个
printf语句不一样。好,我们现在来仔细分析一下printf(%d+%d=%d,a, b, c);。
printf语句只会输出双引号里面的部分,双引号之外的部分只是对
双引号内的部分起到补充说明的作用。
例如,printf(%d+%d=%d, a, b, c);这行语句,双引号里面的部
分是%d+%d=%d,那么计算机在输出的时候就严格按照%d+%d=%d来
执行,输出的形式必然是%d+%d=%d。
当计算机遇到第1个“%d”时,知道“讨债的”来了,于是它便向双引
号后面的变量讨债,排在第1个的是a,那么就向a讨债。a的值是1,于是第1个“%d”得到的便是1。
第2个是“+”,那么照样输出。
第3个又是“%d”,同样到双引号的后面去讨债,因为排在第1个的a
已经被讨过债了,因此向排在第2个的b讨债。b的值是2,于是这
个“%d”得到的便是2。
第4个是“=”,照样输出。
第5个还是“%d”,同样到双引号的后面去讨债,因为排在第1个的a
和排在第2个的b已经被讨过债了,因此向排在第3个的c讨债。c的值是
3,于是最后这个“%d”得到的便是3。
最后输出的内容是1+2=3。
请注意,通常双引号内部“%d”的个数,和后面变量的个数是相等
的,它们是一一对应的。如果没有一一对应,从C语言的语法角度来讲
是没有错误的,但这不合常理,最好避免这样的情况出现。
一起来找茬
下面这段代码是让计算机分别计算10-5与10+5的值,并分两行显
示,第一行显示差,第二行显示和。其中有3个错误,快来改正吧!
inlcude
include
int mian( )
{ int a, b, c;
a=10;
b=5;
c=a-b;
printf(%dn, c);
c=a+b;
printf(%d, c);
system(pause);
return 0;
}
更进一步,动手试一试
指定两个数,输出这两个数的和、差、积与商。例如,指定两个数
9和3,输出9+3=12、9-3=6、9×3=27、93=3。
include
include
int main
{
int a, b, c;
a=9;
b=3;
c=a+b;
printf(%d+%d=%d\n, a, b, c); c=a-b;
printf(%d-%d=%d\n, a, b, c);
c=ab;
printf(%d%d=%d\n, a, b, c);
c=ab;
printf(%d%d=%d\n, a, b, c);
system(pause);
return 0;
}第7节 数据输入——我说算啥就算啥
我们已经学会了如何做一个加法计算器,但是目前的加法计算器还
不够人性化,每次计算两个数的和时,都需要修改C语言代码,然后重
新编译运行才能得到结果,很显然这样的加法计算器是不会有人喜欢用
的,那如何让使用者自己任意输入两个数就可以直接得到结果呢?
我们知道,让计算机说话用printf,那么让计算机学会听用什么
呢?scanf将会把听到的内容告诉你的程序。
计算机“说话”的过程,我们称为“输出”,计算机“听”的过程,我们
则称为“读入”。好,下面来看看,计算机是如何读入的。
scanf的语法与printf语法类似,例如,我们要从键盘读入一个数,放在小房子a中,代码如下:
scanf(%d, a);
你瞧,与输出小房子a的语句printf(%d, a);是差不多的,只有
以下两处不同。
第一处是:读入是使用scanf这个词,而输出是使用printf这个词。
第二处是:读入比输出在a前面多了一个“”符号。
“”符号我们称为“取地址符”,简称“取址符”。它的作用是得到小房子a的地址。
scanf(%d, a);这句话可以理解为:我们要从外界向计算机的
内部传送一个数值,并需要将这个值存放到指定的“编号为a”的盒子
中。这样我们就需要知道小盒子a在计算机内部的地址。就像邮递员送
信一样,要传送的数据就是信件,小盒子a就是信箱编号。
那你可能要问,为什么在读入的时候要得到小房子a的地址,而输
出的时候却不需要呢?在读入数据的时候,计算机需要把读入的值存放
在小房子a(也就是变量a)中,此时需要知道你指定的这个小房子a的
地址,才能把值准确地放进其中;但是在输出的时候,值已经在小房子
a中了,因此可以直接输出到屏幕上。
打一个比方:假如你要去一个教室上课,那么在上课之前你需要知
道这个教室的地址,这样你才能去;但是如果下课了,你需要走出这个
教室,因为此时你已经在教室中,所以就不再需要这个教室的地址。
如果要从键盘读入两个数,分别给小房子a和小房子b呢?这里有以
下两种写法。第一种:
scanf(%d, a);
scanf(%d, b);
第二种:
scanf(%d%d, a, b);
第二种的写法较为简便,两个“%d”之间不需要空
格,“a”和“b”之间用逗号隔开。
从键盘读入两个数,输出这两个数的和的完整代码如下:
include
include
int main
{
int a, b, c;
scanf(%d%d, a, b);
c=a+b;
printf(%d+%d=%d, a, b, c); system(pause);
return 0;
}
好了,总结一下,在C语言中printf是计算机“说出去的”,也就是计
算机需要告诉你的;而scanf是计算机“听进来的”,也就是你需要告诉计
算机的。
接下来,我们要让“加法计算器”更加人性化——带有提示的读入和
输出。
include
include
int main
{
int a, b, c;
printf(这是一个加法计算器,欢迎您使用\n);
printf(--------------------------------\n);
printf(请输入第一个数(输入完毕后请按回车)\n);
scanf(%d, a);
printf(请输入第二个数(输入完毕后请按回车)\n);
scanf(%d, b);
c=a+b;
printf(它们的和是%d, c); system(pause);
return 0;
}
一起来找茬
下面这段代码是从键盘读入两个整数,并输出它们的和。其中有6
个错误,快来改正吧!
include
include
int main( )
{
int a, b, c;
scanf(%d, a, b)
c=a+b
printf(%dn, c);
system(pause);
return 0;
}
更进一步,动手试一试
从键盘读入两个数,并输出这个两个数的和、差、积与商。 include
include
int main
{
int a, b, c;
scanf(%d%d, a, b);
c=a+b;
printf(%d+%d=%d\n, a, b, c);
c=a-b;
printf(%d-%d=%d\n, a, b, c);
c=ab;
printf(%d%d=%d\n, a, b, c);
c=ab;
printf(%d%d=%d\n, a, b, c);
system(pause);
return 0;
}
请注意除法运算。在C语言中,当除号“”左右两边都是整数时,商
也只有整数部分。例如,53的商是1,23的商是0。
这一节,你学到了什么
如何从键盘读入一个数到小房子中?第8节 究竟有多少种小房子
在之前的几节中,我们已经知道计算机如果想“记住”某个值,就必
须在它的大脑“摩天大厦”中,申请一种小房子。例如:
int a, b, c ;
即申请3种小房子分别叫作a、b和c。这3种小房子只能用来存放整数
(整型数据)。
再例如:
float a, b, c ;
即申请3种小房子a、b和c。这三种小房子只能用来存放小数(浮点型数
据)。
也就是说在计算机中,不同类型的数据需要相应类型的小房子来存
储。那么计算机一共有多少种类型的小房子呢?我们来列举几种最常用
的,如表2-1所示。
表2-1 C语言常用的数据类型
数据类型名称 用来存放哪种数据 数据范围
int 用来存放整数 ?2147483648~
2147483647
float 用来存放浮点数 ±1.18×10?38 ~
±3.4×1038
double
用来存放极大和极小
的浮点数
±2.23×10?308 ~
±1.80×10308
char 用来存放字符 256种字符
double也是用来存放小数的,那float和double有什么区别呢?
请观察下面两段代码。
代码1:
include
include
{
float a;
a=3.1415926535897932;
printf(%.15f, a);
system(pause);
return 0;
}
代码2:
include
include
int main
{
double a;
a=3.1415926535897932;
printf(%.15f, a);
system(pause);
return 0;
}通过观察,我们发现代码1和代码2的不同之处只有一点。代码1中
是用float来申请小房子a,代码2中却是用double来申请小房子a。在输出
时,两段代码中printf里面所用的占位符都是“%f”。代码中“%”和“f”之
间的“.15”表示保留小数点后15位(四舍五入)。这里特别说明一下,在
用scanf读入double类型数据时所用的占位符是“%lf”(注意此处不是数字
1而是字母l)而不是“%f”。
它们的运行结果分别如图2-16和图2-17所示。
图2-16 代码1运行的结果
图2-17 代码2运行的结果
怎么样,发现问题了吧?!代码1运行后输出的是
3.141592741012573,显然从小数点后第7位开始就不对了,而代码2运
行后输出的是3.141592653589793,完全正确。因此我们可以发现double
可以比float表示得更精确。另外float和double表示的数的大小范围也不
同,请大家自己去尝试。
在表2-1中我们发现有一个新的数据类型char,用char申请的小房子
是用来存放字符的。 include
include
int main
{
char a;
scanf(%c, a);
printf(你刚才输入的字符是%c, a);
system(pause);
return 0;
}
我们输入一个字符x后按回车键,结果如图2-18所示,当然你也可
以尝试一下别的字符。
图2-18 输入一个字符并输出
想一想,对于上面这段代码,如果此时你输入的不是一个字母,而是一串字母,计算机会输出什么呢?很抱歉!计算机只会输出你输入的
第一个字母。
有的同学可能要问,如果想存储一大串字符该怎么办呢?不要着
急,我们将在后续章节中介绍如何存储一个字符串。
一起来找茬
下面这段代码是让计算机读入一个字符并把这个字符原样输出。其
中有3个错误,快来改正吧!
include
include
int main( )
{
char a;
scanf(%c, c);
printf(%d, c);
system(pause);
return 0;
}
更进一步,动手试一试
从键盘读入一个字符,输出这个字符后面的一个字符。例如,输入
字符a,输出字符b。 include
include
int main
{
char a;
scanf(%c, a);
printf(后面的一个字符是%c, a+1);
system(pause);
return 0;
}
思考一下,为什么一个字符后面的字符就是该字符加1呢?
这一节,你学到了什么
1.double是什么类型?
2.如何存储一个字符?第9节 拨开云雾见月明
通过前面的学习,我们已经知道计算机如果想“记住”某个值,就必
须在计算机的大脑“摩天大厦”中,申请一个小房子。例如,之前我们需
要计算任意两个数的和,程序是这样写的:
include
include
int main
{
int a, b, c;
scanf(%d%d, a, b) ;
c=a+b;
printf(%d+%d=%d, a, b, c);
system(pause);
return 0;
}
其实这个小房子c是多余的,可以直接写成:
printf(%d+%d=%d, a, b, a+b);代码如下:
include
include
int main
{
int a, b;
scanf(%d%d, a, b);
printf(%d+%d=%d, a, b, a+b);
system(pause);
return 0;
}
当然,如果你只想计算4+5的值,可以更简单:
include
include
int main
{
printf(%d,4+5);
system(pause);
return 0;
}如果希望计算4+(6-3)×7的值,可以直接这样写:
include
include
int main
{
printf(%d,4+(6-3)7);
system(pause);
return 0;
}第10节 逻辑挑战1:交换小房子中的数
假如在计算机中我们已经有两个小房子(变量)分别叫作a和b,并
且它们都已经有了一个初始值,但是现在希望将变量a和变量b中的值交
换,该怎么办呢?
先来看一段代码:
include
include
int main
{
int a, b;
scanf(%d%d, a, b);
printf(%d %d, a, b);
system(pause);
return 0;
}
上面这段代码是从键盘读入两个数,然后将这两个数输出。例如,如果你输入的是5和6,那么输出的也是5和6。可是,我们现在的需求是
将变量a和b中的数交换后输出,也就是说如果读入的是5和6,那么输出
的应该是6和5才对。应该怎么办呢?来看一段代码: include
include
int main
{
int a, b;
scanf(%d%d, a, b);
a=b;
b=a;
printf(%d %d, a, b);
system(pause);
return 0;
}
上面的代码企图通过a=b; b=a;语句将变量a和变量b中的值交换,如果你已经运行过上面的代码,就会发现交换并没有成功,变量b的值
没有变化,反而是变量a的值变成了变量b的值,这是为什么呢?
我们来模拟一下计算机运行的过程。
int a, b;指计算机会申请两个小房子(变量),分别叫作a和b。
scanf(%d%d, a, b);指从键盘读入两个数,分别赋值给变量
a和变量b。假如我们从键盘读入的两个数分别是5和6,那么变量a中的
值就是5,变量b中的值就是6。a=b;指计算机会将变量b中的值给变量a,变量a中的值也变成了
6。变量a中原来的5被新来的6给覆盖了,也就是说原来变量a中的5丢失
了。
b=a;指计算机会将此时变量a中的值给变量b,此时变量a中的已经
是6了,所以变量b的值其实还是6。
最终,变量a和变量b中的值都为6。那我们要怎么改呢?通过上面
我们对计算执行过程的模拟,我们发现,主要问题是:计算机在执行完
a=b;这个语句后,原先变量a中的值被弄丢失了。那我们只要在执行
a=b;这个语句之前,先将变量a的值保存在另外一个临时变量中就可以
了,例如,保存在变量t中。代码如下:
t=a;
a=b;
b=t;
先将变量a中的值给变量t,变量t中的值就变为5(假如原来变量a中是5,变量b中是6),然后再将变量b中的值给变量a,变量a中的值就变
为6,最后将变量t中的值给变量b,此时变量b中的值就变为5。成功!
通过一个变量t作为中转站,我们已经成功地将变量a和变量b中的值进
行了交换。
完整的代码如下:
include
include
int main
{
int a, b, t;
scanf(%d%d, a, b); t=a;
a=b;
b=t;
printf(%d %d, a, b);
system(pause);
return 0;
}
一起来找茬
下面这段代码是让计算机读入两个整数,分别放到变量a和变量b
中,并将变量a和变量b中的数交换。其中有两个错误,快来改正吧!
include
include
int main( )
{
int a, b;
scanf(%d%d, a, b);
t=a;
b=a;
b=t;
printf(%d %d, a, b);
system(pause); return 0;
}
更进一步,动手试一试
在本节我们介绍了如何将两个变量的值进行交换,方法是增加一个
临时变量来作为中转。你有没有想过,在不增加任何新变量的情况下是
否也可以完成呢?来看看下面的代码吧。
include
include
int main
{
int a, b;
scanf(%d%d, a, b);
a=b-a;
b=b-a;
a=b+a;
printf(%d %d, a, b);
system(pause);
return 0;
}
请思考一下,为什么通过a=b-a; b=b-a; a=b+a;也可以将变量a与变量b中的值交换呢?第11节 天啊!这怎么能看懂
先来看一段代码:
include
nt a, b, c;
scanf(%d%d, a, b); c=a+b; printf(%d, c); system(pause); return 0; }
怎么样,你看懂了吗?这段代码的意思其实就是从键盘读入两个整
数并且输出它们的和。不错,上面的这段代码从语法角度来讲没有任何
错误,编译器也可以对其编译运行,也就是说计算机可以准确无误
地“认识”这段代码,但是我们会看得比较吃力。一段优秀的代码,不仅
仅要让计算机“看懂”,也要让我们可以看懂。再来看看下面这段代码是
不是更容易让人们理解呢。
include
include
int main
{
int a, b, c;
scanf(%d%d, a, b);
c=a+b; printf(%d, c);
system(pause);
return 0;
}
这里需要指出的是,这里的int a, b, c;前面与上一行相比,多了4个
空格。其实我在输入代码的时候,并不是输入4个空格,而是输入了一
个Tab
[3]。使用Tab来调整你的代码格式,是一名优秀的程序员必须要
养成的习惯。
include
include
int main
{
int a;
a=1; 将变量a赋初始值
printf(%d, a);
system(pause);
return 0;
}
在上面的代码中,“”表示注释,它将告诉编译器从“”开始一直到
本行末尾的内容都是没有用的。注释的主要作用是给程序员看的,通常用来对一行代码进行解释说明或备注。
include
include
int main
{
int a;
a=1; 将变量a赋初始值
printf(%d, a);
system(pause);
return 0;
}
上面的代码有两处注释,第1处注释我们讲过,主要是用来解释说
明本行代码的作用。第2处的注释是将本来有用的代码printf(%d,a);给注释掉,可以理解为“临时性删除”,就是告诉编译器
printf(%d, a);没有用。你可能要问为什么不直接删除呢?因为有
时我们并不希望真正删除,只是暂时不需要,以后说不定还要再用,如
果删除了就找不回来了,如果我们合理地利用“”进行注释,那么计算
机就不会运行这句话,而是理解这句话是给程序员看的。如果我们以后
又要使用这句话,只需将这句话前面的“”去掉就可以了,这样是不是
很方便呢。
有效地在代码中添加注释,可以让你的程序更具可读性。
“”只能注释到本行末尾,如果要注释多行,就要在每行上写“”。其实注释还有另外一种,以“”开始一直到“”结束,中间的内容编译
器都不会理睬。使用“ ”的好处就是它可以跨行。
例如,下面两段代码的效果是相同的:
include
include
int main
{
int a;
a=1;
a=2;
a=3;
a=4;
a=5;
printf(%d, a);
system(pause);
return 0;
}
include
include
int main
{
int a; a=1;
a=2;
a=3;
a=4;
a=5;
printf(%d, a);
system(pause);
return 0;
}
上面两段代码中变量a的值最后还是1。
再来看一段代码:
int a;
a=1;
上面这段代码是定义一个整型变量(小房子)a,并且给变量a赋一
个初始值1。我们以后会经常遇到在定义一个变量(小房子)之后,给
其赋初始值的情况,可以简写如下:
int a=1;多个变量也类似:
int a=1, b=2, c=3;
浮点型和字符型也类似:
float a=1.1;
char c='x';
需要注意的是,在给浮点型变量赋初始值的时候必须是一个小数,也就是说必须有小数点。在给字符型变量赋初始值的时候,字符两边需
要加单引号,记住是单引号,不是双引号。在上面的代码中我们希望把
字符x赋值给字符变量c,所以我们在字符x的左右两边加上了单引号。
编程也是一门艺术,需要追求简洁、高效而且优美的代码,一名优
秀的程序员往往也是一名艺术家。
[1] “C语言编译器”的作用是把我们写的程序“变”成一个“exe”,即可以让计算机
直接运行的程序。这个“变”的专业术语称为“编译”。当你的程序“变”成一
个“exe”后,你就可以脱离“C语言编译器”直接运行你的程序。此时你就可以
把你写的“exe”发给你的朋友和同学,让他们一起来使用你编写的程序。这里
的程序从某种意义上来讲也可以称为“软件”。[2] “啊哈C”是一款非常容易上手的C语言编程软件,使用的是GCC内核。界面
简洁可爱,支持语法高亮、代码折叠、编译错误提示等。操作方便,上手
快,特别适合C语言入门的初学者使用。
[3] Tab表示一个制表符,在编程中用Tab来代替空格是一个很好的习惯,可以让
你的代码看起来更美。Tab键在字母Q键的左边,赶快试一试吧。第3章
较量才刚刚开始
第1节 大于、小于还是相等
和我们一样,计算机也可以判断大小。假如你告诉计算机有a和b两
个数,计算机除了可以告诉你这两个数的和、差、积和商,还可以告诉
你谁大、谁小。现在我们就来瞧瞧计算机是如何判断谁大谁小的。
在此之前,我们需要先说明一下在计算机中用来判断两个数的关系
的符号,即关系运算符,一共有如下6个:
== 相等
> 大于
< 小于 >= 大于等于
<= 小于等于!= 不等于
需要特别注意的是,在计算机中,一个等于号“=”表示赋值,两个
等于号“==”表示判断是否相等,同学们在编写代码的时候千万不要写
错。一个感叹号加一个等于号“!=”表示“不等于”。此外计算机只有大于
等于号“>=”和小于等于号“<=”,没有等于大于号和等于小于号,即不存
在“=>”和“=<”,这一点请一定要注意。
例如,以下写法是正确的:
5>=4
7! =8
a
c==d
以下写法是错误的:
4=<7
8=>3第2节 判断正数
假如你现在想让计算机判断一个整数是否为正数,如果是则显示
yes,不是则什么都不显示,应该怎么办呢?
下面方框中的内容,就是让计算机判断一个数是否为正数的“算
法”。
首先,计算机需要有一个小房子(即变量)来存储这个数。
然后,你需要告诉计算机这个数是什么?
接下来,计算机需要判断这个数是否为正数。
最后输出计算机的判断结果。
算法其实就是解决问题的方法(千万要被这个专业名词给吓住
了)。
我们每遇到一个问题,首先需要思考的是解决这个问题的算法,也
就是解决这个问题的方法和步骤。像上面一样一步一步地列出来,然后
再将算法的每一步通过C语言来实现。
下面,我们就用C语言来实现上面的算法。
首先,计算机需要有一个小房子(即变量)来存储这个数。可以用int a;来申请一个名字叫作a的小房子(即变量),来存
储需要判断的数。
然后,需要告诉计算机这个数是什么?
可以用scanf(%d, a);来读入一个数并将这个数存储在小房
子a中。
接下来,计算机需要判断这个数是否为正数。
这可怎么办?不要紧,待会儿再来分析。
最后输出计算机的判断结果。
如果是正数则显示yes,使用printf(yes);。
好,现在我们集中精力来解决刚才的第3步——判断存放在小房子a
中的数是否为正数。
想一想,我们是如何判断一个数是否为正数的?要从正数的定义出发,如果一个数大于0,就是正数。好,计算机也是这么想的,哈哈。
如果a大于0,则显示yes。
接下来,尝试用C语言来实现。
其中“如果”在C语言中用if来表示。代码如下:
if (a>0) { printf(yes); }
因为当a>0成立时候,这里只需要执行一条语句,此时{ }也可以省
略不写,如下:
if (a>0) printf(yes);
要注意的是,当且仅当条件成立时 只需要执行一条语句 ? ? ? ? ? ? ? ? ?
才能省略{
}。 为什么这么说?不要着急,等你看完本章的第七节就知道了。
当然,如果你觉得写在同一行很不爽,写成两行也是可以的:
if (a>0)
printf(yes);更好的写法应该是在printf(yes);前面空4个空格或者空1个
Tab,表示printf(yes);是if (a>0)的一部分,当a>0条件成立时才
执行printf(yes);这条语句。
if (a>0)
printf(yes);
完整的代码如下:
include
include
int main( )
{
int a;
scanf(%d, a); if (a>0) printf(yes);
system(pause);
return 0;
}
好了,赶快试一试吧。
假如我希望输入正数时显示yes,输入负数或0时显示no,应该怎么
办呢?
若要实现上述要求,第3部分应改为:
如果(a大于0)显示yes
如果(a小于等于0)显示no
对应的C语言代码是:
if (a>0) printf(yes);
if (a<=0) printf(no);
完整的代码如下: include
include
int main( )
{
int a;
scanf(%d, a) ;
if (a>0) printf(yes);
if (a<=0) printf(no);
system(pause);
return 0;
}
此外,if (a>0) printf(yes);
这句话更加完美的写法是:
if (a>0)
{
printf(yes);
}所以判断正数的代码更好的写法是:
include
include
int main( )
{
int a;
scanf(%d, a) ;
if (a>0)
{
printf(yes);
}
if (a<=0)
{
printf(no);
}
system(pause);
return 0;
}
最后,需要注意的是if ( )后面是没有分号的,像下面这些写法都
是不对的!
if (a>0) ; printf(yes); if (a>0);
printf(yes);
if (a>0);
{
printf(yes);
}
至于为什么呢?这句话的意思是“如果什么成立,就做什么”,很明
显“如果什么成立”这句话只说了一半,所以if ( )后面不能加分号,需
要特别注意!
if语句的语法格式为:
if (条件)
{
语句1;
语句2;
语句 ……
}
if后面一对圆括号中的内容是一个关系表达式,当表达式成立时执
行后面花括号中的语句。好了,赶快试一试吧。
一起来找茬
下面这段代码用来判断一个数是否小于或等于100,如果是则输出
yes。其中有3个错误,快来改正吧!
include
include
int main( )
{
int a;
scanf(%d, a) ;
if (a<100) ; printf(yes);
system(pause);
return 0;
}
更进一步,动手试一试
假如我希望输入正数时显示yes,输入负数时显示no,输入0时显示
0,应该怎么办呢?
这一节,你学到了什么
if语句的基本格式是什么?第3节 偶数判断
通过对本章第2节内容的学习,我们知道计算机是通过if语句来进行
判断的。现在来尝试一下判断一个数是否为偶数。首先,先写出算法。
(1)计算机需要有一个小房子(即变量)来存储这个数。
(2)你需要告诉计算机这个数是什么?
(3)计算机需要判断这个数是否为偶数。
(4)计算机输出判断结果。
其中,在第3步你可能遇到一点小麻烦。我们想一下,什么是偶数
呢?偶数就是能够被2整除的数,也就是说如果一个数除以2的余数为
0,那么这个数就是偶数。
那么我们现在只需要判断这个数除以2的余数是不是0,即:
如果a除以2的余数与0相等,则输出yes;
如果a除以2的余数与0不相等,则输出no。
C语言中求余数的运算符号是“%”,所以判断一个数是否为偶数的C
语言代码就是:完整的C语言代码如下:
include
include
int main( )
{
int a;
scanf(%d, a) ;
if (a%2==0)
{
printf(yes);
}
if (a%2! =0)
{
printf(no);
}
system(pause);
return 0;
}
好了,应该尝试一下了。 一起来找茬
下面这段代码用来判断一个数是否是7的倍数。其中有4个错误,快
来改正吧!
include
include
int main
{
int a;
scanf(%d%d, a) ;
if a%7=0
{
printf(yes);
}
system(pause);
return 0;
}
更进一步,动手试一试
如何判断一个数的末尾是不是0呢?如果是则输出yes(例如
120),不是则输出no(例如1 234)。第4节 神器else
在本章第3节中,我们使用了两个if语句让计算机判断一个数是否为
偶数,不出意外的话,我想你已经成功了。本节我们将学习另外一个语
句来简化之前的代码,那就是神奇的else。
else表示否则,只能和if配合使用。
现在回到如何让计算机判断一个数是否为偶数这个问题上,回顾一
下本章第3节的算法:
如果a除以2的余数与0相等,则输出yes;
如果a除以2的余数与0不相等,则输出no。
其实上面第2个“如果”中的条件“a除以2的余数和0不相等”正好就是
第1个“如果”中的条件,即“a除以2的余数和0相等”的相反情况,因此我
们用“否则”来代替,从而简化我们的代码。
如果a除以2的余数与0相等,则输出yes;
否则,输出no。这里的“如果”在C语言中仍然用if来表示,这里的“否则”就用else来
表示。好,转换为如下代码:
if (a % 2==0) printf(yes);
else printf(no);
其实,更漂亮的写法是下面这样的:
if (a % 2==0)
{
printf(yes);
}
else
{
printf(no);
}从键盘读入一个整数判断它是否为偶数的完整代码如下:
include
include
int main
{
int a;
scanf(%d, a);
if(a%2==0)
{
printf(yes);
}
else
{
printf(no);
}
system(pause);
return 0;
}
if-else语句的语法格式为:
if (条件)
{ 语句1;
语句2;
语句 ……;
}
else
{
语句1;
语句2;
语句 ……;
}
当条件为真的时候执行if后面的语句;当条件为假的时候执行else后
面的语句。
一起来找茬
下面这段代码用来判断一个数的末尾是否为7,例如:7、17、127……如果是则打印yes,不是则打印no。其中有6个错误,快来改正
吧。
include
include
int main
{
int a;
scanf(%d, a); if (a%10=7);
{
printf(yes)
}
else;
{
prinf(no)
}
system(pause);
return 0;
}
更进一步,动手试一试
从键盘输入一个正整数,让计算机判断这个数是否为一位数(1~
9)。如果是则输出yes,否则输出no。
这一节,你学到了什么
if-else语句的基本格式是什么?第5节 请告诉我谁大
在本章第4节中,我们学习了使用if-else语句来判断一个整数是否为
偶数的方法。本节我们将学习如何从键盘输入两个整数,让计算机来判
断哪一个整数较大,并把较大的那个整数输出来。例如,如果我们输入
的是5和8,那么计算机输出8。
在学习“如何让计算机判断两个数中,谁更大”这个问题之前,先回
顾一下第2章中如何从键盘读入两个整数并且算出它们的和的问题。
include
include
int main
{
int a, b, c;
scanf(%d%d, a, b);
c=a+b;
printf(%d+%d=%d, a, b, c);
}
在上面这段代码中,我们输出的是“和”。那如何让计算机输出较大
的一个数呢?我们仍然使用“如果”的方法。
首先还是定义3个变量:a和b用来存放输入的两个数,c用来存放a
和b中较大的那个。 int a, b, c;
然后读入从键盘输入的两个数,分别存放到变量a和b中。
scanf(%d%d, a, b);
接下来要注意了,我们将通过之前学过的“如果”和“否则”的方法,来分情况讨论并判断谁更大。
如果(a>b) c=a;
上面这两行代码是说明在a>b条件成立的情况下,我们将a的值赋给
c。但是a>b条件并不一定成立,所以我们还要告诉计算机在条件不成立的情况下,应该怎么办。
所以还要写:
否则 c=b;
那么完整的代码如下:
如果(a>b) c=a;
否则 c=b;
总结一下,如果a>b成立,就将a的值赋给c,执行c=a。如果不成
立,就执行“否则”部分,将b的值赋给c,执行c=b。
计算机通过“如果”和“否则”方法来分情况讨论。当a>b成立时,给
出一种解决方案即执行某一个语句,这里是c=a;。当假设不成立的时
候,给出另外一种解决方案即执行另外一个语句,这里是c=b;。
完整代码如下,赶快尝试一下吧。
include
include
int main
{ int a, b, c;
scanf(%d%d, a, b);
if(a>b)
{
c=a;
}
else
{
c=b;
}
printf(%d, c);
system(pause);
return 0;
}
一起来找茬
下面程序的功能是从键盘读入两个整数,判断它们是否相等,如果
相等则输出yes,不相等则输出no。其中有6个错误,快来改正吧!
include
include
int main
{
int a; scanf(%d, a, b) ;
if (a=b) ;
{
printf(yes) ;
}
else ;
{
prinf(no) ;
}
system(pause);
return 0;
}
更进一步,动手试一试
从键盘输入两个正整数,让计算机判断第2个数是不是第1个数的约
数。如果是则输出yes,不是则输出no。第6节 逻辑挑战2:3个数怎么办
在本章第5节中,我们学习了如何从两个数中找出较大的一个数,那么3个数该怎么办呢?
在解决这个问题之前,先回忆一下,我们是如何在任意3个数中找
出最大一个数的呢?例如,1322、4534、1201这3个数中哪个数最大?
怎么样,想出来了没有?千万不要告诉我,你是“一眼”就看出来
的,如果是这样的话,请你在下列各数中“一眼”找出最大的那个来并告
诉我。怎么样,你“一眼”就看出来了吗?最大的数是多少?如果你可以在
1秒内看出来,那你一定不是地球人,最大的数是1232。
现在回归正题,我们从一个数列中寻找最大的一个数的时候,大致
是从左到右、从上到下快速地扫描(当然,古代的中国人可能是从上到
下、从右到左),在快速扫描的过程中,我们首先会记住第1个数,然
后继续往下看,一直看到一个数比之前记住的最大的数还要大时,就转
为记住这个更大的数,然后一直快速扫描完毕,找出最大的一个。下面
来模拟这个过程。同理(我上学的时候最怕看到这个词语,没有办法,这里我也借用
一下,因为我一时半会儿也想不到更好的词语了),我们来找出3个数
中最大的数也是相同的原理。
计算机要想找出3个数中最大的数,其实就是模仿我们的思维过
程。
首先,用3个变量a、b、c分别存放从键盘读入的3个数。
然后,先比较变量a和b的值,将较大的值赋给变量d。
再比较变量d和c的值,如果变量c的值大于变量d的值,则把变量
c的值赋给变量d。
最后输出变量d的值。
完整的代码如下:
include
include
int main
{
int a, b, c, d;
scanf(%d %d %d, a, b, c); if(a>b)
{
d=a;
}
else
{
d=b;
}
if(d
{
d=c;
}
printf(%d, d);
system(pause);
return 0;
}
当然还有另外一种方法,就是分别比较变量a和b,以及变量a和c的
关系……思路如下:
如果a>=b并且a>=c,则输出a;如果b>a并且b>=c,则输出b;
如果c>a并且c>b,则输出c。
其中“并且”在C语言中用“”来表示,顺便说一下在C语言
中“或”用“||”表示。“||”这个符号可能在键盘上不太好找,它通常
在“Enter”键的上面。在英文输入法状态下,按住“Shift”键不要松手,再
按下“Enter”键上方的那个键,就会出现1个“|”,重复两次就可以啦。
“”表示逻辑“并且”
“||”表示逻辑“或”
想一想为什么不能像下面这样写?这样写会有什么问题?自己去探
索吧!
[1]
如果a>=b并且a>=c,输出a;
如果b>=a并且b>=c,输出b;
如果c>=a并且c>=b,输出c。
完整的代码如下: include
include
int main( )
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if (a>=b a>=c) printf(%d, a);
if (b>a b>=c) printf(%d, b);
if (c>a c>b) printf(%d, c);
system(pause);
return 0;
}
使用这种方法虽然代码比较简洁,但是在10个数中找出最大的数就
很麻烦了。而从介绍的第1种方法则可以很容易地扩展出在10个数中找
出最大的数的方法。
一起来找茬
下面这个程序的功能是从键盘读入一个整数,判断这个数是否为7
的倍数或者为末尾含7的数,例如:7、14、17、21、27、28……如果是
则输出yes,不是则输出no。其中有5个错误,快来改正吧。
include
int main
{
int a;
scanf(%d, a) ;
if (a%7=0 | a%10=7) ;
printf(yes) ;
else
printf(no)
system(pause);
return 0;
}
更进一步,动手试一试
1.从键盘任意读入3个整数,如何从中找出最小的一个?
2.从键盘任意读入4个整数,如何从中找出最大的一个?
3.从键盘输入一个年份(整数),判断这个年份是否为闰年,是
则输出yes,不是则输出no。第7节 逻辑挑战3:我要排序
在本章第6节中,我们学习了如何从3个数中找出最大的一个,现在
有一个新的问题:如何从键盘输入任意3个数,并将这3个数从大到小排
序呢?例如,无论你输入2 1 3、3 2 1、1 2 3还是3 1 2,计算机都能够输
出3 2 1,这该怎么办呢?此时你先不要急着往下看,思考一下,通过我
们之前学习的内容,你应该可以独立完成,赶快打开“啊哈C”去尝试一
下吧!
怎么样?我想你应该已经做出来了,即使不是完全正确也应该有了
大概的思路。如果你还没有尝试过,请赶快再去尝试一下吧,这样会让
你更容易理解下面的内容,同时也可以比较一下你想的和我所讲的是否
一样。顺便说一下,要想学好编程,最重要的就是要多尝试。
要想把3个数从大到小排序,其实有很多种方法,这里我们主要讲
解两种方法。
下面来讲第1种方法,这是一种最直接的方法。
如果a>=b并且b>=c,打印a b c;
如果a>=c并且c>b,打印a c b;
如果b>a并且a>=c,打印b a c;
如果b>=c并且c>a,打印b c a;如果c>a并且a>=b,打印c a b;
如果c>b并且b>a,打印c b a。
完整的代码如下:
include
include
int main( )
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if (a>=b b>=c) printf(%d %d %d, a, b, c);
if (a>=c c>b) printf(%d %d %d, a, c, b);
if (b>a a>=c) printf(%d %d %d, b, a, c);
if (b>=c c>a) printf(%d %d %d, b, c, a);
if (c>a a>=b) printf(%d %d %d, c, a, b);
if (c>b b>a) printf(%d %d %d, c, b, a);
system(pause);
return 0;
}
第2种方法,我称之为“换位法”。一共有3个变量,也就是说分别有
3个小房子a、b和c。我们的目标是在小房子a中存储最大的变量,在小房子b中存储次大的变量,在小房子c中存储最小的变量。
首先,我们先将小房子a中的数与小房子b中的数做比较,如果小房
子a中的数小于小房子b中的数,则将小房子a和小房子b中的数交换。这
样我们就可以确定,在小房子a和小房子b中,一定是小房子a中存的是
比较大的数。关于如何交换两个变量的值,我们在第2章的第10节已经
讨论过了,需要借助另外一个小房子t作为中转,代码如下:
if (a
此时上面的这行语句不能简写为:
if (a
因为,当a
将这3条语句放在一对{ }括号中形成一个语句块,这样当条件a
时,计算机才会依次执行t=a; a=b; b=t;这3条语句。如果不加{ },当条
件a
如何都会执行。因为if语句后面只能跟随一条语句或者一个语句块,使
得a=b;和b=t;与if(a
易让你理解:
if (a
b=t;
所以当需要在if语句后面执行多条语句的时候,就必须要用{ }把所
有需要执行的语句括起来,形成一个语句块,这样,计算机就知道它们
是一起的了,要执行就一起执行,要么就都不执行。
接下来,需要再次比较小房子a和小房子c中的数。如果小房子a中
的数小于小房子c中的数,则将小房子a和小房子c中的数交换。这样就
可以确定,在小房子a和小房子c中,一定是小房子a中存的数的值比较
大。
if (a
经过将小房子a中的数分别与小房子b、小房子c中的数进行比较和
交换,我们可以确定小房子a中存储的数一定是3个数中最大的。至于目
前小房子b和小房子c中存的是什么值不重要,因为我们待会儿还要继续
比较小房子b和小房子c中的值。重要的是已经确定小房子a中存储的已
经是最大的数了。下面继续比较小房子b和小房子c中的值,将较大的值放在小房子b
中。
if (b
下面是完整的代码,赶快来试一试吧。
include
include
int main( )
{
int a, b, c, t;
scanf(%d %d %d, a, b, c);
if (a
if (a
if (b
printf(%d %d %d, a, b, c);
system(pause);
return 0;
}
在第6章,我们将会学习选择排序,它就是基于这种方法的扩展。
题外话:有时像这样的写法,显得过于紧凑。
if (a
if (a
{
t=a;
a=b;
b=t;
}
其完整的代码如下:
include
include
int main( )
{
int a, b, c, t;
scanf(%d %d %d, a, b, c);
if (a
{
t=a;
a=b;
b=t;
}
if (a
t=a;
a=c;
c=t;
}
if (b
{
t=b;
b=c;
c=t;
}
printf(%d %d %d, a, b, c);
system(pause);
return 0;
}
一起来找茬
下面程序的功能是从键盘读入1个整数,如果这个数是奇数就输出
这个数后面的3个数,如果这个数是偶数,就输出这个数前面的3个数。
例如,如果输入的整数是5,就输出678;如果输入的整数是4,就输出
321。其中有两个错误,快来改正吧。
include
include
{
int a;
scanf(%d, a) ;
if (a%2==1)
printf(%d , a+1) ;
printf(%d , a+2) ;
printf(%d , a+3) ;
else
printf(%d , a-1) ;
printf(%d , a-2) ;
printf(%d , a-3) ;
system(pause);
return 0;
}
更进一步,动手试一试
从键盘读入任意4个整数,将其从小到大输出。第8节 运算符总结
通过前面的学习,我们了解了C语言中的许多运算符,有算术运算
符“+”、关系运算符“==”和逻辑运算符“”、“||”。下面我们来总结一
下,如表3-1所示。
表3-1 运算符总结
名称 作用
+ 加
减
乘
除
> 大于
< 小于
== 等于
>= 大于等于
<= 小于等于!= 不等于
与
|| 或! 非第9节 1>2究竟对不对
幼儿园的小朋友大概都知道1>2这个关系表达式是不成立的。对C
语言来讲,1>2这个关系表达的写法并没有任何错误,只不过它是假的
关系表达式。如果喜欢,你也可以写11<10,相信你还可以写出很多这
样假的关系表达式。可是你千万不要以为类似于11<10这样的假的表达
式没有任何意义,在第4章你会发现它大有用途。
此外,2>=2这个关系表达式是真的,因为它表示的是2大于2或者2
等于2,只需满足其中任意一个条件就是真的关系表达式。类似于1<=2
这样的表达式也是真的。
请看下面这段代码:
if (1>2)
{
printf(yes);
}
else
{
printf(no);
}
上面这段代码表示,如果1>2成立,也就是说如果1>2这个关系表达
式是真的,则输出yes,否则输出no。很显然1>2是假的,计算机会输出no。这个应该很容易理解。但是看到下面这段代码你肯定会晕:
if (1)
{
printf(yes);
}
else
{
printf(no);
}
你猜计算机会输出什么?去试一试!
如果是下面这样呢?
if (-5)
{
printf(yes);
}
else
{
printf(no);
}你猜计算机输出了什么,去试一试吧。
如果是这样呢?代码如下:
if (0)
{
printf(yes);
}
else
{
printf(no);
}
计算机又输出了什么呢?
如果上面的3段代码你都尝试过,你会发现前两段代码都是输出
yes,也就是说,计算机认为前两个代码中if后面圆括号内的关系表达式
都是成立的,是真的。第3段代码输出的是no,即认为第3段if后面一对
圆括号内的关系表达式不成立,是假的。
这时你可能会觉得奇怪了,关系表达式不应该是一个式子吗,至少
也应该有一个“>”、“<”或“==”之类的运算符才对啊。为什么单独一个数
字也有真假呢?
这个确实很奇怪,计算机就是认为1和-5是真的,0是假的。其实在
C语言中,对于某一个数讨论真假时,只有0是假的,其余都被认为是真
的。很显然,如下3个程序都是打印yes: if (8)
{
printf(yes);
}
else
{
printf(no);
}
if (1000)
{
printf(yes);
}
else
{
printf(no);
}
if (-123)
{
printf(yes);
} else
{
printf(no);
}
只有下面这个程序才会打印no:
if (0)
{
printf(yes);
}
else
{
printf(no);
}第10节 讨厌的嵌套
if-else语句的“嵌套”就是在一个if-else语句中再“嵌套”另外一个if-
else语句。在讲“嵌套”之前我们先回忆一下本章第6节中的一个例子:如
何在三个数中找出最大的一个数。
include
include
int main( )
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if (a>=b a>=c) printf(%d, a);
if (b>a b>=c) printf(%d, b);
if (c>a c>b) printf(%d, c);
system(pause);
return 0;
}
在上面的代码中,我们使用了“”这个逻辑关系运算符号来解决
两个条件同时“满足”的需求。其实还有另外一种方法来解决这个问题。 if(a>=b a>=c)
printf(%d, a);
例如,上面这段代码,可以用“嵌套”的方式写成:
if(a>=b)
{
if(a>=c)
{
printf(%d, a);
}
}
其意思是:当a>=b条件满足时,再进一步讨论a与c的关系(如果
a>=c也成立的话,就打印a)。
接着往下想,如果此时a>=b已经成立,但是a>=c不成立的话,是不
是就意味着在a、b、c中,c是最大值呢?答案是肯定的。代码如下:
if(a>=b)
{
if(a>=c)
{ printf(%d, a);
}
else
{
printf(%d, c);
}
}
那如果第一个条件a>=b不成立呢?完整的代码如下:
include
include
int main
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if(a>=b) a>=b成立的情况
{
if(a>=c) 进一步讨论a与c的关系
{
printf(%d, a);
}
else
{
printf(%d, c); }
}
else a>=b不成立的情况
{
if(b>=c) 进一步讨论b与c的关系
{
printf(%d, b);
}
else
{
printf(%d, c);
}
}
system(pause);
return 0;
}
在上面的代码中所有的if-else语句都加了{ },这样看起来很臃肿,我们之前说过如果if和else后面只有一条语句的话,是可以省略{ }的。
代码如下:
include
include
int main {
int a, b, c;
scanf(%d %d %d, a, b, c);
if(a>=b)
{
if(a>=c)
printf(%d, a);
else
printf(%d, c);
}
else
{
if(b>=c)
printf(%d, b);
else
printf(%d, c);
}
system(pause);
return 0;
}
上面的代码其实还可以更简洁,如下:
include
int main
{
int a, b, c;
scanf(%d %d %d, a, b, c);
if(a>=b)
if(a>=c)
printf(%d, a);
else
printf(%d, c);
else
if(b>=c)
printf(%d, b);
else
printf(%d, c);
system(pause);
return 0;
}
你发现没有,在上面的代码中,我们把最外层if-else语句的{ }也去
掉了。有的同学可能就有问题要问了。我们先来解决问题2。问题2比较简单,else的匹配采用就近原则,离上方哪个if最近,就属于哪个if。所以问题2所指向的那个else是属于
if(b>=c)这个if。这样你就可以把if和else分别一一配对了吧,是不是
有点连连看的感觉。
问题1说起来比较麻烦,但是原理很简单,请听我慢慢道来。其实
上面虚线框中的代码是一个if-else语句,并且是一个很完整的if-else语
句,因为它不但有if部分还有else部分。只不过很特别的是,if部分和
else部分都分别有自己的子语句printf部分,所以看起来就显得很多了。
其本质上就是一条if-else语句,一个“复合语句”。不过在外层的
if(a>=b)看来,它就是一条if-else语句,至于这条语句内部长什么样
子,if(a>=b)并不关心,其实就像大盒子里面套小盒子一样,if(a>=b)是搞不清楚if(a>=c)里面是什么样子的。第11节 if-else语法总结
其实说起来很简单,当if( )括号内的关系表达式成立的时候,就
执行if( )后面的{ }中的内容,不成立的时候则执行else后面{ }中的内
容。当{ }内的语句只有一条的时候,{ }可以省略。
if(关系表达式)
{
语句;
语句;……
}
else
{
语句;
语句;……
}
当{ }内的语句只有一条的时候,可以省略{ }。
if(关系表达式)
语句; else
语句;
[1] 在写本书草稿的时候,我也没有注意到这个问题,感谢@滚雪球snow的提
醒。第4章
重量级选手登场
第1节 永不停止的哭声
通过第2章的学习,我们知道如果让计算机开口说话要使用printf语
句。例如,让计算机说“wa”,则使用printf(wa);。那如果让计算机
说10遍“wa”呢?你可以尝试这样写:
printf(wa wa wa wa wa wa wa wa wa wa);
或者你也可以这样写:
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa);
printf(wa); printf(wa);
如果让计算机说10000遍“wa”呢?该怎么办呢?我想你肯定要疯了
吧。在本节我们就要学习如何让计算机做重复的事情。
好,首先我们学习如何让计算机“永无止境”地说“wa”。这很简单,代码如下:
while(1>0)
{
printf(wa);
}
赶快尝试一下,你是不是发现计算机开始无止境地说“wa”了呢。
完整的代码如下:
include
include
int main
{
while(1>0)
{
printf(wa); }
system(pause);
return 0;
}
一定要尝试啊,尝试后再往下看。
当然,你也可以让计算机无止境地说任何内容。例如:
while(1>0)
{
printf(bie wa);
}
回到正题。上面的代码中由两部分组成,一部分是while( )中的
内容,另一部分是{ }中的内容。它表示的意思是,当while后面( )中
的关系表达式为真时,即关系表达式成立时才执行{ }中的内容。
那么很显然,1>0这个关系是永远成立的,所以计算机会一直执行{
}中的内容,而上面的例子{ }中只是输出wa,所以计算机就会不停地输
出wa。这里顺便说一下,如果{ }中只有一条语句,那么{ }便可以省略。
也就是说可以简写成:
while(1>0)
printf(wa);
这时你可能要问了:while后面( )中的1>0是否可以写成2>1或者
3>0等?
当然可以,如果想让计算机永不停止地如此执行,你可以写任何一
个关系表达式为真的式子。甚至,你可以写while(1)。还记得吗,我
们在第3章说过,如果对某个数字判断真假,只要这个数不为0就是真
的。例如,下面这段代码也可以永不停止地在屏幕上打印wa:
while(1)
printf(wa);下面我来实现一个很炫的效果,“黑客帝国”来啦!
include
include
int main
{
while(1>0)
{
printf(0 1);
}
system(pause);
return 0;
}
执行上面的代码后计算机就会不停地在屏幕上打印0和1。
当然,你可以改变一下打印的背景与字的颜色,例如,改为黑色的
背景,绿色的字。
还记得吗?是使用system(color 0a);这个语句。 include
include
int main
{
system(color 0a);
while(1>0)
{
printf(0 1);
}
system(pause);
return 0;
}
是不是很像黑客帝国?
猜一猜,运行下面这段代码,计算机会有什么反应?
include
include
int main
{
while(1<0)
{
printf(wa);
} system(pause);
return 0;
}
我想你应该猜到了,计算机一句“wa”都没有说,这是为什么呢?因
为1<0这个关系表达式不成立,所以计算机没有执行后面{ }中的内容。
此时你会发现计算机要么打印无数遍都不停止,要么就一次都不打
印。如果想打印指定的次数该怎么办?例如,我们之前遗留下来的问
题:打印10000遍wa,一次也不多、一次也不少该怎么办?不要着急,让我们一起进入本章第2节。
一起来找茬
下面这段代码是让计算机“永无止境”地打印hello。其中有两个错
误,快来改正吧!
include
include
int main( )
{
while(1>0);
print(hello);
system(pause);
return 0;
} 更进一步,动手试一试
让计算机“永无止境”地在屏幕上显示中文汉字“你好”。
这一节,你学到了什么
在C语言中我们用什么语句来实现循环的功能?第2节 我说几遍就几遍
在本章第1节,我们学习了如何使用while循环来让计算机做重复的
事情,本节将揭晓如何让计算机重复指定的次数。
我们知道如果while后面( )中的关系表达式成立,计算机就会运
行{ }中的内容。如果( )中的关系表达式永远成立,那么计算机会“永
无止境”地去重复执行{ }中的内容。
假如让计算机打印100次“wa”,我们需要解决的就是如何让while中的关系表达式在前100次是成立的,然后在第101次的时候就不成立
了。想一想,根据我们之前学过的知识,你有没有什么方法?
很显然while后面的( )中的关系表达式,像2>1或者1<=100等都是
不适合的,因为像这样用固定的数字组合的关系表达式,一旦被写出,那么这个式子是否成立就已经是板上钉钉啦,非真即假,而且永远不会
改变。例如,1<=100这个关系表达式是永远成立的,这样并不符合我们
的要求。我们需要创造怎样一个新的关系表达式,才能让这个式子有时
成立,有时不成立?该怎么办呢?我猜你已经想到了!那就是——伟大的“变量”。
我们可以尝试一下带有变量的关系表达式,例如,a<=100。因为a
是一个变量,a这个小房子里面所装的数是可以变化的。当小房子a中的
数是1的时候,a<=100是成立的;当小房子a中的数是101时,a<=100就
不成立了,这正好满足了对于表达式a<=100有时成立有时不成立的要
求。对于a<=100这个关系表达式是否成立的关键就在于a这个变量所装
的数是多少,也就是变量a的值。
如果想让a<=100在前100次成立,在第101次不成立的话,只需将变
量a的值从1变化到101就可以了。那么如何让变量a的值从1变化到101
呢?我们只需在最开始的时候将变量a的值赋为1,然后while循环每循环
一次,就将变量a的值在原来的基础上再加1就可以了。当变量a的值加
到101时,a<=100就不成立了,就会结束循环。代码如下:
int a;
a=1;
while(a<=100)
{
printf(wa);
a=a+1;
}
再来分析一下上面的代码,a=a+1;这条语句的作用是把小房子a中
的值在原本的基础上增加1(在第2章第5节有详细解释,如果还没有搞
懂还是回去看看吧)。变量a最开始时值为1,每执行一次while循环,变量a的值就会在原来的基础上增加1,依次变成2、3、4、5、6、7、8、9,…,100、101。直到变量a的值为101时,a<=100的条件不成立,退出循
环。
完整的代码如下:
include
include
int main
{
int a;
a=1;
while(a<=100)
{
printf(wa);
a=a+1;
} system(pause);
return 0;
}
赶快尝试一下吧。如果输出10000个wa该怎么办?或者输出10个
hello呢?赶快去尝试一下吧。
接下来一个问题:如果要打印1~100该怎么办?
include
include
int main
{
int a;
a=1;
while(a<=100)
{
printf(wa);
a=a+1;
}
system(pause);
return 0;
}
在这段代码中,我们打印了100个wa,那么打印1~100也很简单,只需修改printf语句就可以了。该如何修改printf语句呢?之前printf语句
的作用是输出wa,现在需要输出1~100,正巧变量a的值就是从1一点点
增加到100的。我们只需在每次循环时把a的值输出即可,即把
printf(wa);改为printf(%d , a);。完整的代码如下:
include
include
int main
{
int a;
a=1;
while(a<=100)
{
printf(%d , a);
a=a+1;
}
system(pause);
return 0;
}
赶快尝试一下吧。
如果我们想倒序输出呢,就是让计算机先输出100再输出99接着输
出98、97、96、95、…、1,该怎么办?
我们刚刚学过的“让计算机输出1~100”,就是让变量a从1开始,通过while循环把变量a的值每次都输出来,并且每次循环的时候将变量a的
值增加1,这样就会打印出1~100。而此时的要求是从100打印到1。很
显然我们需要让变量a从100开始,通过while循环把变量a的值每次都输
出来,不过每次需要递减1,一直递减到1为止。代码如下:
include
include
int main
{
int a;
a=100; 初始值从100开始
while(a>=1) 请注意这里的循环条件变为a>=1
{
printf(%d , a);
a=a-1; 每循环一次将a的值递减1
}
system(pause);
return 0;
}
问题又来啦,如果希望打印的是1~100中的偶数呢?自己想一想
吧。
怎么样,有没有思路?其实要输出1~100中的偶数,有很多种方
法。比如之前变量a是从1开始的,之后每次在原有的基础上增加1,那么a就会从1到2再到3再到4……一直到101,当变量a的值增加到101时,不满足条件a<=100,就会退出while循环。现在我们可以改变一下思
路,让变量a的值从2开始,每次增加2,这样变量a就会从2增加到4再增
加到6……以此类推。代码如下:
include
include
int main
{
int a;
a=2;
while(a<=100)
{
printf(%d , a);
a=a+2;
}
system(pause);
return 0;
}
好了,又到了尝试的时候了。
如何让计算机打印1~100中能被3整除的数,你应该也会了,就是
先将变量a的初始值赋为3,然后每次增加3。赶快再尝试一下吧。
上面的写法虽然好,却不是万能的,假如不是输出1~100中能被3整除的数,而是输出1~100中所有不能被3整除的数呢?例如:1、2、4、5、7、8、10, …, 97、98、100,又该怎么办呢?不要着急,我们将
在本章第3节彻底解决这个问题。
一起来找茬
下面这段代码是让计算机从100打印到200。其中有3个错误,快来
改正吧!
include
include
int main
{
int a;
a=100;
while(a<200) ;
{
printf(%d , a);
}
system(pause);
return 0;
}
更进一步,动手试一试
让计算机从1打印到100再打印到1,例如:1 2 3 …… 98 99 100 9998 …… 3 2 1。第3节 if对while说:我对你很重要
在本章第2节中,我们学习了while循环的基本使用方法,但是遗留
了一个问题,即如何让计算机输出1~100中所有不能被3整除的数,例
如:1、2、4、5、7, …, 97、98、100。
通过本章第2节的学习,我们可以很容易地让计算机打印1、2、3,…,100,只需让变量a从1开始每次增加1就可以了。如果想每次遇到3的
倍数就不打印的话,我们只需在每次打印之前对变量a的值进行判断就
好了,即当变量a的值是3的倍数时就不输出,否则就输出。那怎么判断
变量a的值是否是为3的倍数呢?这就需要我们在第3章学习的if语句。我
们只需要通过if语句来判断变量a的值除以3的余数是否为0就可以了。如
果余数不为0,说明变量a中的值不是3的倍数,就将变量a中的值打印出
来;否则就说明变量a中的值是3的倍数,不能打印。
那么怎么判断变量a中的值除以3的余数是否为0呢?需要使用“%”这
个运算符。在第3章中我们介绍过,“%”读作mod,也可以称之为“取
模”,作用就是获取余数。另外说一下“%”这个运算符的左右两边必须为
整数。而“”这个符号表示除号,作用是获取商,“”运算符的左右两边
既可以是整数也可以是小数。代码如下:
include
include
int main
{ int a;
a=1;
while(a<=100)
{
if(a%3! =0)
printf(%d , a);
a=a+1;
}
system(pause);
return 0;
}
赶快尝试一下吧。如果要输出1~100中能被3整除但是不能被5整除的所有数,又该怎
么办?
这个数是3的倍数但不是5的倍数,也就是需要变量a除以3的余数为
0并且除以5的余数不为0。这里的逻辑关系“并且”在C语言中的表示方法
我们在第3章已经学习过,用“”表示,代码如下:
include
include
int main
{
int a;
a=1;
while(a<=100)
{
if(a%3==0 a%5! =0)
printf(%d , a);
a=a+1;
}
system(pause);
return 0;
}
更复杂的来啦!
你有没有和同学玩过一个游戏——大家围成一圈,从1开始报数,但是每逢遇到7的倍数或者末尾含7的数,例如7、14、17、21、27、28
等,就要拍手并且不能报出,谁出错了,谁就要受到惩罚。
现在我想知道1~100中有多少这样的数,请你写这样一个程序,输
出1~100中所有7的倍数和末尾含7的数。
很简单,我们先参照以往的程序,利用while循环,让变量a从1递增
到100,不过我们每次在输出变量a的值之前需要对变量a进行判断。根
据题目的要求,如果变量a的值是7的倍数或者末尾含有7就打印出来。
判断一个变量是否为7的倍数我们已经很熟悉了,只需要判断变量a除以
7的余数是否为0就可以,即如果a%7==0这个关系表达式成立就输出。
那怎么判断变量a的值末尾是否含7呢?我们仔细想一想就会发现,末尾
含7的数其实就是这个数的个位为7,也就是这个数除以10的余数为7。
发现这个规律就好办了,即在a%10==7这个关系表达式成立时输出就可
以啦。
好了,现在有两个关系表达式a%7==0和a%10==7,分别表示这个
数是否为7的倍数以及末尾是否含7。这两个式子是“或者”的关系,即只
要有一个成立,就将这个数输出。这里的逻辑关系“或者”在C语言中的
表示方法我们在第3章也学习过,用“||”表示,代码如下:
include
include
int main
{
int a;
a=1; while(a<=100)
{
if(a%7==0 || a%10==7)
printf(%d , a);
a=a+1;
}
system(pause);
return 0;
}第4节 求和!求和!!求和!!!
在本章第2节中,我们已经学习了如何让计算机打印1~100,那如
何让计算机求1~100中所有数的和呢?
你可能会说,首项加尾项的和乘以项数然后再除以2,就可以了。
没错,你可以这样做,但是如果求1~100中所有7的倍数或者末尾含7的
数的总和,又该怎么办呢?
在求1~100的和之前,我们先来解决如何求1+2+3的值。
没错,你可以这样写:
include
include
int main
{
int a;
a=1+2+3;
printf(%d, a);
system(pause);
return 0;
}
但是如果计算1~100中所有数的和也这样写的话,是不是太麻烦了呢?我们可以尝试另一种写法,代码如下:
include
include
int main
{
int a;
a=0; 想一想为什么a的初始值要为0呢?
a=a+1;
a=a+2;
a=a+3;
printf(%d, a);
system(pause);
return 0;
}
你可能会说这样写岂不是更麻烦……但是我们发现在上面的这段代
码中,a=a+1;a=a+2; a=a+3;这三句话,基本思想是相同的,第一次加
1,第二次加2,第三次加3。我们可以把这三个语句用a=a+i;来表示。
然后让变量i从1到3循环就可以了。代码如下:
include
include
int main {
int a, i;
a=0;
i=1;
while(i<=3)
{
a=a+i;
i=i+1;
}
printf(%d, a);
system(pause);
return 0;
}
如果需要计算1~100的和,我们只需将上面代码中i<=3修改为
i<=100就可以了,赶快去尝试一下吧。
如果求1~100中所有7的倍数或者末尾含7的数的总和,又该怎么办
呢?先来回顾一下刚刚才学会的求1~100中所有数的和的方法,代码如
下:
include
include
int main
{ int a, i;
a=0;
i=1;
while(i<=100)
{
a=a+i;
i=i+1;
}
printf(%d, a);
system(pause);
return 0;
}
在上面的代码中,变量i会从1到100每次递增1,然后每次将变量i的
值累加到变量a上。这个变量i就像是一个搬运苹果的工人,刚开始只拿
1个苹果,之后拿2个苹果,再之后又拿3个苹果……最后一次一下拿了
100个苹果。
变量a就像是一个很大很大的水果篮子,用来装这些苹果。每次拿
来的苹果统统被装进篮子里面,第一次放1个苹果进去,第二次放2个苹
果,第三次放3个苹果进去……最后一次放100个苹果进去。最后篮子a
中苹果的总数就是1~100的和。所以我们最后输出了变量a的值,这就
是答案。那么求1 ......
您现在查看是摘要介绍页, 详见PDF附件(6134KB,378页)。





