C语言课程设计(txt+pdf+epub+mobi电子书下载)


发布时间:2020-08-22 09:09:10

点击下载

作者:刘博,董学文

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

C语言课程设计

C语言课程设计试读:

前言

C语言课程设计是计算机程序设计的主要实践课程,为帮助读者熟练掌握基本的程序设计方法,我们编写了本书。

本书将程序设计题目分为文件类、字符串类、算法类、综合类和其他类共五大类,集同类题目于一章,方便读者集中学习;不少题目提供了多种实现方法,启发读者多角度思考;题目分析力求重点突出、简洁明了,而非面面俱到,希望读者能够结合参考程序阅读思考。

本书对C程序设计语言的编程环境、调试程序的基本方法、编码风格等方面进行了介绍。参考程序均按照编码风格并使用标准C语言撰写,以增强程序的可读性,方便读者自行调试和运行。

全书分为7章,各章节内容安排如下:

第1章,编程环境。本章介绍VC 6.0、VS 2008、Dev-C++、Eclipse等编程环境下创建Win32的控制台项目及Debug调试。

第2章,编码风格。本章介绍编码风格,旨在使代码更容易阅读、分享和检查。

第3~7章,通过例题分别讲解文件类、字符串类、算法类、综合类和其他类编程方法。其中,第6章通过一个完整的通讯录软件综合类题目,介绍用数组和链表存储记录的方法,并对链表存储记录的方法进行扩展:加入了文件保存记录及用户登录和权限控制功能。

附录A介绍课程设计要求及评分标准,可供课程实施时参考。附录B的C语言运算符优先级和附录C的ASCII字符编码方便读者学习时参考。

本书在编写过程中得到了西安电子科技大学计算机学院领导的关心和万波副教授的支持与帮助。同时,作者对机械工业出版社的同志表示感谢。

本书第2章、第3章、第6章、4.1节、4.2节、4.3节、4.4节、5.1节、5.2节、5.3节、7.1节、7.2节及附录由刘博编写;第1章、4.5节、4.6节、5.4节、5.5节、5.6节、7.3节由董学文编写。全书由刘博统稿。在程序编写过程中还得到了杨寒的帮助。

由于作者自身水平有限,错误及不当之处在所难免,敬请专家、读者给予指教。可发邮件至bliu@xidian.edu.cn、xwdong@xidian.edu.cn。刘博 董学文西安电子科技大学2013年1月第1章编程环境本章简单介绍几个常用的C语言编程环境,包括VC 6.0、Dev-C++、VS 2008等。不同的编程环境,其功能不完全一样。有些编程环境(如VC 6.0和VS 2008)功能较强大,除了简单的Win32程序外,还能开发其他比较复杂的程序,如基于MFC的静态链接库、动态链接库等。面向C语言程序开发人员,本书将从两个方面对各编程环境进行介绍:首先介绍各编程环境下创建一个Win32的控制台项目/工程的过程;其次介绍各编程环境下的Debug调试。调试是编程人员应该具备的基本技能之一,其重要性甚至超过学习一门编程语言。不会调试,意味着编程人员即使会一门编程语言,也不能编制出任何好的软件。编程过程中,不可能不出现错误或异常,因而需要利用各种手段进行查错和排错。其中常用的方法就是Debug调试。Debug调试的一般步骤为:设置断点,开始调试,添加查看,单步调试,停止调试。1.1 VC 6.0简介

Visual C++6.0是Microsoft公司推出的开发Win32程序的集成开发环境,可将“高级语言”翻译为“机器语言(低级语言)”,并支持面向对象可视化编程。它具有程序框架自动生成、灵活方便的类管理、代码编写和界面设计集成交互操作、可开发多种程序等优点,而且通过简单的设置即可使其生成的程序框架支持数据库接口、OLE和WinSock网络。

Visual C++6.0,简称VC 6.0或VC 6,是微软公司于1998年推出的Visual Studio系列的第6版,一经推出,便受到众多编程人员的欢迎,并成为专业程序员进行软件开发的首选工具。即使微软公司继续推出Visual C++.NET(VC 7)、Visual C++2005(VC 8)、Visual C++2008(VC 9)、Visual C++2010(VC 10),但VC 6.0仍以其界面简洁、占用资源少、操作方便等优点受到广大编程人员热爱。

VC 6.0不仅是一个C++编译器,而且是一个基于Windows操作系统的可视化集成开发环境(Integrated Development Environment,IDE)。VC 6.0通过一个名为Developer Studio的组件,将其他多个开发组件(包括编辑器、调试器以及程序向导AppWizard、类向导ClassWizard等)集成为一个和谐的开发环境。

VC 6.0的优点如下:

1)同时支持面向过程和面向对象的程序开发。

2)界面简单、资源消耗小、操作方便。

3)VC 6.0进行Windows应用程序的开发主要有两种方式:一种是WiNPI方式,另一种是MFC方式。MFC(Microsoft Foundation aClass)是微软公司提供的一个类库(class library),以C++类的形式封装了Windows的API,并且包含一个应用程序框架。传统的WinAPI开发过程比较繁琐,MFC对WinAPI进行再次封装,因而MFC相对于WinAPI开发更具备效率优势。

4)VC 6.0作为一个集成开发工具,提供了软件代码自动生成和可视化的资源编辑功能。在使用VC 6.0开发应用程序的过程中,系统能自动生成大量各种类型的文件,大大简化了程序开发人员的工作。

VC 6.0的缺点如下:

1)对C++标准支持不完全,例如对模板的支持比较差。

2)需要打补丁,否则不够稳定。最新补丁为SP6,推荐安装,否则编译时易出现假死现象。

