C语言程序设计

978-7-115-58231-7
作者: [印] 亚沙万特·卡内特卡尔(Yashavant Kanetkar)
译者: 徐波
编辑: 郭媛
分类: C语言

图书目录:

详情

学习任何程序设计语言的最佳方法都是创建良好的程序,C 语言也不例外。一旦决定编写程序我们就会发现,总是有至少两种方法可以实现。那么,如何才能找到最好的方法来实现程序?本书就能帮助读者解决此类问题。本书是一本C 语言程序设计的经典教材。多年来,本书被很多工程和科学研究所及院校指定为学习教材。 本书这一版本(第17 版)除了讲解C 语言中基本的函数、指针、控制指令、数据类型、数组、字符串、输入输出、位操作等内容外,还增加了C 语言程序设计的各个主题的实例和面试问题,以便读者尽快熟悉C 语言的实际应用。书中的实例和习题已经过作者认真挑选,集中体现了各个知识要点的具体用法。本书提供可供读者下载的程序源代码,并配套出版《C 语言程序设计 习题解答》。 本书结构合理,内容深入浅出,既适合用作高等学校本科和专科学生学习C 语言程序设计的教材,也适合用作零基础的程序设计初学者的自学用书。

图书摘要

版权声明

Copyright ©2020 BPB Publications India. All rights reserved.

First published in the English language under the title “Let Us C” by Yashavant Kanetkar BPB Publications India. (sales@bpbonline.com)

Chinese translation rights arranged with BPB Publications India through Media Solutions, Tokyo, Japan.

本书中文简体版由BPB Publications India授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式或任何手段复制或抄袭本书内容。

版权所有,侵权必究。

版权信息

书名:C语言程序设计

ISBN:978-7-115-58231-7

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

著    [印] 亚沙万特·卡内特卡尔(Yashavant Kanetkar)

译    徐 波

责任编辑 郭 媛

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315

内容提要

学习任何程序设计语言的最佳方法都是创建良好的程序,C语言也不例外。一旦决定编写程序我们就会发现,总是有至少两种方法可以实现。那么,如何才能找到最好的方法来实现程序?本书就能帮助读者解决此类问题。本书是一本C语言程序设计的经典教材。多年来,本书被很多工程和科学研究所及院校指定为学习教材。

本书这一版本(第17版)除了讲解C语言中基本的函数、指针、控制指令、数据类型、数组、字符串、输入输出、位操作等内容外,还增加了C语言程序设计的各个主题的实例和面试问题,以便读者尽快熟悉C语言的实际应用。书中的实例和习题已经过作者认真挑选,集中体现了各个知识要点的具体用法。本书提供可供读者下载的程序源代码,并配套出版《C语言程序设计 习题解答》。

本书结构合理,内容深入浅出,既适合用作高等学校本科和专科学生学习C语言程序设计的教材,也适合用作零基础的程序设计初学者的自学用书。

作者简介

通过出版著作以及开发关于C、C++、数据结构、VC++(Visual C++的简写)、.NET和嵌入式系统的在线“探索”视频课程,Yashavant Kanetkar使自己过去25年的IT生涯越发光彩夺目。Yashavant的著作和在线课程在为印度乃至全世界培养IT科技人才方面做出了不小的贡献。

Yashavant的著作在全世界范围内广受欢迎,数以百万计的学生和专业人员从中受益。他的著作被翻译为印地语、古吉拉特语、英语、日语、韩语和汉语,分别在印度、美国、日本、韩国和中国出版。

Yashavant是一位极受欢迎的IT领域演说家,在TedEx、印度理工学院(IIT)、印度国家理工学院(NIT)、印度信息技术学院(IIIT)和一些全球软件公司举办过研讨会和讲习班。

Yashavant由于在创业、专业以及教育方面的优异成就,被印度理工学院坎普尔校区授予久负盛名的“杰出校友奖”(distinguished alumnus award)。这个奖已被授予50位最优秀的印度理工学院坎普尔校区的校友,在过去50年里,这些人在自己的专业以及社会改良方面做出了杰出贡献。

由于对印度IT教育做出了杰出贡献,Yashavant连续5年被微软公司授予“最佳.NET技术撰稿人”(best .NET technical contributor)和“最有价值专家”(Most Valuable Professional,MVP)称号。

Yashavant拥有VJTI Mumbai(位于孟买的一所理工学院)的工学学士学位,并拥有印度理工学院坎普尔校区的工学硕士学位。他当前是Kanetkar ICIT Pvt. Ltd实验室的主任。读者也可以通过kanetkar@kicit.com与他进行交流。

前  言

《C语言程序设计》(Let Us C)成为印度大多数理工大学的教学材料已经有些年头了。大约是在去年的时候,我收到一些建议,大家觉得本书的篇幅应该稍作精简,因为许多学生在学习C语言之前已经对它有所了解。我欣然接受了这些建议,并按照上述原则对本书进行了改编,希望读者能够喜欢当前这个较为精练的版本。

在本书之前的某个版本中,我对章节进行了重新整理,这样如果使用本书作为C语言程序设计的教材,那么用22节课(每节课1小时)就可以完成本书的学习,每节课正好讲授一章的内容。很多读者喜欢这个思路,认为这种方式使得他们的学习之路变得非常顺利,为此我也感到非常欣慰。我对本书章末习题进行的合理重组也受到读者的广泛欢迎。根据读者的反馈,我在本书的第15版中引入了一项新内容——“课后笔记”。这是一种手写形式的C语言程序设计笔记。通过读者发来的电子邮件,我推测这项内容对于读者是极有帮助的,可以在考试、答辩或面试之前帮助他们纠正一些概念。

许多读者还告诉我,他们通过阅读“面试常见问题”这一章受益匪浅。我对这一章的内容进行了进一步的完善。这一章背后的理念非常简单——本书的所有读者迟早会在面试室里接受关于C语言程序设计的面试。现在我可以证实这一章可以帮助读者顺利接受这个考验,并获得良好的结果。

在本书的第17版中,我在每一章中增加了一节新内容——“程序”,里面包含了与该章所讨论主题有关的有趣程序。本书所列出的所有程序都会以源代码的形式出现在异步社区。读者可以下载它们并对它们进行完善和修改,或者按自己的意愿对它们进行任何操作。如果读者希望得到本书习题的答案,可以参阅《C语言程序设计 习题解答》(Let Us C Solutions)。如果读者需要更多的习题进行实践,可以参考另一本书Exploring C。和往常一样,这两本书的新版本也是随本书的第17版一起发行的。

本书不仅是我的书,也是读者的书。如果读者觉得我在某些方面可以改进,或者对下一版本的内容有一些建议,那么请通过异步社区或者kanetkar@kicit.com或sales@bpbonline.com与我直接联系。

我为本书能够通过一种微不足道的方式影响许多人的职业生涯而感到窃喜。

最近,我获得了印度理工学院坎普尔校区授予的“杰出校友奖”。我非常高兴能够与下面这些伟大的人同列:Infosys公司首席导师Narayan Murthy、印度储备银行前主管D. Subbarao博士、斯坦福大学Rajeev Motwani博士、H. C. Verma教授、NASSCOM主席Som Mittal先生、哈佛大学Minwalla教授、印度理工学院坎普尔校区前教导主任Sanjay Dhande博士、美国麻省理工学院Arvind教授和Sur教授,以及印度理工学院金奈校区Ashok Jhunjhunwala教授。