3)仅支持Windows操作系统,不支持其他操作系统如Linux。另外,与最新的Windows 7不兼容,在Win7系统下VC 6.0安装成功后会出现无法打开cpp文件的现象。

4)界面开发功能不够强大。1.1.1 VC 6.0创建Win32控制台工程

本节主要演示利用VC 6.0创建Win32控制台工程的步骤,编程环境为VC 6.0 SP6英文版。

第一步,点击File→New,弹出New对话框,如图1-1所示。选择左上角标签的“Projects”,在列表框中选择“Win32 Console Application”,并且将右边的“Project name”和“Location”分别设置好,点击OK按钮。本步骤的功能是:选择工程类型,设置工程名与工程路径。在VC 6.0下代码均以工程的形式出现,不像DOS下以单一文件出现。示例中工程名为“myTestProject”,工程路径为“D:\TEST\”。图 1-1 New对话框

第二步,点击OK按钮后,又弹出一个对话框,如图1-2所示,选择所创建控制台工程的类型。对话框中有四个选项“An empty project”、“A simple application”、“A‘Hello World!’application”、“ANpplication that supports MFC”。a图 1-2 Win32 Consol Application

若选择An empty project项将生成一个空的工程,工程内不包括任何东西,如任何h文件和cpp文件。

若选择A simple application项将生成包含一个空的main函数的cpp文件和一个空的头文件的工程。

选择A“Hello World!”application项与A simple application项没有什么本质的区别,仅在main函数内部出现hello world的输出语句。

若选择ANpplication that supports MFC项将可以利用VC 6.0所提a供的类库来编程。

第三步,我们从一个空的工程来开始我们的工作,以便更清楚地展示编程的各个环节。选择An empty project项,单击Finish按钮,这时VC 6.0会为你生成一个小型报告,报告的内容是刚才所有选择项的总结,并且询问你是否接受这些设置。如果接受,单击OK按钮,否则单击Cancel按钮。执行完上述操作后进入到真正的编程环境,如图1-3所示,界面分为四个部分:

屏幕的最上面是菜单和工具条,在工具条上可通过右键设置显示哪些工具条。·

屏幕左边有一个Workspace窗口,窗口中默认包含两个标签,一个是ClassView,·一个是FileView。ClassView中列出的是这个工程中所包含的所有类的信息,当然本书程序为C语言程序,均不涉及类,因而当前ClassView标签下是空的。FileView标签中列出的是这个工程包含的所有文件的信息。打开该标签下所有层次会发现有三个文件夹,Source Files文件夹中包含了工程中所有的源文件,Header Files文件夹中包含了工程中所有的头文件,Resource Files文件夹中包含了工程中所有的资源文件。所谓资源就是工程中所用到的对话框、菜单、位图、加速键等信息,这些在图形界面应用程序中会应用到,而在本书中编程均为控制台程序,不会涉及这一部分内容。当前工程为一个空工程,因而现在FileView中也不包含任何东西。在本书后续截图中Workspace窗口中除了FileView标签和ClassView标签外,还包含VA View和VA Outline标签。后面这两个标签是安装Visual Assist插件后产生的。Visual Assist是Visual Studio系列编程工具中著名的插件,能自动识别各种关键字、系统函数、成员变量,自动给出输入提示,自动更正大小写错误,自动标示错误等,有助于提高开发过程的自动化和开发效率。

·屏幕的右边是视图区,打开的文件将在视图区显示出来。

·屏幕的下端是Output窗口,程序编译调试、代码查找结果等信息将在Output窗口中显示输出。图 1-3 VC 6.0编程界面

通过之前的步骤,生成一个空的工程。下面我们将循序渐进地生成我们的程序。

首先生成一个源文件,选择菜单Project中子菜单Add To Project下的New项,或者选择菜单File下的New项,在出现的对话框中选择Files标签,在列表框中选中C++Source File项,选中Add to project复选框,在下拉列表框中选中刚创建的工程myTestProject,然后在File文本框中为将要生成的文件取一个名字,我们为文件取名为main.cpp,并在Location文本框中为文件选择一个存储目录,如图1-4所示。图 1-4 工程中新建cpp文件

在File栏输入文件名,示例中输入文件名main.cpp,点击OK按钮后在该工程下创建main.cpp文件。1.1.2 程序编译及异常原因分析

本节中通过一个示例程序演示程序编译及调试步骤。示例代码实现如下功能:从键盘中输入一个a~z间的字符,验证输入。输入不满足要求时,循环输入。

在main.cpp函数里输入程序代码:

#include<stdio.h>

int main(int argc,char*argv[])

{

char chInput=‘0’;

printf(“本程序功能:\n1验证字符输入,不满足要求时循环输入;”“\n2清空输入缓冲区函数fflush(stdin)的演示\n\n”);

printf(“请输入a-z之间字符:”);

scanf(“%c”,&chInput);

while(chInput>‘z’||chInput<‘a’)

{

//fflush(stdin); //清空输入缓冲区

printf(“\n输入字符不在a-z之间,请重新输入。”);

printf(“请输入a-z之间字符:”);

scanf(“%c”,&chInput);

}

printf(“输入正确!\n”);

return 0;

}

1.编译运行及结果分析

点击菜单Build→build(工程名).exe或工具栏上的按钮编译链接生成可执行程序。

程序运行界面如图1-5所示图 1-5 程序运行界面

程序运行,发现存在异常。当输入一个不在a~z之间的字符时,会连续输出两次提示信息,如图1-6所示。

若输入多个不在a~z间的字符,程序出现异常状况,如输入“123”,“67”,程序异常行为如图1-7所示。

程序异常分析:程序中是通过语句scanf(“%c”,&chInput)从键盘中输入数据对变量赋值的。当键入字符A并按下Enter键进行确认时,输入缓冲区存在两个字符的输入:1为‘A’,2为Enter键对应的字符(ASCII码为十进制的13)。图 1-6 程序运行异常情况一图 1-7 程序运行异常情况二

程序异常原因:未清空输入缓冲区,把Enter键对应的字符也赋给变量,因而输出两次错误提示信息。

修改程序,取消代码中“//fflush(stdin);”处的注释。

编译运行结果如图1-8所示,满足编程要求。图 1-8 修改后的程序运行结果

2.清空缓冲区的方法

通过fflush(stdin)操作输入流(清空输入流),是对C标准的扩充(MSDN文档中写着:fflush on input stream is an extension to the C standard)。本书中介绍的Dev-C++、VC 6.0、VS 2008编辑器均支持这个功能。

若编译器(如GCC 3.2)不支持fflush(stdin)这种方法清空输入缓冲区,可采用“while((c=getchar())!=‘\n’&&c!=EOF){;}”方法清空输入缓冲区,将示例代码中的fflush(stdin)换成该语句,同时增加字符变量c的定义语句“char c”,编译即可。1.1.3 VC 6.0调试

一般情况下,VC 6.0中从AppWizard创建的工程中自动包含调试信息。若当前工程配置中不支持调试,需要在菜单Project→Setting中设置。

1.1.2节中直接给出了代码运行异常的原因,但实际编程过程中,需要进行调试才能分析出具体的错误原因或异常原因。下面以上节代码为例,介绍VC 6.0的Debug调试的一般步骤。

前面提到过,Debug调试的一般步骤为:设置断点、开始调试、添加查看、单步调试、停止调试,下面分别介绍。

1.设置断点

断点是调试器设置的一个代码位置,是最常用的调试方法。进行调试时,一开始程序处于运行状态。运行到断点处,程序中断执行,回到调试器,由运行状态转换到调试状态。调试时,只有设置了断点并使程序回到调试器,才能对程序进行在线调试。

可以通过下述方法设置一个断点。首先把光标移动到需要设置断点的代码行上,然后按如下四种方式操作设置断点:

1)按F9快捷键。

2)按快捷键Ctrl+B或Alt+F9,或者通过菜单Edit/Breakpoints打开Breakpoints对话框。打开后在Location标签下点击Break at编辑框右侧的箭头,选择合适的位置信息。一般情况下,直接选择line×××就足够了,如果想设置不是当前位置的断点,可以选择Advanced,然后填写函数、行号和可执行文件信息。还可以在Data标签下设置数据断点,调试过程中当输入变量改变时或者输入表达式成立时触发断点;在Message标签下设置消息断点,当程序产生某条消息时触发断点(数据断点和消息断点为较高级的断点设置,后文中若没有特别说明,断点均指位置断点)。

3)点击右键,选择Insert/Remove Breakpoint,如图1-9所示。

4)点击工具栏按钮。图 1-9 断点设置

若断点为位置断点,设置成功后,会在相应代码行前显示。本例中,程序运行后发现输出提示信息异常,因而在while循环体内第一条语句前设置断点,如图1-10所示。图 1-10 断点设置成功

2.开始调试

开始调试后,程序一开始处于运行状态。运行到位置断点代码处暂停,处于调试状态。点击菜单Build→Start Build→Go或者按F5快捷键,或者点击工具栏按钮进行调试。

输入字符“A”并按Enter键回车后,程序运行到断点处暂停,返回调试器。此时程序处于调试状态下,如图1-11所示。图 1-11 调试状态图一显示当前程序暂停的位置(位于待运行代码行前)。

图1-11表示,程序在断点所处代码行运行前暂停,即在第一次while循环体执行前暂停,并返回调试器。

3.添加查看

图1-11中代码窗口下侧为调试程序时经常使用到的两个调试窗口,Variables窗口和Watch窗口。在菜单View→Debug Window下可以设置是否显示这两个窗口。

Variables窗口:Variables窗口包含三个选项卡。Auto选项卡显示运行程序当前行以及上一行中所使用的变量;Locals选项卡显示在当前执行的函数内具有局部定义的所有变量(包括局部变量和传入函数的参数);this选项卡显示this指针当前所指向的对象内部的成员变量。

可以通过Variables窗口修改简单类型变量的当前值(比如:int、double),只要在窗口中双击该值就可以修改了。

Watch窗口:可以在Watch窗口中手工将表达式输入到Name域中,或者拖曳表达式,或者从剪贴板粘贴。Watch窗口中也可以修改简单类型的变量的值。

通常调试人员将希望关注的变量加入Watch窗口,以监视整个调试过程中该变量的变化情况。

例如,本例中输出提示信息异常,因而需要监视chInput变量的变化情况。图1-11中将chInput变量加入Watch窗口,当前chInput值为65(字符‘A’的ASCII码)。

4.单步调试

单步调试动作按钮包括:、、和,下面分别介绍。step into(F11键)表示程序从当前位置开始单步运行,遇到函数调用则进入到函数定义中执行。step out(Shift+F11组合键)表示程序跳出当前函数定义,直接执行函数调用的下一行(与step into配套使用)。step over(F10键)表示程序从main函数开始单步执行,遇到函数调用则越过函数定义执行调用的下一行。run to cursor(Ctrl+F10组合键)表示程序从main函数或当前运行位置开始,执行到光标所在行。