我认为本书以及我的其他著作在我获得“杰出校友奖”的过程中起到了最主要的作用。令我略感吃惊的是,几乎所有对本书略有所知或者想要了解的人都希望从我口中得知编写一本畅销数百万册的著作的诀窍所在。我的回答是尽心竭力,向读者倾心传授自己所知道的一切,并尽量保持简单。我不知道这个回答是否能让大家信服,但我在撰写本书的前16个版本时一直遵循这个原则,这个版本同样如此。

祝大家程序设计愉快!

Yashavant Kanetkar

致  谢

本书已经成为我生命中重要的一部分。在过去的20年里,我创作了本书并不断地对它进行完善。在这个过程中,除了赞美之外,我收到很多来自学生、开发人员、教授、出版人和作者的建议。从本书第1版撰稿到第17版出版,他们给我提供了太多的帮助,我恨不得把他们的名字都署在本书的封面上。

我需要特别感谢Manish Jain,他对本书的写作思路充满信心,信任我的写作能力,不断地给我鼓励并不时地向我提供有益的建议。我祝愿每位作家都能拥有一位像Manish这样富有协作精神、知识渊博且不遗余力地提供支持的出版人。

在本书之前的版本中,逐步的修改和完善一直没有停止。在这个过程中,许多人在运行程序和寻找漏洞方面提供了很大的帮助。我相信在集合了他们的智慧之后,本书所有的程序都能够正确地运行。如果书中仍然有错误、疏忽或不一致的情况,那肯定是我自己的责任。

感谢家人的耐心和包容,在本书马拉松式的编写过程中他们忍受我每天工作到深夜,忍受键盘的敲击声及其他烦扰。考虑书的封面思路是一回事,把它落到实处又是另一回事。本书(英文原版)封面的设计是由Vinay Indoria完成的,衷心地向他表示感谢!

最后,我衷心地感谢让我观察到C语言的每一处角落的无数学生,正是因为他们,本书才能够以多种语言在印度、美国、日本、韩国和中国出版。

资源与支持