在图1-11状态下,连续使用step over进行调试,观察程序运行过程。程序在执行完一次while循环体后,判断chInput的值满足循环条件,继续执行第二次循环(也可在图1-12所示。

1-11状态下,按F5键或点击工具栏按钮继续调试),程序第二次在断点处暂停,如图由此可发现程序的错误,并可以分析出异常原因。如1.1.2节所述,程序异常原因是未清空输入缓冲区,把Enter键对应的字符也赋给变量,因而输出两次错误提示信息。

找到程序异常原因后即可修改程序,使其符合设计目标。修改程序,取消代码中“//fflush(stdin);”的注释,编译运行即可。图 1-12 调试状态图二

5.停止调试

停止调试分为:

自动停止调试:程序退出时,调试过程自动结束。

手动停止调试:点击菜单Debug→Stop Debugging或工具栏上的按钮结束调试。1.2 VS 2008简介

Visual Studio的新版本为2010版,简写为VS 2010。但VS 2010耗费资源较大,在程序开发人员中认可度不高,因而本书中仍将Visual Studio 2008(简写为VS 2008)作为较新版本向读者进行介绍。

VS 2008是微软公司于2007年年底发布的面向Windows Vista、Office 2007、Web 2.0的下一代开发工具,对之前的版本进行了全面的升级,引入了250多个新特性,如语言更为简洁,整合了对象、关系型数据、XML的访问方式;支持项目模板、调试器和部署程序;集成了ASP.NET Ajax 1.0,支持Web应用的高效开发;支持Office应用和Mobile应用的开发。

借助VS 2008,开发人员能够快速创建高质量、用户体验丰富而又紧密联系的应用程序,充分展示了Microsoft开发智能客户端应用程序的构想。同时VS 2008使得采集和分析信息更为简单、便捷,业务决策也更为有效。

针对开发人员,VS 2008在三个方面提供了关键改进:

首先,应用程序开发更简捷、快速。从建模、编码到调试,VS 2008提供了增强的编程语言、设计器、编辑器以及与数据相关的新功能,以快速开发程序,同时支持在同一开发环境内创建面向多个.NET Framework版本的应用程序。

例如:编程人员可以利用语言集成的查询(LINQ)功能,轻松地构建解决方案以分析和处理信息;编程人员能够在同一开发环境内构建面向.NET Framework 2.0、3.0或3.5的应用程序。

其次,用户体验显著增强。VS 2008提供了新的工具,可在如Web、Windows Vista、Office 2007、SQL Server 2008和Windows Server 2008等新平台上进行使用。编程人员可利用这些工具快速创建个性化、用户体验丰富以及紧密联系的应用程序。

例如:使用Web、ASP.NET Ajax及其他新技术,开发人员能够迅速创建更高效、交互式更强和更个性化的新一代Web体验。

最后,有助于提高团队协作效率。为了提高团队协作效率,VS 2008提供了帮助开发团队改进协作和服务的项目,例如提供工具,可将数据库专业人员和图形设计人员加入到开发流程中。1.2.1 VS 2008创建Win32控制台工程

在当前编程环境(VS 2008中文版)下,创建一个简单Win32控制台项目的步骤如下:

1)点击菜单文件→新建→项目,进入新建项目对话框。

2)在项目类型中选择其他语言下的“Visual C++”,在模板中选择“Win32控制台应用程序”,在名称栏输入项目名,选择项目存储位置,点击“确定”按钮。

3)在Win32应用程序向导中按默认选项,连续点击“下一步”按钮。创建项目,或者直接点击“完成”按钮创建项目。

4)简单Win32控制台项目创建完毕。1.2.2 VS 2008调试

VS 2008中的断点调试步骤与VC 6中的相近,具体如下:

1)点击增加断点:将光标定位到程序中希望增加断点处,点击菜单调试→切换断点,增加/移除位置断点,也可采用右键点击断点→插入断点这种方式。断点增加成功后,如图1-13中“断点位置”标记所示。

2)在开始调试:点击菜单调试→启动调试或者按钮进行调试,参见图1-13中“调试按钮”标记。程序当前执行位置参见“程序执行位置”标记。

3)添加监视:在监视窗口中,输入待监视变量的名称,即可在调试过程中监测变量的值和运行状态。参见图1-13中“监视窗口”标记,与VC 6中的Watch类似。

4)单步调试动作:各单步调试动作(如下一步、跳过等)与VC 6中各调试动作功能相同。

5)停止调试:点击菜单调试→停止调试或点击工具栏按钮。图 1-13 VS 2008调试状态1.3 Dev-C++简介

Dev-C++是Windows系统下的一种C/C++程序的集成开发环境,遵循C/C++标准,使用MinGW32/GCC编译器。

Dev-C++具有良好的开放性,它与免费的C++编译器和类库相配合,共同提供一种全开放、全免费的方案。它是一款用Delphi开发出来的自由软件,遵守GPL协议,拥有对其一切工具自由使用的权利,包括取得它的源代码。作为一款自由软件,Dev-C++在全球开发人员的努力下,不断发展进步,已经成为一款非常实用的编程软件。

Dev-C++集成开发环境包括多页面窗口、工程编辑器以及调试器等。工程编辑器中集合了编辑器、编译器、链接程序和执行程序;提供可定制的高亮度语法显示,支持代码自动补全,以减少编辑错误和简化编程工作;提供完善的调试功能,适合初学者与编程高手的不同需求。

Dev-C++支持多种语言,多国语言版中包含简、繁体中文语言界面及技巧提示,另外还有英语、俄语、法语、德语、意大利语等二十多个国家和地区语言提供选择。

Dev-C++的优点如下:

1)是免费软件,不涉及版权使用问题。

2)使用MinGW32/GCC编译器,支持交叉编译,例如可在Dev-C++中配置ARM交叉编译环境。

3)编译器对C++标准支持程度高,并支持诸多第三方库。

4)编译器和IDE都提供源代码。

Dev-C++的缺点如下:

1)GDB调试和代码跟踪能力不够强大。

2)断点调试功能不如VC。

3)图形界面程序的开发能力弱。1.3.1 Dev-C++创建Win32控制台工程

在当前编程环境(Dev-C++4.9.9中文版)下,创建一个简单Win32控制台工程的步骤如下:

1)点击菜单文件→新建→工程,进入工程创建对话框。

2)在工程类型中选择console application,在名称栏中输入工程名,工程语言设置选择C工程或C++工程,点击“确定”按钮。

3)选择该工程文件“工程名.dev”的保存位置,点击“保存”按钮。

4)Win32控制台工程创建完毕。1.3.2 Dev-C++调试

Dev-C++的断点调试步骤与VC 6相近,具体如下(本节使用代码与上节中相同):

1)设置断点:将光标定位到程序中希望增加断点处,点击菜单调试→切换断点,增加/移除断点。断点增加成功后,参见图1-14中“断点位置”标记所示。图 1-14 Dev-C++调试状态

2)开始调试:点击菜单调试→调试,或按钮进行调试,参见图1-14中“工具栏调试按钮”标记。程序当前执行位置参见“程序执行位置”标记。

3)添加/移除查看:点击添加查看、移除查看按钮,可在调试过程中监测变量的值和运行状态。参见图1-14中“添加/移除查看”标记和“查看窗口”标记,与VC 6中的Watch类似。

4)单步调试动作:各单步调试动作(如下一步、跳过等)与VC 6中各调试动作功能相同。

5)停止调试:在调试状态下,点击菜单调试→停止或按钮。1.4 Eclipse平台简介

Eclipse是著名的跨平台的自由集成开发环境(IDE),其特点如下:

1)Eclipse平台是用Java语言编写的,因此具有跨平台特性,即在Linux和Windows平台下皆可使用Eclipse。其跨平台性降低了编程人员在不同平台下编程时熟悉IDE的难度。

2)Eclipse最初用于开发Java程序,后来逐渐发展为一个各种程序语言的IDE,只要安装相应的插件即可。目前的主流程序语言,如C/C++、C#、Java、PHP、Perl、Python、Ruby、Rebol、JavaScript、SQL、XML、UML等,皆可在Eclipse上撰写。例如:若要在Eclipse中开发C/C++程序,需安装CDT(C/C++Development Toolkit)插件,并进行相关配置。

Windows或Linux系统下Eclipse平台的C/C++编程环境搭建过程类似,均较为复杂,本书仅简单介绍Window下的Eclipse环境搭建过程。

Windows下搭建Eclipse平台的C/C++编程环境,需要按顺序安装以下软件:

1)Java Runtime Environment.

要在Eclipse平台下进行C++应用程序开发,首先要使用Eclipse。而Eclipse本身是Java应用程序,因此需要安装Java Runtime Environment(JRE)—Java应用程序的必备运行环境。Eclipse的最新版本是Eclipse Classic 4.2,它要求使用JRE V1.4或更高版本。如果还需要使用Eclipse进行Java语言编程,则需要安装Java Development Kit(JDK)。

2)Eclipse.

需要安装Eclipse。Eclipse最新版本是Eclipse Classic 4.2。

3)CDT.

CDT(Eclipse C/C++Development Toolkit)是一种Eclipse插件,能把Eclipse从Java IDE转换为功能强大的C/C++IDE,同时将许多深受Java开发人员喜爱的Eclipse的优秀功能提供给C/C++开发人员,例如项目管理、集成调试、类向导、自动构建、语法着色和代码完成。

4)MinGW.

Eclipse和CDT中不包含C/C++的编译器,因此需要安装MinGW或Cygwin作为编译器。MinGW和Cygwin是获取GNU toolchain的两种主要方式,其中MinGW避开了GPL协议,同时能与CDT完美整合,因而推荐安装。第2章编码风格

编码风格旨在使代码更容易阅读、分享和检查。编译器虽然不会挑剔难看的代码,然而代码主要是写给人看的,代码和语言文字一样是为了表达思想、记载信息,所以一定要写得清楚、整洁。2.1 文件结构

C++/C程序通常由头文件和定义文件组成。头文件用来保存程序的声明,以“.h”为文件后缀。定义文件用来保存程序的实现,C程序以“.c”为文件后缀,C++程序以“.cpp”为文件后缀。2.1.1 头文件的结构

头文件由文件注释、预处理、函数声明等部分组成。一般来说,头文件中只存放声明而不存放定义,定义存放在与头文件对应的定义文件中。

标准库的头文件用#include<filename.h>格式来引用;非标准库的头文件用#include“filename.h”格式来引用。

如果一个工程的头文件数目较多,应将头文件和定义文件分别保存于不同的目录以便维护。为了防止头文件被重复引用,可用ifndef/define/endif结构产生预处理块。2.1.2 定义文件的结构

定义文件由文件注释、头文件引用、程序实现体等部分组成。2.2 程序排版和注释

程序排版和注释非程序功能的组成部分,但清晰、美观的排版和准确、简洁的注释均可增强程序的可读性。2.2.1 缩进与对齐

缩进可以体现语句块的层次关系。一般采用4个空格或1个Tab字符缩进。若采用Tab字符缩进,可将编辑器Tab字符宽度设置为4。不要在代码中混合使用Tab字符和空格来进行代码缩进。2.2.2 空行

使用空行的目的在于分隔程序段落,使程序布局更加清晰。每个函数定义之后应加空行。函数体内一组变量定义之后应加空行,函数体内一段逻辑相对独立的代码之后应加空行。2.2.3 代码行