本书由异步社区出品,异步社区(https://www.epubit.com/)为您提供相关资源和后续服务。

配套资源

本书提供如下资源:

源代码。

要获得以上配套资源,请在异步社区本书页面中单击,跳转到下载界面,按提示进行操作即可。

提交勘误信息

作者、译者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,再单击“提交”按钮即可(见下图)。本书的作者、译者和编辑会对您提交的勘误信息进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

扫码关注本书

扫描右侧的二维码,您将会在异步社区微信服务号中看到本书信息及相关的服务提示。

与我们联系

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线投稿(直接访问www.epubit.com/contribute即可)。

如果您所在的学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

关于异步社区和异步图书

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近40年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、人工智能、测试、前端、网络技术等。

异步社区

微信服务号

第1章 起步

“良好的开端是成功的一半”

我们无法从一开始就很强大,但我们必须准备变得强大。因此,良好的开端是非常重要的。在踏上C语言学习道路之前,本章将帮助读者做好一些准备工作。

本章内容

1.1 什么是C语言

1.2 C语言的基础知识

  1.2.1 字母、数字和特殊符号

  1.2.2 常量、变量和关键字

  1.2.3 C语言的常量类型

  1.2.4 整型常量的创建规则

  1.2.5 浮点型常量的创建规则

  1.2.6 字符型常量的创建规则

  1.2.7 C语言的变量类型

  1.2.8 变量名的创建规则

  1.2.9 C语言的关键字

1.3 第1个C语言程序

  1.3.1 C语言程序的格式

  1.3.2 C语言程序中的注释

  1.3.3 什么是main()

  1.3.4 变量及其用法

  1.3.5 printf()及其用法

  1.3.6 编译和运行

1.4 接收输入

1.5 程序

在开始用C语言编写程序之前,我们最好能够明白:C语言到底是什么?C语言是如何出现的?它和其他程序设计语言相比有哪些区别?在本章中,我们将简单地讨论这些问题。

任何程序设计语言都要处理4个重要的问题,包括数据的存储方式、数据的操作方式、如何实现输入和输出以及如何控制程序中指令的执行顺序。在本章中,我们将讨论其中的前3个问题。

1.1 什么是C语言

C语言是一种程序设计语言,它是由美国AT&T公司贝尔实验室的Dennis Ritchie于1972年发明的。C语言之所以流行,是因为它简单易用。现在有一种说法——“C语言已经被诸如C++、C#和Java这样的语言取代,因此现在没有必要再学习C语言了”。我非常郑重地对这种说法表示反对,理由如下。

(1)C++、C#和Java使用一种被称为面向对象程序设计(Object-Oriented Programming,OOP)的原则对程序进行组织。面向对象程序设计有许多优点。但是在使用这种程序组织原则时,我们仍然需要掌握一些基本的程序设计技巧。因此,先学习C语言,再迁移到C++、C#或Java是合理的做法。这种两步走的学习过程可能会花费更长的时间,但最终这些付出都是值得的。

(2)大多数流行的操作系统(如Windows、UNIX、Linux和Android)是用C语言编写的。而且,一旦需要对操作系统进行扩展以使用新设备,就需要编写设备驱动程序,而设备驱动程序完全是用C语言编写的。

(3)像微波炉、洗衣机和数码相机这样的常见家用设备如今也变得越来越智能。这种智能化来自微处理器、操作系统以及设备中嵌入的程序。这类程序必须运行得足够快,并且只能在容量有限的内存中运行。在创建这类操作系统和程序时,C语言是一种非常适合的程序设计语言。

(4)读者肯定看到过一些专业的3D计算机游戏,用户乘坐诸如飞船这样的物体飞行并向入侵者开火。所有这类游戏的本质就是速度。为了匹配这种速度需求,程序必须对用户的输入做出足够快速的反应。用于创建这类游戏的流行游戏框架(如DirectX)就是用C语言编写的。

我希望这些理由足以说服读者把学习C语言作为学习程序设计的第一步。

1.2 C语言的基础知识

学习C语言和学习英语有很多相似之处,如图1.1所示。

图1.1

1.2.1 字母、数字和特殊符号

图1.2列出了C语言所允许的合法字母、数字和特殊符号。

图1.2

1.2.2 常量、变量和关键字

字母、数字和特殊符号经过适当组合之后可以构成常量、变量和关键字。常量是一种不会发生变化的实体,而变量是一种可能会发生变化的实体。关键字是一种具有特殊含义的单词。在程序设计语言中,常量常被称为文字值,变量常被称为标识符。下面我们观察C语言中不同类型的常量和变量。

1.2.3 C语言的常量类型

C语言中的常量可以分为以下两种主要类型。

(1)基本常量。

(2)次级常量。

图1.3对这两种常量进行了进一步的分类。

图1.3

在当前阶段,我们的讨论仅限于基本常量,即整型常量、浮点型常量和字符型常量。下面是创建这些不同类型的常量的规则。

1.2.4 整型常量的创建规则

(1)整型常量必须至少包含1位数字。

(2)整型常量中不能出现小数点。

(3)整型常量可以包含任意个数的0,可以为正或负。如果整型常量前没有符号,那么默认为正。

(4)整型常量的内部不允许出现逗号或空白。

(5)整型常量的取值范围是-2 147 483 648~+2 147 483 647。

示例: 426   +782   -8000   -7605

严格地说,整型常量的取值范围取决于编译器。对于像Visual Studio、GCC这样的编译器,整型常量的取值范围是-2 147 483 648~+2 147 483 647;对于像Turbo C或Turbo C++这样的编译器,整型常量的取值范围是-32 768~+32 767。

1.2.5 浮点型常量的创建规则

浮点型常量可以写成两种形式:小数形式和指数形式。在创建小数形式的浮点型常量时,必须遵循下面这些规则。

(1)浮点型常量必须至少包含1位数字。

(2)浮点型常量必须具有小数点。

(3)浮点型常量可以为正或负,默认为正。

(4)浮点型常量的内部不允许出现逗号或空白。

示例:+325.34   426.0   -32.76   -48.5792

指数形式通常用于浮点值太大或太小的情况,但我们也可以用指数形式表示任何浮点型常量。

在指数形式中,浮点型常量由两部分表示。出现在e之前的部分被称为尾数(mantissa),出现在e之后的部分被称为指数。因此,0.000342用指数形式表示就是3.42e-4(在常规算术中表示3.42×10-4)。

在创建指数形式的浮点型常量时,必须遵循下面这些规则。

(1)尾数部分和指数部分应该由字母e或E分隔。

(2)尾数部分的前面可以有正号或负号,默认为正号。

(3)指数部分必须至少包含1位数字,可以是正整数或负整数,默认为正整数。

(4)指数形式的浮点型常量的取值范围是-3.4e38~3.4e38。

示例:+3.2e-5    4.1e8    -0.2E+3    -3.2e-5

1.2.6 字符型常量的创建规则

(1)字符型常量是出现在一对单引号中的单个字母、数字或特殊符号。

(2)两个单引号都应为英文单引号。例如,'A'是合法的字符型常量,‘A’则不是。

示例:   'A'    'I'    '5'    '='

1.2.7 C语言的变量类型

一种特定类型的变量只能存储同一种类型的常量。例如,整型变量只能存储整型常量,浮点型变量只能存储浮点型常量,字符型变量只能存储字符型常量。因此,C语言具有很多类型的变量,就像它的常量类型一样。

任何C语言程序都会执行一些计算,这些计算的结果存储在计算机内存的某些位置。为了方便地提取和使用这些值,内存位置都有特定的名称。由于存储在每个内存位置的值可能会发生变化,因此这些内存位置的名称就被称为变量名。

不同类型常量的创建规则是不同的。但是,在创建所有类型的变量名时,可以使用同一组规则。

1.2.8 变量名的创建规则

(1)变量名是1~31个字母、数字和下画线的组合。有些编译器允许变量名的长度最多为247个字符。不要创建太长的变量名,因为会增加我们的输入负担。

(2)变量名的第1个字符必须是字母或下画线(_)。

示例: si_int   pop_e_89   avg   basic_salary

我们应该创建有意义的变量名。例如,计算存款利息时,应该创建类似prinroinoy这样的变量名表示本金、利率和年数,而不是采用类似abc这样的任意变量名。

变量名的创建规则对于所有基本类型和次级类型的变量都是相同的。因此,为了对变量进行区分,在程序中必须声明变量的类型。

示例:int   si, m_hra;
    float  bassal;
    char  code;

1.2.9 C语言的关键字

对于C语言编译器(或者计算机)来说,关键字是含义已经明确的单词。C语言一共有32个关键字。图1.4列出了这些关键字。

图1.4

关键字一般不能作为变量名使用。但是,有些C语言编译器允许使用与关键字完全相同的变量名。

除了图1.4所示的关键字之外,编译器厂商可能还会提供更多的关键字。尽管ANSI委员会建议这类编译器特定的关键字应该以两个下画线开头(如__asm),但并不是所有的编译器厂商都遵循这个规则。

1.3 第1个C语言程序

理解了变量、常量和关键字之后,下一个合乎逻辑的步骤就是将它们组合起来构成指令。但是,我们并不采用这种做法,而是直接编写第1个C语言程序。在完成这个任务之后,我们再详细讨论组成这个程序的指令。

我们的第1个C语言程序非常简单:根据一组表示本金、利率和年数的值计算存款利息。

/* 计算存款利息 */
/* 作者:gekay   日期:25/03/2020 */
# include <stdio.h>
int main( )
{
    int p, n ;
    float r, si ;
    p = 1000 ;
    n = 3 ;
    r = 8.5 ;
    /* 计算存款利息的公式 */
    si = p * n * r / 100 ;
    printf( "%f\n" , si ) ;
    return 0 ;
}

下面我们详细讨论这个C语言程序。

1.3.1 C语言程序的格式

C语言程序的格式决定了其书写方式。C语言程序的格式具有某些特定的规则,它们适用于所有的C语言程序。这些规则如下。

(1)C语言程序中的每条指令都是一条独立的语句。

(2)C语言程序中的语句必须按照我们希望它们执行的顺序出现。

(3)两个单词之间可以插入空白字符以提高语句的可读性。

(4)所有的语句都应该使用小写字母。

(5)每条C语句必须以分号(;)结尾。因此,分号(;)是作为语句结束符使用的。

(6)一条C语句可以出现在某特定行的任意位置,这也是C语言被称为自由形式的程序设计语言的原因。

(7)通常一行包含一条语句。但是,我们也可以在一行中书写多条语句,只要每条语句以分号结尾即可。

1.3.2 C语言程序中的注释

在C语言程序中,注释用于说明程序或程序中某些语句的作用。在程序的开头使用注释说明程序的作用、作者和编写日期是一种很好的做法。

下面是在C语言程序中使用注释的一些提示。

(1)注释可以采用小写形式、大写形式或混合形式。它们应该出现在/**/之间。因此,这个程序中的前2行都是注释。

(2)有时候,程序中某条特定语句的作用并不是那么明显。这时就可以用注释来说明这条(或这些)语句的作用,如下所示。

/* 计算简单利息的公式 */
si = p * n * r / 100 ;

(3)在程序的任何地方都可以使用任意数量的注释。因此,注释可以出现在语句之前或之后,甚至出现在语句的内部,如下所示。

/* formula */ si = p * n * r / 100 ;
si = p * n * r / 100 ; /* 公式 */
si = p * n * r / /* 公式 */ 100 ;

(4)注释不能嵌套。这意味着一条注释不能出现在另一条注释的内部。因此,下面的注释是非法的。

/* 计算存款利息 /* 作者: gekay           日期: 25/03/2020 */ */

(5)一条注释可以跨越多行,如下所示。

/* This comment has
  three lines
  in it */

(6)ANSI C还允许使用另一种形式的注释,如下所示。

// 计算存款利息
// 公式

1.3.3 什么是main()

main()是所有C语言程序的一个关键组成部分,我们需要理解它的作用及具体内涵。

(1)main()是一个函数。函数是一组语句的容器。一个C语言程序可能包含多个函数。如果其中只包含一个函数,那么这个函数必须是main()函数。main()函数的所有语句都必须出现在一对花括号{}中。

(2)和计算器的功能一样,函数也返回一个值。main()总是返回一个整数值,因此main()前面的类型关键字是int。这被称为函数的返回类型。这个程序返回的整数值是0。0表示程序运行成功。如果main()中的语句无法顺利完成任务,那么我们可以通过让main()函数返回一个非零值来表示程序运行失败。

(3)main()函数返回值的方式因不同的编译器而异,如下所示。

① Turbo C、Turbo C++:Alt C|Information

② Visual Studio:调试器的Watch窗口中的$ReturnValue

③ Linux:程序执行之后,在命令行中执行echo $?

(4)有些像Turbo C / Turbo C++这样的编译器甚至允许main()不返回任何值。在这种情况下,我们可以在main()的前面加上关键字void。但这并不是main()函数的标准书写方式。我们将在第8章详细讨论函数及其作用。

1.3.4 变量及其用法

现在,我们通过这个程序来理解常量和变量的重要性。

(1)程序中的任何变量在使用之前必须声明,如下所示。

int p, n ;               /* 声明 */
float r, si ;            /* 声明 */
si = p * n * r / 100 ;   /* 使用 */

(2)在下面这条语句中,*和/都是算术操作符。C语言的算术操作符包括+、-、*和/

si = p * n * r / 100 ;

1.3.5 printf()及其用法

C语言并没有提供任何关键字用于在屏幕上显示输出。屏幕上的所有输出都是通过像printf()这样的库函数实现的。下面我们通过这个程序来理解printf()函数。

(1)变量si的值被计算出来之后,需要在屏幕上显示出来。我们选择使用printf()函数来完成这个任务。

(2)为了使用printf()函数,我们需要在程序的开头添加#include<stdio.h>#include是一种预处理指令。

(3)printf()函数的基本格式如下。

printf( "<格式字符串>", <变量列表> ) ;

<格式字符串>可以包含如下格式指示符。

%f:表示输出浮点数。

%d :表示输出整数。

%c :表示输出字符。

除了像%f%d%c这样的格式指示符之外,格式字符串还可以包含其他任何字符。这些字符会在printf()执行时按原样输出。

(4)下面是printf()函数的一些常见使用例子。

printf( "%f", si ) ;
printf( "%d %d %f %f", p, n, r, si ) ;
printf( "Simple interest = Rs. %f", si ) ;
printf( "Principal = %d\nRate = %f", p, r ) ;

上面最后一条语句的输出如下所示。

Principal = 1000
Rate = 8.500000

由于存在换行符'\n',输出被分为两行。换行符能把光标定位到下一行,它是C语言提供的几个转义序列之一。第18章将详细讨论这个概念。

(5)printf()不仅可以输出变量的值,还可以输出表达式的结果,例如3、3 + 2、c和a + b * c – d,如下所示。

printf( "%d %d %d %d", 3, 3 + 2, c, a + b * c – d ) ;

注意,3c也是合法的表达式。

1.3.6 编译和运行

写完程序之后,我们需要输入程序并指示计算机执行这个程序。有两个工具可以帮助我们完成这个任务:编辑器和编译器。编辑器允许我们输入程序,而编译器则负责把程序转换为机器语言。这种转换是必要的,因为计算机只能理解机器语言。

除了这两个工具之外,我们还需要一些其他工具来提高程序设计的效率,例如预处理器、链接器和调试器。单独对这些工具进行操作是一件很乏味的事情,因此它们都被捆绑到了GUI中,这样使用这些工具时就会方便很多。这种捆绑通常被称为集成开发环境(Integrated Development Environment,IDE)。

我们可以使用的IDE有很多。每种IDE都面向不同的操作系统和微处理器。附录A描述了使用IDE的细节,包括从哪里下载、如何安装和使用。在学习本书的任何程序之前,读者应该先阅读附录A的内容,并在自己的计算机上安装正确的IDE。

1.4 接收输入

在这个C语言程序中,我们假设变量pnr的值分别是1000、3和8.5。每次运行这个程序时,它所产生的存款利息都是同一个值。如果我们想要计算其他几组值的存款利息,就需要把这些值植入程序中,然后重新编译并运行程序。这意味着这个程序的通用性不够强,无法在不修改程序的前提下计算任意一组值的存款利息。这显然不是一种好的做法。

为了具有更好的通用性,这个程序在运行过程中应该要求用户通过键盘提供pnr的值。

我们可以通过scanf()函数来实现这个目的。这个函数可以帮助我们从键盘接收输入。下面这个程序展示了这种做法。

/* 计算存款利息 */
/* 作者:gekay   日期:25/03/2020 */
# include <stdio.h>
int main( )
{
    int p, n ;
    float r, si ;
    printf( "Enter values of p, n, r" ) ;
    scanf( "%d %d %f", &p, &n, &r ) ;
    si = p * n * r / 100 ;
    printf( "%f\n" , si ) ;
    return 0 ;
}

第1条printf()语句在屏幕上输出Enter values of p, n, r。我们没有在这条printf()语句中使用任何表达式,这意味着在printf()中使用表达式是可选的。

注意,在scanf()函数中变量名的前面加上&符号是必要的。&是取址操作符,它提供了这个变量在内存中的地址。&a这种用法告诉scanf()应该把用户通过键盘提供的值存储在哪个地方。第9章将详细讨论&操作符的工作方式。

注意,在向scanf()函数提供值时必须用空格、制表符或换行符对它们进行分隔。空格是通过空格键输入的,制表符是通过Tab键输入的,换行符是通过Enter键输入的。下面是一些例子。

由空格分隔的3个值:

1000 5 15.5

由制表符分隔的3个值:

1000    5    15.5

由换行符分隔的3个值:

1000
5
15.5

1.5 程序

练习1.1

假设Ramesh的基本工资是通过键盘输入的。他的物价津贴(Dearness Allowance,DA)是基本工资的40%,房租津贴(House Rent Allowance,HRA)是基本工资的20%。编写一个程序,计算他的总收入。

程序

/* 计算Ramesh的总收入 */
# include <stdio.h>
int main( )
{
    float bp, da, hra, grpay ;
    printf( "\nEnter Basic Salary of Ramesh: " ) ;
    scanf( "%f", &bp ) ;
    da = 0.4 * bp ;
    hra = 0.2 * bp ;
    grpay = bp + da + hra ;
    printf( "Basic Salary of Ramesh = %f\n", bp ) ;
    printf( "Dearness Allowance = %f\n", da ) ;
    printf( "House Rent Allowance = %f\n", hra ) ;
    printf( "Gross Pay of Ramesh is %f\n", grpay ) ;
    return 0 ;
}

输出

Enter Basic Salary of Ramesh: 1200
Basic Salary of Ramesh = 1200.000000
Dearness Allowance = 480.000000
House Rent Allowance = 240.000000
Gross Pay of Ramesh is 1920.000000
________________________________________________________________________________

练习1.2

假设两个城市的距离(以千米为单位)是通过键盘输入的。编写一个程序,把这个距离转换为以米、厘米、英尺和英寸为单位。

程序

/* 距离的转换 */
# include <stdio.h>
int main( )
{
    float km, m , cm, ft, inch ;
    printf( "\nEnter the distance in Kilometers: " ) ;
    scanf( "%f", &km ) ;
    m = km * 1000 ;
    cm = m * 100 ;
    inch = cm / 2.54 ;
    ft = inch / 12 ;
    printf( "Distance in meters = %f\n", m ) ;
    printf( "Distance in centimeter = %f\n", cm ) ;
    printf( "Distance in feet = %f\n", ft ) ;
    printf( "Distance in inches = %f\n", inch ) ;
    return 0 ;
}

输出

Enter the distance in Kilometers: 3
Distance in meters = 3000.000000
Distance in centimeter = 300000.000
Distance in feet = 9842.519531
Distance in inches = 118110.234375
________________________________________________________________________________

练习1.3

假设一名学生5门课的成绩都是通过键盘输入的,且每门课的满分是100分。编写一个程序,计算这名学生的总分和平均分。

程序

/* 计算总分和平均分 */
# include <stdio.h>
int main( )
{
    int m1, m2, m3, m4, m5, aggr ;
    float per ;
    printf( "\nEnter marks in 5 subjects: " ) ;
    scanf( "%d %d %d %d %d", &m1, &m2, &m3, &m4, &m5 ) ;
    aggr = m1 + m2 + m3 + m4 + m5 ;
    per = aggr / 5 ;
    printf( "Aggregate Marks = %d\n", aggr ) ;
    printf( "Percentage Marks = %f\n", per ) ;
    return 0 ;
}

输出

Enter marks in 5 subjects: 85 75 60 72 56
Aggregate Marks = 348
Percentage Marks = 69.000000

习题

(  )

(  )

1.下面哪些是非法的C语言常量?为什么?

'3.15'             35,550             3.25e2
2e-3               'eLearning'        "show"
'Quest'            23            4 6 5 2

2.下面哪些是非法的变量名?为什么?

B' day              int             $hello
#HASH               dot.            number
totalArea           _main           temp_in_Deg
total%              1st             stack-queue
variable name       %name%          salary

3.判断下列说法是正确的还是错误的。

(1)C语言是由Dennis Ritchie开发的。

(  )

(2)像Windows、UNIX、Linux和Android这样的操作系统都是用C语言编写的。

(  )

(3)C语言程序可以很方便地与PC或笔记本电脑的硬件进行交互。

(  )

(4)C语言程序的浮点型常量既可以用小数形式也可以用指数形式表示。

(  )

(5)一个字符变量在任意时刻只能存储1个字符。

(6)整型常量的最大值因编译器而异。

(  )

(7)通常所有的C语句都是用小写形式书写的。

(  )

(8)C语言中的两个单词之间可以插入空白字符。

(9)变量名的内部不能插入空白字符。

(  )

(10)C程序可以在编辑器的帮助下转换为机器语言代码。

(  )

(11)大多数开发环境提供了编辑器供用户输入C程序,并提供了编译器来把C程序转换为机器语言代码。

(  )

(12)int、char、float、real、integer、character、char、main、printf和scanf都是关键字。

(  )

4.对下面的左右两列进行配对。

(a) \n          ① 文字值

(b) 3.145        ② 语句结束符

(c) -6513        ③ 字符型常量

(d) 'D'          ④ 转义序列

(e) 4.25e-3       ⑤ 输入函数

(f) main()         ⑥ 函数

(g) %f、 %d、 %c       ⑦ 整型常量

(h) ;           ⑧ 取址操作符

(i) 常量          ⑨ 输出函数

(j) 变量          ⑩ 格式指示符

(k) &           ⑪指数形式

(l) printf()         ⑫浮点型常量

(m) scanf()         ⑬标识符

5.指出下列程序中可能存在的错误。

(1) int main( )
      {
         int a ; float b ; int c ;
         a = 25 ; b = 3.24 ; c = a + b * b – 35 ;
      }
(2) #include <stdio.h>
      int main( )
      {
          int a = 35 ; float b = 3.24 ;
          printf( "%d %f %d", a, b + 1.5, 235 ) ;
      }
(3) #include <stdio.h>
      int main( )
      {
          int a, b, c ;
          scanf( "%d %d %d", a, b, c ) ;
      }
(4) #include <stdio.h>
      int main( )
      {
          int m1, m2, m3
          printf( "Enter values of marks in 3 subjects" )
          scanf( "%d %d %d", &m1, &m2, &m3 )
          printf( "You entered %d %d %d", m1, m2, m3 )
      }

6.完成下列任务。

(1)假设用户通过键盘输入一个以华氏温度表示的气温。编写一个程序,把这个华氏温度转换为摄氏温度。

(2)假设矩形的长度和宽度以及圆的半径都是通过键盘输入的。编写一个程序,计算矩形的面积和周长以及圆的面积和周长。

(3)A0纸的大小是1189mm×841mm,后续每种纸A(n)的大小就是把前一种纸A(n-1)的长边对半截开。因此,A1纸的大小是841mm×594mm。编写一个程序,计算并输出A0、A1、A2……A8纸的大小。

课后笔记

1.建议学习C语言的三个主要原因:

(1)为学习C++、C#或Java打下良好的基础;

(2)UNIX、Linux、Windows和游戏框架是用C编写的;

(3)嵌入式系统的程序是用C编写的。

2.常量 = 文字值 →无法修改;变量 = 标识符 → 可以修改。

3.变量和常量的类型:①基本类型; ②次级类型。

4.基本类型包括:①整型;②浮点型;③字符型。

5.取值范围:

(1) 2字节整数的取值范围是-32 768~+32 767;

(2) 4字节整数的取值范围是-2 147 483 648~+2 147 483 647;

(3)浮点数的取值范围是-3.4×1038~+3.4×1038

6.在字符型常量中,两个引号都必须撇向左,例如'A'。

7.变量具有如下含义:

(1)它是一个其值可以改变的实体;

(2)它是一个表示内存位置的名称。

8.变量名是大小写敏感的,并且必须以字母和下画线开头。

9. C语言关键字的总个数是32。关键字的例子有char、int、float等。

10. printf()函数可以输出多个常量和变量。

11. printf()scanf()函数中的格式指示符:%i%f%c

12. main()是一个函数,它必须返回一个整数值:返回0表示程序运行成功,返回1表示程序运行失败。

13.在程序中可以使用/*…*///表示注释。

14. &表示取址操作符,在scanf()函数中,变量名的前面必须有这个操作符。

第2章 C语言的指令

“定好目标,出发”

板球队队长的能力无法超脱球队而存在。如果球队实力不济,队长纵有通天之能也将独木难支。对于C语言程序设计而言,情况也是如此。除非我们能够透彻地理解C语言所提供的指令,否则就无法设计良好的程序。本章将讨论这些指令。

本章内容

2.1 指令的类型

2.2 类型声明指令

2.3 算术指令

2.4 整型和浮点型的转换

2.5 赋值时的类型转换

2.6 操作符的优先层次

2.7 操作符的结合性

2.8 控制指令

2.9 程序

程序只不过是指令的集合而已。不同的指令可以帮助我们在程序中完成不同的任务。在第1章中,我们看到了如何使用不同的指令编写简单的C语言程序。在本章中,我们将探索这些程序中使用的指令。

2.1 指令的类型

C语言具有3种类型的指令。

(1)类型声明指令:这种指令用于声明C语言程序中使用的变量的类型。

(2)算术指令:这种指令用于对常量和变量执行算术运算。

(3)控制指令:这种指令用于控制C语言程序中各种语句的执行顺序。

下面让我们深入观察这些指令。

2.2 类型声明指令

类型声明指令通常出现在main()函数的起始部分。下面是这种指令的一些例子。

int bas ;
float rs, grosssal ; 
char name, code ;

下面是类型声明指令的一些微妙的变形。

(1)在声明变量的类型时,我们还可以像下面这样对变量进行初始化。

int i = 10, j = 25 ;
float a = 1.5, b = 1.99 + 2.4 * 1.44 ;

(2)变量在使用之前必须先定义。下面的语句是非法的,因为我们在定义变量a之前就使用了该变量。

float b = a + 3.1, a = 1.5 ;

(3)下面的语句则没有问题。

int  a, b, c, d ; 
a = b = c = 10 ;

但是,下面的语句是非法的。

int  a = b = c = d = 10 ;

同样,这是因为我们在定义变量b之前就试图使用该变量(把它赋值给变量a)。

2.3 算术指令

C语言的算术指令由等号左边的变量名以及等号右边通过操作符连接的变量名和常量组成。

示例:int   ad ;
    float   kot, deta, alpha, beta, gamma ; ad = 3200 ;
    kot = 0.0056 ;
    deta = alpha * beta / gamma + 3.2 * 2 / 5 ;

其中:

*/-+是算术操作符。

=是赋值操作符。

2、53200是整型常量。

3.20.0056是浮点型常量。ad是整型变量。

kotdetaalphabetagamma是浮点型变量。

变量和常量被统称为“操作数”。在执行一条算术语句时,“算术操作符”会对右边的操作数执行操作,并通过“赋值操作符”把结果赋值给左边的变量。

C语言的算术语句分为3种类型,如下所示。

(1)整型模式的算术语句:在这种语句中,所有的操作数都是整型变量或整型常量。

示例:int   i, king, issac, noteit ;
     i = i + 1 ;
     king = issac * 234 + noteit - 7689 ;

(2)浮点型模式的算术语句:在这种语句中,所有的操作数均为浮点型常量或浮点型变量。

示例:float   qbee, antink, si, prin, anoy, roi ; 
     qbee = antink + 23.123 / 4.5 * 0.3442 ; 
     si = prin * anoy * roi / 100.0 ;

(3)混合模式的算术语句:在这种语句中,有些操作数是整数,有些操作数是浮点数。

示例:float   si, prin, anoy, roi, avg ;
     int  a, b, c, num ;
     si = prin * anoy * roi / 100.0 ; 
     avg =( a + b + c + num ) / 4 ;

注意下面这些与算术指令有关的要点。

(1)C语言要求等号的左边只能出现1个变量。也就是说,z = k * l是合法的,但k * l = z是不合法的。

(2)除了除法操作符之外,C语言还提供了求模操作符(%)。求模操作符会返回一个整数除以另一个整数的余数。因此,10/2这个表达式的结果是5,而10%2的结果是0

注意,求模操作符无法作用于浮点数。另外在使用求模操作符时,余数的符号总是与被除数的符号相同。因此,-5 % 2的结果是-1,而5 % -2的结果是1

(3)整数、浮点数和字符均可参与算术操作。因此,下面的语句是合法的。

char   x = 'a', y = 'b' ;
int   z = x + y ;

在内存中,所有的字符都是用ASCII码表示的。'a''b'的ASCII码分别是01100001和01100010。它们对应的数值分别是97和98。上面语句中的加法是对这两个数值执行的,而不是对字符本身执行的。

(4)没有任何操作符是默认存在的,操作符必须明确地写明。在下面的例子中,b后面的乘法操作符必须明确地写明。

a = c.d.b(xy);               //普通的算术语句
a = c * d * b *( x * y );    //C语句

(5)C语言中不存在指数运算操作符。指数运算必须按照下面这样的方式实现。

float  a ;
a = pow( 3.0, 2.0 ) ; 
printf( "%f", a ) ;

上述语句中的pow()函数是由C标准库提供的,用于计算3.0的2.0次方。pow()函数只适用于浮点数,因此这里使用了3.0和2.0。

注意,为了使用pow()函数,程序的开头必须添加#include<math.h>#include是预处理指令。我们将在第8章更深入地学习标准库函数,并在第12章学习预处理指令。

读者可以自行探索math.h头文件中声明的其他数学函数,如abs()sqrt()sin()cos()tan()等。

2.4 整型和浮点型的转换

为了有效地开发C语言程序,我们需要理解用于执行浮点数和整数转换的隐式规则。下面描述了这些规则,读者必须认真理解。

(1)对一个整数和另一个整数执行算术操作后,将总是生成整型结果。

(2)对一个浮点数和另一个浮点数执行算术操作后,将总是生成浮点型结果。

(3)对一个整数和一个浮点数执行算术操作后,将总是生成浮点型结果。在这种算术操作中,整数首先被提升为浮点数,然后执行算术操作,因此产生的结果总是浮点数。

图2.1展示的一些例子可以有效地消除读者心中的疑惑。

图2.1

2.5 赋值时的类型转换

如果等号左边和右边的表达式的类型不相同,那么等号右边表达式的值会根据等号左边变量的类型进行升级或降级。例如,观察下面的赋值语句。

int   i ;
float   b ; 
i = 3.5 ; 
b = 30 ;

在第1条赋值语句中,3.5尽管是浮点数,但却无法存储在i中,因为i是一个int类型的变量。因此,3.5(float类型)被降级为3(int类型),然后被存储于i中。后面那条语句的情况正好相反。30被提升为30.0,然后被存储于b中,b是一个float类型的变量,只能存储浮点数。

除了上面这些简单的表达式之外,这些规则在复杂的表达式中仍然适用。例如,观察下面的赋值语句。

float   a, b, c ;  int   s ;
s = a * b * c / 100 + 32 / 4 - 3 * 1.1 ;

在上面的赋值语句中,有些操作数是int类型,还有一些是float类型。我们知道,在表达式的求值过程中,int值会被提升为float类型,表达式的结果也是float类型。但是,由于最后要被赋值给s,因此表达式的结果被再次降级为int类型。

观察图2.2所示的算术指令的结果。假设k是整型变量,a是浮点型变量。

图2.2

注意,尽管下面这两条语句会产生相同的结果0,但它们获得这个结果的过程却不同。

k = 2 / 9 ;
k = 2.0 / 9 ;

在第1条语句中,由于2和9都是整数,因此结果也是整数(也就是0),然后0被赋值给k。在第2条语句中,9被提升为9.0,然后执行除法,结果是0.222222;但是,这个值无法存储于int变量k中,因此它先被降级为0,之后才被存储于k中。

2.6 操作符的优先层次

在对算术语句进行求值时,有些问题可能会令人困惑。例如:表达式2 * x – 3 * y是对应于(2x) – ( 3y)还是对应于2(x – 3y)呢?类似地,A / B * C是对应于A /(B * C)还是对应于(A / B) * C呢?为了圆满地回答这些问题,我们必须理解操作符的优先层次。操作符的执行优先级被称为操作符的优先层次。表2.1显示了常用操作符的优先层次。

表2.1

优先级

操作符

描述

第1级

* / %

乘法、除法、求模

第2级

+ -

加法、减法

第3级

=

赋值

在括号内部,表2.1列出的优先层次同样适用。另外,如果括号的层数不止一层,最内层括号中的操作将首先执行,然后执行次内层括号中的操作,依此类推。

下面我们通过几个例子来更清晰地说明这个问题。

例2.1:确定操作的优先层次并对下面这个表达式进行求值,假设i是一个整型变量。

i = 2 * 3 / 4 + 4 / 4 + 8 - 2 + 5 / 8

下面展示了这个表达式的求值过程。

i = 2 * 3 / 4 + 4 / 4 + 8 - 2 + 5 / 8
i = 6 / 4 + 4 / 4 + 8 - 2 + 5 / 8        操作:*
i = 1 + 4 / 4 + 8 - 2 + 5 / 8            操作:/
i = 1 + 1+ 8 - 2 + 5 / 8                 操作:/
i = 1 + 1 + 8 - 2 + 0                    操作:/
i = 2 + 8 - 2 + 0                        操作:+
i = 10 - 2 + 0                           操作:+
i = 8 + 0                                操作:-
i = 8                                    操作:+

注意,6/4的结果是1而不是1.5。这是因为64都是整数,于是6/4的结果也必然是一个整数。类似地,5/8的结果是0,因为58都是整数,5/8必然返回一个整数。

例2.2:确定操作的优先层次并对下面这个表达式进行求值,假设kk是一个浮点型变量。

kk = 3 / 2 * 4 + 3 / 8

下面展示了这个表达式的求值过程。

kk = 3 / 2 * 4 + 3 / 8
kk = 1 * 4 + 3 / 8           操作:/
kk = 4 + 3 / 8               操作:*
kk = 4 + 0                   操作:/
kk = 4                       操作:+

注意,和例2.1提到的原因相同,3/8的结果是0

C语言的全部45个操作符可根据优先级进行分级。我们还没有看到过其中很多操作符,因此我们现在不打算深入讨论操作符的优先级。附录B提供了所有操作符以及它们的完整优先级表格。

到目前为止,我们看到了用C语言编写的算术语句是如何求值的。但是,如果我们不知道怎样把一个基本的代数表达式转换为C表达式,那么我们对这方面知识的掌握就是不完整的。图2.3显示了一些代数表达式以及对应的C表达式。

图2.3

2.7 操作符的结合性

当一个表达式包含两个优先级相同的操作符时,它们之间的平局是通过操作符的结合性来打破的。C语言的所有操作符要么具有从左向右的结合性,要么具有从右向左的结合性。下面我们通过一些例子来解释这个概念。

观察下面这个表达式。

a = 3 / 2 * 5 ;

这里出现了两个优先级相同的操作符——/*,这里的平局是通过/*的结合性来打破的。由于这两个操作符都具有从左向右的结合性,因此首先执行/,然后执行*

观察另一个表达式。

a = b = 3 ;

这里的两个赋值操作符具有相同的优先级。因此,操作顺序是由赋值操作符的结合性决定的。=的结合性是从右向左,因此首先执行第2个=,然后执行第1个=

我们再观察最后一个表达式。

z = a * b + c / d ;

其中,*/具有相同的优先级和结合性(从左向右)。编译器可以自行决定先执行*还是/,因为不管两者谁先执行,结果都是一样的。

附录B指出了C语言中所有操作符的结合性。注意,所有操作符的优先级和结合性都是预先确定的,无法改变。

2.8 控制指令

控制指令控制程序中指令的执行顺序。换句话说,控制指令决定了程序的控制流。在C语言中,共有4种类型的控制指令。

(1)顺序控制指令。

(2)选择或决策控制指令。

(3)重复或循环控制指令。

(4)case控制指令。

顺序控制指令确保指令的执行顺序与它们在程序中出现的顺序相同。决策和case控制指令允许计算机决定接下来执行哪条指令。循环控制指令允许反复执行一组语句。在接下来的第3~7章,我们将详细讨论这些控制指令。

2.9 程序

练习2.1

假设一个三角形的三条边的边长是通过键盘输入的,编写一个程序,计算这个三角形的面积。

程序

/* 根据边长计算三角形的面积 */ 
# include <stdio.h>
# include <math.h> /* for sqrt( ) */
int main( )
{
    float  a, b, c, sp, area ;
    printf( "\nEnter sides of a triangle: " ) ; scanf( "%f %f %f", &a, &b, &c ) ; 
    sp =( a + b + c ) / 2 ;
    area = sqrt( sp *( sp - a ) *( sp - b ) *( sp - c ) ) ; 
    printf( "Area of triangle = %f\n", area ) ; 
    return 0 ;
}

输出

Enter sides of a triangle: 4 5 6 
Area of triangle = 9.921567
________________________________________________________________________________

练习2.2

假设一个5位数是通过键盘输入的,编写一个程序,反转这个5位数。

程序

/* 反转一个5位数 */ 
# include <stdio.h>
int main( )
{
    int  n, d5, d4, d3, d2, d1 ; long int  revnum ;
    printf( "\nEnter a five digit number(less than 32767): " ); scanf( "%d", &n );
    d5 = n % 10 ;        /* 第5位数字 */
    n = n / 10 ;         /* 剩余的数字 */
    d4 = n % 10 ;        /* 第4位数字 */
    n = n / 10 ;         /* 剩余的数字 */
    d3 = n % 10 ;        /* 第3位数字*/
    n = n / 10 ;         /* 剩余的数字 */
    d2 = n % 10 ;        /* 第2位数字*/
    n = n / 10 ;         /* 剩余的数字 */
    d1 = n % 10 ;        /* 第1位数字*/
    revnum = d5 * 10000 + d4 * 1000 + d3 * 100 + d2 * 10 + d1 ; 
    /* 指定%ld,用于输出长整数 */
    printf( "The reversed number is %ld\n", revnum ) ; 
    return 0 ;
}

输出

Enter a five digit number(less than 32767): 12345 
The reversed number is 54321
________________________________________________________________________________

练习2.3

假设一种货币共包含6种面值的纸币,如1卢比、2卢比、5卢比、10卢比、50卢比和100卢比。如果金额是通过键盘输入的,编写一个程序,计算组成这个金额最少需要几张纸币。

程序

#include <stdio.h>
int main( )
{
    int amount, nohun, nofifty, noten, nofive, notwo, noone, total ; 
    printf( "Enter the amount: " ) ;
    scanf( "%d", &amount ) ; 
    nohun = amount / 100 ; 
    amount = amount % 100 ; 
    nofifty = amount / 50 ; 
    amount = amount % 50 ; 
    noten = amount / 10 ;
    amount = amount % 10 ; 
    nofive = amount / 5 ; 
    amount = amount % 5 ; 
    notwo = amount / 2 ; 
    amount = amount % 2 ; 
    noone = amount / 1 ; 
    amount = amount % 1 ;
    total = nohun + nofifty + noten + nofive + notwo + noone ; 
    printf( "Smallest number of notes = %d\n", total ) ; 
    return 0 ;
}

输出

Enter the amount: 570
Smallest number of notes = 8
________________________________________________________________________________

习题

1.指出下列C语句中可能存在的错误。

(1)x =( y + 3 ) ;
(2)cir = 2 * 3.141593 * r ;
(3)char = '3' ;
(4)4 / 3 * 3.14 * r * r * r = vol_of_sphere ;
(5)volume = a3 ;
(6)area = 1 / 2 * base * height ;
(7)si = p * r * n / 100 ;
(8)area of circle = 3.14 * r * r ;
(9)peri_of_tri = a + b + c ;
(10)slope =( y2 - y1 ) ÷( x2 - x1 ) ;
(11)3 = b = 4 = a ;
(12)count = count + 1 ;
(13)char ch = '25 Apr 12' ;

2.对下列表达式进行求值,并说明它们的优先层次。

(1) ans = 5 * b * b * x - 3 * a * y * y - 8 * b * b * x + 10 * a * y ;
      (a = 3, b = 2, x = 5, y = 4,假设ans为int类型)
(2) res = 4 * a * y / c - a * y / c ;
      (a = 4, y = 1, c = 3,假设res是int类型)
(3) s = c + a * y * y / b ;
      (a = 2.2, b = 0.0, c = 4.1, y = 3.0,假设s是float类型)
(4) R = x * x + 2 * x + 1 / 2 * x * x + x + 1 ;
      (x = 3.5,假设R是float类型)

3.说明下列表达式的求值顺序。

(1)g = 10 / 5 /2 / 1 ;
(2)b = 3 / 2 + 5 * 4 / 3 ;
(3)a = b = c = 3 + 4 ;
(4)x = 2 - 3 + 5 * 2 / 8 % 3 ;
(5)z = 5 % 3 / 8 * 3 + 4
(6)y = z = -3 % -8 / 2 + 7 ;

4.下列程序的输出是什么?

(1) # include <stdio.h>
      int main( )
      {
          int  i = 2, j = 3, k, l ; float   a, b ;
          k = i / j * j ; 
          l = j / i * i ; 
          a = i / j * j ; 
          b = j / i * i ;
          printf( "%d %d %f %f\n", k, l, a, b ) ; 
          return 0 ;
      }
(2)# include <stdio.h>
      int main( )
      {
          int  a, b, c, d ; 
          a = 2 % 5 ; 
          b = -2 % 5 ; 
          c = 2 % -5 ; 
          d = -2 % -5 ;
          printf( "a = %d b = %d c = %d d = %d\n", a, b, c, d ) ; 
          return 0 ;
      }
(3) # include <stdio.h>
      int main( )
      {
          float a = 5,  b = 2 ; 
          int c, d ;
          c = a % b ;
          d = a / 2 ;
          printf( "%d\n", d ) ; 
          return 0 ;
      }
(4) # include <stdio.h>
      int main( )
      {
          printf( "nn \n\n nn\n" ) ; 
          printf( "nn /n/n nn/n" ) ; 
          return 0 ;
      }
(5) # include <stdio.h>
      int main( )
      {
          int a, b ;
          printf( "Enter values of a and b" ) ; 
          scanf( "  %d %d  ", &a, &b ) ; 
          printf( "a  = %d b = %d", a, b ) ; 
          return 0 ;
      }

5.下列说法是正确的还是错误的?

(1)*或/、+是C语言中算术操作符的正确优先层次。   (  )

(2)[]{} 可以在算术指令中使用。   (  )

(3)优先层次决定了哪个操作符最先被使用。   (  )

(4) 在C语言中,算术指令在=的左边不能包含常量。   (  )

(5)在C语言中,**操作符用于指数运算。   (  )

(6)%操作符不能作用于浮点数。   (  )

6.填空。

(1)在y = 10 * x / 2 + z ;这条语句中,_____操作是最先执行的。

(2)如果a是一个整型变量,a = 11 / 2 ;这条语句将把______存储在a中。

(3)表达式a = 22 / 7 * 5 / 3的结果是______

(4)表达式x = –7 % 2 – 8的结果是______

(5)如果d是一个float变量,d = 2 / 7.0这个操作将把______存储在d中。

7.完成下列任务。

(1)假设用户通过键盘输入一个5位数,编写一个程序,计算它的各位数字之和。(提示:使用求模操作符%)

(2)编写一个程序,接收一个点的笛卡儿坐标(x, y),并把它们转换为极坐标(r, θ)。(提示:

(3)编写一个程序,接收地球上两个地点的纬度(L1, L2)和经度(G1, G2) (用度数表示),并输出这两个地点之间的距离(D,以海里[1]为单位)。以海里表示的距离公式如下。

[1] 1海里≈1852米。

(4)风寒因子是暴露在空气中的皮肤在受到风的影响后测得的温度。风寒温度总是低于空气温度,风寒因子可通过下面这个公式来计算。

其中,t表示空气温度,v表示风速。编写一个程序,接收tv的值,并计算风寒因子(wcf)。

(5)假设用户通过键盘输入一个角度的值,编写一个程序,输出它的所有三角比。

(6)用户通过键盘把两个数输入内存位置CD。编写一个程序,交换内存位置CD的内容。

课后笔记

1. void main()是错误的,正确的形式是int main()

2.每种编译器都面向一种特定的“操作系统+微处理器”组合,这种组合被称为平台。我们为一种平台创建的编译器在另一种平台上是无法使用的。

3. 交换两个变量内容的标准步骤如下。

t = a ;  a = b ; b = t ;

4. 操作符/产生商,操作符%产生余数。当使用%操作符时,余数的符号与被除数的符号相同。%操作符不适用于浮点数。

5. C语言提供了3种类型的指令:① 类型声明指令;② 算术指令;③ 控制指令。

6.声明和赋值可以组合在一起。

示例:int a = 5;

7. C语言提供了3种类型的算术语句:①整型模式的算术语句;②浮点型模式的算术语句;③混合模式的算术语句。

8.算术指令的规则如下。

(1)如果一个操作数为float类型,那么结果也是float类型。

(2)只有当两个操作数都是int类型时,结果才是int类型。

9. 语句a = pow( 2, 5 );会把25存储在a中。记得在程序的开头添加#include <math.h>

10.每个操作符都具有优先级和结合性。

11.常用操作符按优先级从前往后排列如下:* / % + – =。可以使用()改变优先级。

12.当通过优先级无法决定哪个操作首先执行时,可通过结合性来打破僵局。结合性分为从左向右和从右向左。+、–、*、/和 %的结合性是从左向右,=的结合性是从右向左。

13. printf()的格式字符串可以包含如下内容。

(1)格式指示符:%c%d%f

(2)转义序列:\n\t等。

(3)任何其他字符。

14. scanf()的格式字符串只能包含格式指示符。

15.控制指令控制程序中指令的执行顺序。

16.控制指令有4种类型:①顺序控制指令;② 决策控制指令;③循环控制指令;④ case控制指令。

相关图书

代码审计——C/C++实践
代码审计——C/C++实践
C/C++代码调试的艺术(第2版)
C/C++代码调试的艺术(第2版)
大规模C++软件开发 卷1:过程与架构
大规模C++软件开发 卷1:过程与架构
C/C++程序设计竞赛真题实战特训教程(图解版)
C/C++程序设计竞赛真题实战特训教程(图解版)
C/C++函数与算法速查宝典
C/C++函数与算法速查宝典
C程序设计教程(第9版)
C程序设计教程(第9版)

相关文章

相关课程