一行代码只做一件事会使程序易于阅读和注释。如果可能,则应在定义变量的同时初始化。

if、for、do、while、switch等语句应单独成行,其执行语句部分应另起一行,并且即使执行语句只有一行也应用花括号括起来。例如:

if((tmp=fopen(“tmp.txt”,“w”))==NULL){

printf(“Can’t create tmp.txt file\n”);

}

长句(大于80个字符)应拆行,拆分出的新行要进行适当的缩进,使排版整齐,语句易读。例如:

struct key keyTable[]={

“auto”,0,

“break”,0,

“case”,0,“char”,0,“const”,0,“continue”,0,

“default”,0,“do”,0,“double”,0,

“else”,0,“enum”,0,“extern”,0,

……

};

fprintf(fp,“%s%c%s%s\n”,(p->data).name,(p->data).sex,(p->data).tel,(p->data).email);

printf(“This is such a long sentence that”

“it cannot be held withiN line\n”);a2.2.4 空格

一元运算符前后不要空格,二元运算符两侧应有一个空格。例如:

i++;

i=i+1;

操作符‘[]’,‘→’,‘.’前后不要空格。例如:

strcpy((n->data).name,buffer.name);

关键字if、for、do、while、switch等与其后的控制表达式的左括号‘(’之间应有一个空格,但左括号‘(’的右边及右括号‘)’的左边不要空格。当if、for、while、switch等语句采用紧凑型写法时,右括号‘)’与左花括号‘{’之间应有一个空格。for语句分号‘;’后应有一个空格。例如:

for(i=0;i<c;i++){

if(strcmp(r[i].email,e)==0){

return i;

}

}

函数参数个数大于1时,每个逗号‘,’后面应有空格。函数名与紧跟的左括号‘(’之间不要空格。例如:

int MyStrncmp(const char*s1,const char*s2,int len);2.2.5 对齐

语句if、for、do、while、switch等有“紧凑型”和“清晰型”两种对齐风格,应保持风格一致,不要混合使用。例如:

/*紧凑型*/

if(argc<2){

int i;

……

}

/*清晰性*/

if(argc<2)

{

int i;

……

}

定义函数时,左花括号另起且独占一行,并与函数对齐。{}之内的代码块在‘{’右侧4个空格或Tab字符处左对齐。例如:

int MyStrlen(const char*s)

{

int length=0;

……

}2.2.6 间接访问操作符‘*’

操作符‘*’靠近数据类型时,语义直观,但容易造成误解,操作符‘*’靠近变量名可避免误解。例如:

int*x,y; /*操作符*靠近数据类型,y容易被误解为指针变量*/

int*x,y; /*操作符*靠近变量名,y不会被误解为指针变量*/2.2.7 注释

注释有助于程序的阅读,注释语言必须准确、简洁。注释主要说明代码“能做什么”,而非“怎样做”,“怎样做”由代码本身说明。

函数、变量、常量等标识符的命名应尽量体现其含义,以减少不必要的注释。

应边写代码边注释,修改代码的同时修改注释。

1.文件注释

文件注释位于头文件和定义文件的开头,内容可包括版权信息、文件名称、文件描述、当前版本号、作者、修改者、完成日期等。本书中的示例文件注释仅列出了文件名、文件描述和作者。例如:

/*

*文件名:keyword.c

*描述:统计C程序中的关键字

*作者:刘博

*/

2.函数注释

函数注释内容可包括函数功能、输入参数、输出参数、返回值等,写在函数定义之上,与函数定义之间不留空行。例如(本书中的示例函数注释仅列出了函数功能):

/*

*函数功能:计算字符串s的长度

*输入参数:字符串s

*输出参数:无

*返回值:字符串长度

*/

int MyStrlen(const char*s)

{

……

}

3.代码行注释

注释应与被描述的代码相邻,可以放置于代码的上方或右方。函数、变量、常量等标识符的命名若无法充分体现其含义,应进行注释。代码块行数较多或者逻辑较复杂时,应在段落结束处进行注释。2.3 命名规则

制定命名规则的目的是增强程序的可读性,命名规则并没有统一的标准,这里给出一种简单的命名规则仅供参考。

函数、变量、常量等标识符的命名要清晰,使其具有自注释性。较长的单词可取单词的头几个字母形成缩写,一些单词可采用公认的缩写。标识符应避免仅靠大小写不同来区分。

变量和参数的标识符以首单词小写,其后各单词首字母大写组成。常量以全大写字母组成,单词间可用下划线分隔。函数名由以大写字母开头的单词组成,函数名通常应包含动词。

全局变量和全局函数在整个项目中都会用到,命名要详尽。局部变量和仅在一个源文件中调用的函数的命名可以适当简略。禁止使用汉语拼音来命名,其可读性极差。

类名由以大写字母开头的单词组成。类的数据成员加前缀m_,静态变量加前缀s_,全局变量加前缀g_。例如:

int maxNumber; /*变量*/

#define MAX_LENGTH 80 /*常量*/

int MyStrlen(const char*str); /*函数及参数*/

class Example{ /*类*/

public:

Example(double min,double max);

double GetMax()const{return m_max;}

double GetMin()const{return m_min;}

private:

double m_max;

double m_max;

static int s_count;

};2.4 表达式和基本语句

用命名能体现其含义的宏或枚举代替数字常量。例如:

enum{EXIT,ADD,SEARCH,DEL,DISP}function=DISP;

switch(function){

case ADD:

Add(addressBook,&count);

break;

case SEARCH:

……

表达式中运算符较多时,应用括号明确表达优先顺序,以避免优先级错误。

switch语句即使不需要default处理,也应该保留语句default:break。goto语句会破坏程序的结构性,非需勿用。

整型变量用“==”或“!=”与0比较。指针变量用“==”或“!=”与NULL比较,尽管NULL的值与0相同,但两者意义不同,应注意区分。浮点变量用“>=”或“<=”形式与数字比较,应避免用“==”或“!=”比较。布尔变量用if(s)表示s为真,if(!s)表示s为假。各类型比较表达式如表2-1所示。2.5 函数

用void明确表示函数无参数或返回值。例如:

void DisplayMenu(void); /*无参无返回值*/

函数参数是指针且仅作输入使用时,应在类型前加const,以防止该指针所指内容在函数体内被意外修改。例如:

char*MyStrcpy(char*s1,const char*s2); /*类型前加const*/

函数体内一般应对参数的有效性进行检查。调用函数时,一般应对其返回值进行判断,对于错误的返回值,应进行相应处理。例如:

if((fp=fopen(argv[1],“r”))==NULL){

printf(“Can’t open%s\n”,argv[1]);

exit(1);

}第3章文件类文件可分为文本文件和二进制文件两种。文本文件可用来保存字符,文件中的字节是字符的编码,源文件是文本文件。二进制文件可用来保存可执行文件,文件中的字节是机器指令或数据编码。C语言程序有3个预定义的文本流在程序执行时默认打开:标准输入(stdin)、标准输出(stdout)和标准错误(stderr)。文件的读写属于I/O操作。FILE类型保存和文件有关的信息,文件的打开操作在内存中分配一个FILE类型并将其指针返回。大多数I/O函数都接受一个指向FILE类型的指针作为参数,标准I/O库函数在头文件stdio.h中声明。常用的I/O函数有:·FILE*fopen(const char*filename,const char*mode)函数:用来打开文件流,接受文件名filename和打开模式mode两个字符串参数,返回一个FILE*类型的指针。若打开文件时遇到错误,则fopen函数返回null指针。fopen常用打开模式如表3-1所示。·int fclose(FILE*stream)函数:用来关闭一个打开的流stream并清除其所有内部数据缓冲区。如关闭时遇到错误,则返回EOF,否则返回0。fopen和fclose函数通常成对使用。·int fgetc(FILE*stream)函数:从流stream中读取下一个字符,并把它作为一个int类型返回。若发生错误或已经位于文件尾,函数返回EOF。·int*fputc(int c,FILE*stream)函数:把字符c写入流stream的当前位置,并将写入值按int类型返回。若发生错误,函数返回EOF。·int ungetc(int c,FILE*stream)函数:将字符c压回输入流stream,当下次读取流stream时会读取先前被压入的字符。若多次调用ungetc函数压入字符,当下次读取流stream时先前压入的字符按与压入相反的顺序读取。若函数调用成功,则返回被压入的字符c;若函数调用失败,则返回EOF。·char*fgets(char*s,int n,FILE*stream)函数:三个参数为指向字符数组起始位置的指针s、计数值n和输入流stream。函数从输入流stream读取字符到数组,直到遇到换行符、文件尾或未遇到换行符和文件尾但读取了n-1个字符。读取完毕后,数组中已读取的字符后会自动添加一个结束符‘\0’。若因读取到换行符而结束,换行符也存储在数组中,且在自动添加的结束符‘\0’之前。函数的返回值为指向字符数组起始位置的指针s,当读取任何字符之前就遇到文件结束符或错误时,返回null指针。·int fscanf(FILE*stream,const char*format,……)函数:对格式化的输入文本进行解析,从第一个输入流参数stream中读取字符,根据格式控制字符串参数对字符序列进行转换后存储到指针所指定的对象中。·int fprintf(FILE*stream,const char*format,……)函数:根据格式控制字符串参数转换字符,将其输出给第一个参数stream所指定的流。·size_t fread(void*ptr,size_t size,size_t count,FILE*stream)函数:可用来读取二进制文件,从流stream读取最多count个大小为size的元素到指针ptr指向的数组。fread函数最多读取count个元素,并返回其实际读取的元素个数,故当读到文件尾时,返回值可能小于count。若遇到错误,则返回0。·size_t fwrite(const void*ptr,size_t size,size_t count,FILE*stream)函数:可用来写入二进制文件,将指针ptr指向的数组中最多count个大小为size的元素写入流stream。fwrite函数最多写入count个元素,并返回实际写入的元素个数。除非出现错误,否则函数的返回值与count相同。·int remove(const char*filename)函数:删除filename文件。·int rename(const char*oldname,const char*newname)函数:把oldname的文件名修改为newname。3.1 文件复制【例3.1】编写文本文件复制程序,命令行格式为:mycopy filename1 filename2。

题目分析

每个C语言程序必须定义一个main函数作为程序的入口。程序启动从main函数开始执行,main函数返回时程序终止,若main函数末尾没有返回语句,则默认执行return 0语句。

标准C语言的main函数有两种形式:接受0个参数的int main(void),即int main();接受2个参数的int main(int argc,char*argv[])。对于后者,形参argc表示传递给程序的参数个数;形参argv是指针数组,其每个指针分别指向传递给程序的字符串参数,第一个字符串argv[0]是程序的名称。

文件的打开和关闭可调用fopen和fclose函数。文件的读取和写入可通过三种方式实现:1)fgetc和fputc函数配合,每次读写一个字符,见参考程序mycopyV1.c;2)fscanf和fprintf函数配合,每次读写一个字符,见参考程序mycopyV2.c;3)fread和fwrite函数配合,每次读写BUFSIZE个字符,见参考程序mycopyV3.c。方式3)通过增设缓冲区buffer[BUFSIZE],减少I/O操作的次数,提高程序运行速度,可用于读写量较大的程序。

检测到异常时,用exit标准库函数退出。void exit(int status)函数可正常终止一个程序并执行清理操作,形参status值为0表示程序成功退出,非零值可表示各类异常终止。从main函数通过return语句返回一个整数值相当于用这个整数值调用exit函数。exit函数在头文件stdlib.h中声明。

参考程序

/*

*文件名:mycopyV1.c

*描述:编写文件复制命令行程序,命令行格式为:mycopy filename1 filename2

*作者:刘博

*/

#include<stdio.h>

#include<stdlib.h>

int main(int argc,char*argv[])

{

FILE*fpSrc,*fpDes;

char ch;

/*检查命令行参数个数*/

if(argc!=3){

printf(“Usage:mycopy SourceFile DestinationFile\n”);

exit(1);

}

/*打开文件*/

if((fpSrc=fopen(argv[1],“r”))==NULL){

printf(“open file error!\n”);

exit(1);

}

if((fpDes=fopen(argv[2],“w”))==NULL){

printf(“creat file error!\n”);

exit(1);

}

/*复制文件*/

while((ch=fgetc(fpSrc))!=EOF){

fputc(ch,fpDes);

}

/*关闭文件*/

fclose(fpSrc);

fclose(fpDes);

}

/*

*文件名:mycopyV2.c

*描述:编写文件复制命令行程序,命令行格式为:mycopy filename1 filename2

*作者:刘博

*/

#include<stdio.h>

#include<stdlib.h>

int main(int argc,char*argv[])

{

FILE*fpSrc,*fpDes;

char ch;

/*检查命令行参数个数*/

if(argc!=3){

printf(“Usage:mycopy SourceFile DestinationFile\n”);

exit(1);

}

/*打开文件*/

if((fpSrc=fopen(argv[1],“r”))==NULL){

printf(“open file error!\n”);

exit(1);

}

if((fpDes=fopen(argv[2],“w”))==NULL){

printf(“creat file error!\n”);

exit(1);

}

/*复制文件*/

while(fscanf(fpSrc,“%c”,&ch)!=EOF){

fprintf(fpDes,“%c”,ch);

}

/*关闭文件*/

fclose(fpSrc);

fclose(fpDes);

}

/*

*文件名:mycopyV3.c

*描述:编写文件复制命令行程序,命令行格式为:mycopy filename1 filename2

*作者:刘博

*/

#include<stdio.h>

#include<stdlib.h>

#define BUFSIZE 1024

int main(int argc,char*argv[])

{

FILE*fpSrc,*fpDes;

char buffer[BUFSIZE];

int in,out;

/*检查命令行参数个数*/

if(argc!=3){

printf(“Usage:mycopy SourceFile DestinationFile\n”);

exit(1);

}

/*打开文件*/

if((fpSrc=fopen(argv[1],“r”))==NULL){

printf(“open file error!\n”);

exit(1);

}

if((fpDes=fopen(argv[2],“w”))==NULL){

printf(“creat file error!\n”);

exit(1);

}

/*复制文件*/

while((in=fread(buffer,1,BUFSIZE,fpSrc))>0){

out=fwrite(buffer,1,in,fpDes);

/*判断读出和写入元素个数是否一致*/

if(in!=out){

printf(“copy error!\n”);

exit(1);

}

}

/*关闭文件*/

fclose(fpSrc);

fclose(fpDes);

}3.2 文件比较【例3.2】打印出两个文本文件第一个不相同的行(每行字符数不多于80),命令行格式为:filecmp filename1 filename2。

题目分析

文件的按行读取可调用fgets标准库函数。比较字符串可调用strcmp或strncmp标准库函数。

自定义函数filecomp用来比较不同行。当找到第一个不同行时filecomp函数返回到main()函数。lp1和lp2的作用为:当filename1和filename2出现第一个不相同行时,控制循环结束;当filename1或filename2未出现不相同行但已读到文件结束符或发生读取错误时,控制循环结束。

参考程序

/*

*文件名:filecmp.c

*描述:打印出两个文本文件第一个不相同的行。

*命令行格式为:filecmp filename1 filename2

*作者:刘博

*/

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#define MAXLINE 80/*每行字符数不多于80*/

void filecomp(FILE*fp1,FILE*fp2);

int main(int argc,char*argv[])

{

FILE*fp1,*fp2;

/*检查命令行参数个数*/

if(argc!=3){

printf(“Usage:filecmp File1 File2\n”);

exit(1); /*异常退出*/

}

/*打开文件*/

if((fp1=fopen(argv[1],“r”))==NULL){

printf(“can’t open%s\n”,argv[1]);

exit(1); /*异常退出*/

}

if((fp2=fopen(argv[2],“r”))==NULL){

printf(“can’t open%s\n”,argv[2]);

exit(1); /*异常退出*/

}

filecomp(fp1,fp2);

/*关闭文件*/

fclose(fp1);

fclose(fp2);

}

/*比较两个文件第一个不同行*/

void filecomp(FILE*fp1,FILE*fp2)

{

char line1[MAXLINE],line2[MAXLINE];

char*lp1,*lp2;

do{

lp1=fgets(line1,sizeof(line1),fp1);

lp2=fgets(line2,sizeof(line2),fp2);

if(lp1==line1&&lp2==line2){

if(strncmp(line1,line2,MAXLINE)!=0){

printf(“first difference line:\nfile1:%sfile2:%s”,

line1,line2);

lp1=lp2=NULL; /*找到不同行,循环结束*/

}

}else if(lp1!=line1&&lp2==line2){

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载