c语言学习导引 15页

  • 269.77 KB
  • 2022-08-11 发布

c语言学习导引

  • 15页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档由用户上传,淘文库整理发布,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,请立即联系网站客服。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细阅读内容确认后进行付费下载。
  4. 网站客服QQ:403074932
C语言学习导引要点:★什么是程序?一般程序设计语言包含哪些功能?★一般程序设计语言在语法上包含哪些内容?★结构化程序设计有哪些基本的控制结构?★C语言有哪些特点?★C语言程序的基本框架如何?★形成一个可运行的C语言程序需要经过哪些步骤?★如何应用流程图描述简单的算法?对于将C语言作为第一门编程语言(ProgrammingLanguage)的读者来说,最关心的问题应该是如何尽快学会用C语言进行程序设计。要做到这一点,我们首先对程序设计语言,特别是C语言本身要有所了解,更重要的是通过不断的编程实践,逐步领会和掌握程序设计的基本思想和方法。熟练的编程技能是在不断的知识与经验积累的基础上发展起来的。初学编程的人一开始由于缺乏足够的语言知识和编程经验,对于很简单的问题往往也会感到无所适从,不知如何下手编写程序。本书建议你从一开始学习C语言起就要试着编写程序,可以先模仿教科书中的程序,试着改写它并逐步体会、循序渐进,直到会独立地编写程序解决比较复杂的问题。为了使读者能逐步从简单的模仿中体会程序设计的基本思想和方法,而不拘泥于具体的语法细节,本章作为这本教材的引言将简要介绍程序设计语言的功能、语法要素、C语言的特点以及程序设计求解问题的一般步骤等。1.1一个C语言程序为了让读者对C语言有一个感性认识,首先来看一下用C语言编写的一个程序。【例1-1】求阶乘问题。输入一个正整数n,输出n!。源程序#include/*编译预处理命令*/voidmain()/*主函数*/{intn;/*变量定义*/1\nintfactorial(intn);/*函数声明*/scanf("%d",&n);/*输入一个整数*/printf("%d\n",factorial(n));/*调用函数计算阶乘*/}intfactorial(intn)/*定义计算n!的函数*/{inti,fact=1;for(i=1;i<=n;i++)fact=fact*i;returnfact;}运行程序时,输入4,则输出24,即4的阶乘。当然,你可以输入别的数,输出的将是另外一个值。对于以上程序,不要求初学程序设计的读者一下子就能理解。上述程序中的许多内容将会在随后各章的内容中逐步介绍,但希望初学者能对C程序有个初步的印象。C程序是由函数(Function,一种子程序)所组成的。前面的程序涉及到4个函数:main()、factorial()、scanf()和printf()。scanf()和printf()是系统事先设计好的函数,分别用于数据的输入和输出;factorial()是程序中定义的函数,主要目的是求n!,并将n作为函数的参数;main()函数是程序的主函数。所有的C程序都有且只有一个main()。C程序都从main()函数处开始运行,而且main()函数结束时,程序也就结束了。对于上述例子,程序先执行main()函数中的scanf()函数调用,输入数据n,然后调用printf()函数,输出结果。当调用printf()函数时,必须要先知道所要输出的数据,即factorial(n)。因此,此时发生了对factorial()函数的调用(Call),调用该函数所获得的结果作为printf()函数的参数(Argument),由printf()函数负责将该值按十进制整数(%d)输出。程序最根本的是对数据的处理,为此,需要处理的数据先要将其表示出来。在这个程序的factorial()函数中,我们用整数型变量(Variable)n表示要求阶乘的整数,同样在main()函数中也用n来表示(用别的变量名字也可以,如m)。同时,在factorial()函数中,用fact()存储计算的结果,用i表示1到n之间的某个整数。程序需要对数据处理的过程进行控制。在这里,最主要的控制是将1到n的每个整数i乘到我们所要的结果变量fact中。这个控制通过for循环语句(LoopStatement)来实现。2\n)提示:变量都有类型(如整数类型int),并在内存中占有一定的空间,如在VC++中,整数变量占用4个字节的空间。这样,每个整数就都有一定的范围。所以,对于上述程序,当输入整数13时,其n!的结果就超出了整数所能表达的范围,而输出一个不正确的结果。1.2程序与程序设计语言计算机程序(Program)是人们为解决某种问题用计算机可以识别的代码编排的一系列加工步骤。计算机能严格按照这些步骤去做,包括计算机对数据的处理。程序的执行过程实际上是对程序所表达的数据进行处理的过程。一方面,程序设计语言提供了一种表达数据与处理数据的功能;另一方面,编程人员必须按照语言所要求的规范(即语法要求)进行编程。1.2.1程序与指令计算机最基本的处理数据的单元应该就是计算机的指令了。孤零零的一条指令本身只能完成计算机的一个最最基本的功能,如实现一个加法运算或实现一个大小的判别。计算机所能实现的指令的集合称为计算机的指令系统。虽然计算机指令所能完成的功能很基本,并且指令系统中指令的个数也很有限。但一系列指令的组合却能完成一些很复杂的功能。这也就是计算机的奇妙与强大功能所在。计算机一系列指令的有序组合就构成了程序。假设某台虚拟的计算机指令系统由以下几条指令,其中指令的第一部分是指令名(如Store,Add等),随后的几个部分是指令处理所涉及的数据(如x,y,z,p等):z指令1Inputx:将当前输入数据存储到内存的X单元。z指令2Outputx:将内存x单元的数据输出。z指令3Addxyz:将内存x单元的数据与y单元的数据相加并将结果存储到内存的z单元。z指令4Subxyz:将内存x单元的数据与y单元的数据相减并将结果存储到内存的z单元。z指令5BranchEqxyp:比较x与y,若相等则程序跳转到p处执行,否则还是按一般顺序执行下一条指令。z指令6Jumpp:程序跳转到p处执行。z指令7Setxy:将内存y单元的值设为x。上述简单的7条指令通过不同的组合就可以完成不同的功能。例如,下面是一段由上述一些指令组成的虚拟的程序,完成的功能是:输入3个数,将它们相加,最后输出结果。1.InputA;输入第一个数据到存储单元A中;3\n2.InputB;输入第二个数据到存储单元B中;3.InputC;输入第三个数据到存储单元C中;4.AddAB;将A、B相加并将结果存在D中;5.AddCDD;将C、D相加并将结果存在D中;6.OutputD;输出D的内容。又例如,下面一段程序通过不断执行加法(Z=Z+A)运算实现两个整数(A、B)的乘法功能,即把A累加B次就可以获得A*B的结果。1.InputA;输入第一个数据到存储单元A中;2.InputB;输入第二个数据到存储单元B中;3.Set0X;将X设为0,X用以统计A累加的次数;4.Set0Z;将Z初始值设为0,Z用以存放A*B的最后结果;5.BranchEqXB9;判别X与B是否相等;若相等说明A已累加了B次,程序跳转到第9条指令,输出结果;6.AddZAZ;Z=Z+A;7.Add1XX;X=X+1;8.Jump5;程序跳转到第5条指令,继续循环执行第6、7条指令;9.OutputZ;输出Z的值,该值等于A*B。上述程序中A、B用于存储准备相乘的两个数(第1、2指令);Z用于存储乘法运算的结果,开始时初试化为0(第4指令),随后不断将A累加到Z上(第6指令),而累加次数的控制通过X来实现;X开始时设为0(第3指令),随后A每累加一次就将X加1(第7指令);但X被累加B次时(第5指令),Z的值就是A*B的结果了,最后输出所产生的结果(第9指令)。一般情况下程序的执行是按指令排列的顺序一条一条地做的。但稍微复杂一点的程序往往需要通过判断不同的情况执行不同的指令分支,第5条指令(BranchEq)就是这种情况。另外,在许多情况有些指令需要被重复地执行,例如第6、7两条指令,所以也需要有指令能强行改变程序中指令执行的顺序,如第8条指令(Jump)。实际的程序在计算机中是以1、0组成的指令码来表示的,也就是说程序也是0、1组成的序列。当然,计算机能够识别这个序列。实际上,程序与数据一样共同存储在存储器里。当程序要运行时,当前准备运行的指令从内存被调入CPU中由CPU处理这条指令。这种将程序与数据共同存储的思想就是目前绝大多数计算机采用的冯.诺伊曼模型的存储程序概念。然而,为什么程序一定要由计算机中的指令所组成呢?一方面,通过定义计算机可直接实现的指令集使得程序在计算机中的执行变得简单,计算机硬件系统只要实现了指令就能方便地实现相应的程序;另一方面,需要计算机实现的任务成千上万,如果每一个任务都相对独立,与其它程序之间没有公共的内容,编程工作将十分困难。这就是计算机科学中很重要的一个概念—“重用”的体现。如果程序设计直接用0、1序列的计算机指令来写,那将是一件难以忍受的事。所以,人们设计了程序设计语言,用这种语言来描述程序,同时应用一种软件(如编译系统)将用程序设4\n计语言描述的程序转换成计算机能直接执行的指令序列。总的来说,计算机程序是人们为解决某种问题用计算机可以识别的代码编排的一系列数据处理步骤。计算机能严格按照这些步骤去做。1.2.2程序设计语言的功能程序设计语言是人用来编写程序的手段,是人与计算机交流的语言。人为了让计算机按自己的意愿处理数据,必须用程序设计语言来表达所要处理的数据,同时用程序设计语言来表达数据处理的流程。因此,程序设计语言必须具有表达数据和处理数据(称为控制)的能力。1.数据表达(DataRepresentation)世界上的数据有多种多样,而语言本身的描述能力总归是有限的。为了使计算机程序设计语言能有效地、充分地表达各种各样的数据,一般将数据抽象为若干种类型。数据类型(DataType)是对某些具有共同特点的数据集合的总称。如,平常我们所说的整数、实数就是数据类型的例子。对数据类型来说,涉及两方面的内容:即该数据类型代表的数据是什么(数据类型的定义域)、能在这些数据上做些什么(即操作或称运算)。例如,我们大家熟悉的整数类型所包含的数据是{…,-2,-1,0,1,2,…},而+、-、*、/就是作用在整数上的运算。在程序设计语言中,一般都事先定义好几种基本的数据类型,供程序员直接使用,如整型、实型(浮点型)、字符型等。这些基本数据类型在程序中的具体对象主要是两种形式:常量(又称常数Constant)与变量(Variable)。常量值在程序中是不变的,例如123是一个整数常量,12.3是一个实型常量,’a’是一个字符常量。变量则可对它做一些相关的操作,改变它的值。例如,在C语言中可以通过“inti”来定义一个新的变量i,然后就可以对该变量进行某种操作,例如赋值(如,i=20;)。同时,为了使程序员能更充分地表达各种复杂的数据,程序设计语言还提供了构造新的具体数据类型的手段,如数组(Array)、结构(Structure)、文件(File)、指针(Pointer)等。例如,在C语言中可以通过”inta[10]”来定义一个由10个整数组成的数组变量。这样变量a所代表的就不是一个整数,而是10个整数组成的有序序列,其中的每一个整数都叫a的分量。程序设计语言提供的基本数据类型以及构造复杂类型的手段,如数组、结构等,为有限能力的程序设计语言表达客观世界中多种多样的数据提供了良好的基础。2.流程控制(FlowControl)程序设计语言除了能表达各种各样的数据外,还必须提供了一种手段来表达数据处理的过程,即程序的控制过程。程序的控制过程通过程序中的一系列语句来实现。当要解决的问题比较复杂时,程序的控制过程也会变得十分复杂。一种比较典型的程序设计方法是:将复杂程序划分为若干个相互独立的模块(Modular),使完成每个模块的工作变得单纯而明确,在设计一个模块时不受其它模块的牵连。同时,通过现有模块积木式的扩展就可以形成复杂的、更大的程序模块或程序。这种程序设计方法就是结构化的程序设计方法(StructuredProgramming)。C语言就是支持这种设计方法的典型语言。在结构化程序设计方法中,一个模块可以是一条语句(Statement)、一段程序或一个函数(Function)(子程序)等。5\n一般来说,从程序流程的角度看,模块只有一个入口、一个出口。这种单入、单出的结构为程序的调试(查错debug)提供了良好的条件。多入多出的模块结构将使得程序的调试变得异常困难。按照结构化程序设计的观点,任何程序都可以将模块通过三种基本的控制结构进行组合来实现。这三种基本的控制结构是:(1)顺序控制结构(Sequentialcontrolstructure):一个程序模块执行完后,按自然顺序执行下一个模块。(2)分支控制结构(Branchcontrolstructure)(又称选择结构):计算机在执行程序时,一般是按照语句顺序执行的,但在许多情况下需要根据不同的条件来选择所要执行的模块。例如,检测某种条件是否满足,如果条件满足执行某些指令,否则执行另外一些指令。象我们周末时,根据天气情况决定去郊游还是在房间里学习,就是一种分枝控制。(3)循环控制结构(Loopcontrolstructure):有时,经常需要重复地执行某些相同的处理过程,即重复执行某个模块。当然,重复执行这些模块一般是有条件的。也就是说,检测某些条件,如果条件满足就是重复执行相应的模块。顺序结构是一种自然的控制结构,通过安排语句或模块的顺序来实现。所以,对一般程序设计语言来说,需要提供表达分支控制和循环控制的手段。以上三种控制方式称为语句级控制。它实现了程序在语句间的跳转。例如,对于1.2.1中求两个整数(A、B)相乘的例子,该程序实际上存在着问题:当B为负数使该程序将终止不了!如果B是负数,我们可以将A、B均乘上-1,再应用1.2.1中的思路求解,就可得到正确的结果。其求解过程大致可描述如下:1.分别输入两个数到A、B两个变量;2.如果B是负数,那么B=B*(-1),A=A*(-1);3.设X=0,Z=0;4.当X不等于B,重复做以下操作:zZ=Z+A;zX=X+1;5.输出Z。上述处理过程基本上是从步骤1顺序做到步骤5,其中步骤2就是一种分支控制,而步骤4就是循环控制。当我们要处理的问题较复杂时,为了增强程序的可读性以及便于程序维护,往往将程序分为若干个相对独立的子程序。例如,在C语言中,子程序的作用是由函数来完成的。函数通过一系列语句的组合来完成某种特定的功能(如,求整数n的阶乘)。当程序一些地方需要相应功能时,不用重新写一系列代码,而是直接调用就可以了,并根据需要传递不同的参数(如求n阶乘函数中的n)。同一个函数可以被一个或多个函数(名括自己)调用任意多次。函数调用时可传递零个或多个参数(Argument),函数被调用的结果将返回给调用函数。这种涉及函数定义和调用的控制称为单位级控制。所以,程序设计语言的另一个功能就是提供单位级控制的手段,即函数的定义(Definition)与调用(Call)手段。6\n1.2.3程序设计语言的语法程序员利用程序设计语言来编写他想要的程序以处理相应的问题。在程序中,可能要表达数据,包括定义相应的用于存储数据的变量;还要用程序设计语言来描述需要的数据处理过程,包括语句间的控制和子程序间的控制。为了让计算机能理解程序员在程序中所描述的这些工作,用程序设计语言所写的程序必须符合相应语言的语法(Grammar)。编写程序就象用某种自然语言(如中文)来写文章,首先语法要通,即要符合语言所规定的语法规则。当然,语法通了并不意味着你的文章就符合要求了,你有可能词不达意、离题万里。后者就是我们在程序调试(查错)时需要发现的事,即找出程序中的错误(非语法错误)。这是一个非常需要耐心和经验的过程。而语法错误的检查则要相对容易得多。一般我们把用程序设计语言所编写的未经编译的程序称为源程序(SourceCode,又称源代码)。从语法的角度看,源程序实际上是一个字符序列。这些字符序列按顺序分别组成了一系列“单词”。这些“单词”包括语言事先约定好的保留字(ReservedWords,如用于描述分支控制的if、else,用于描述数据类型的int等)、常量(Constant)、运算符(Operator)、分隔符以及程序员自己定义的变量名、函数名等。在这些“单词”中,除了运算符(如+、-、*、/)、普通常量(如-12、12.34、’a’)、分隔符(如“;”、“(”、“)”等)外,其它主要是有关用来标识(表示)变量、函数、数据类型、语句等的符号,这些标识符号就叫标识符(Idendifier)。任何程序设计语言对标识符都有一定的定义规范,即只要满足这些规范的字符的组合才能构成该语言所识别的标识符。例如,例1-1程序中include、int、factorial、n、fact、for、i、return等都是标识符。“单词”的组合形成了语言有意义的语法单位,如变量定义、表达式(Expression)、语句、函数定义等。一些简单语法单位的组合又形成了更复杂的语法单位,最后一系列语法单位组合成程序。就象在作文中,单词组合成主语、谓语、宾语等,而主语、谓语、宾语又组合成句子,简单的句子又可以组合成更复杂的句子,句子又组合成段落,段落组合成文章(相当于我们的程序)。例如,对例1-1的程序,”inti,fact=1;”是若干“单词”组合成变量定义;“fact=fact*i”是若干“单词”组成的表达式,后面加“;”后形成了一个简单语句,而该语句又与“for(i=1;i<=n;i++)”组合成一个循环语句。计算机要理解程序,首先要识别出程序中的“单词”,继而识别出各种语法单位。当计算机无法识别程序中的“单词”和语法单位时,说明该程序出现了语法错误。这些识别工作是由编译程序来做。下面就以C语言为例,简要说明C语言最主要的语法要素。1、C语言的主要“单词”(1)标识符。C语言的标识符规定由字母、数字以及下划线组成,且第一个字符必须是字母或下划线。如,_name1是一个合法的标识符,而left&right就是非法的。在C语言中,标识符中的字母大小写是有区别的。最主要的标识符是:保留字和用户自定义标识符。(2)保留字。也称关键字,它们是C语言规定的、赋予它们以特定含义、有专门用途的标7\n识符。这些保留字也主要与数据类型和语句有关。如int(整数类型)、float(浮点数类型)、char(字符类型)、typedef(类型定义)、以及与语句相关的if、else、while、for、break等。(3)自定义标识符。包括在程序中定义的变量名、数据类型名、函数名以及符号常量名。一般来说,为了便于程序阅读,经常取有意义的英文单词作为用户自定义标识符(如前面程序中定义的n、fact等)。(4)常量。常量是有数据类型的,如,整型常量123、实型常量12.34、字符常量’a’、字符串常量“helloworld!”等。(5)运算符。代表对各种数据类型实际数据对象的运算。如,+(加)、-(减)、*(乘)、/(除)、%(求余)、>(大于)、>=(大于等于)、==(等于)、=(赋值--assignment)等。绝大多数运算为双目运算(涉及两个运算对象),也有单目(涉及一个运算数)和三目(三个运算数)运算,如C语言中的条件运算“?:”就是一个三目运算。(6)分隔符,如:;、[、]、(、)、#等。2、C语言的主要语法单位(1)表达式。运算符与运算对象(可以是常量、函数、变量等)的有意义组合就形成了表达式。如,2+3*4、i+2b)是否成立,来决定执行“x=a;”(如果成立)还是“x=b;”(如果不成立)。if(a>b)x=a;elsex=b;z循环语句:c语言实现循环控制的过程具体有三种形式,即while语句、for语句、do-while语句等。如,下列while循环语句就是实现求1到100的和,并把结果存在变量sum中。在这个循环中,(i<=100)是循环执行的条件,即只要这个条件被满足,一对“{…}”中的循环体就会一直循环执行。应该注意到,由于循环体每循环一次,i被加1(”i=i+1”),所以,当循环到一定的时候,i的值就会超过100,即循环条件(i<=100)不再被满足了。此时,循环结束。sum=0;/*初始化sum和i*/i=1;while(i<=100){/*通过循环把1、2、…100分别加到sum中*/8\nsum=sum+i;i=i+1;}z复合语句(Compoundstatement):通过一对大括号“{}”,将若干语句顺序组合在一起就形成了一个程序段。如,前面while语句中的“{sum=…}”。(4)函数定义与调用。函数是完成特定任务的独立模块,是C语言唯一的一种子程序形式。通常,函数的目的是接收0个或多个数据(成为函数的参数),并至多返回一个结果(称为函数的返回值)。函数的使用最主要涉及到函数的定义与调用。函数定义的主要内容是通过编写一系列语句来规定其所完成的功能。完整的函数定义涉及函数头和函数体。其中,函数头包括:函数的返回值类型、函数名、参数类型;而函数体是一个程序模块,规定了函数所具有的功能。函数调用则通过传递函数的参数并执行函数定义所规定的程序过程,以实现相应功能。以下是函数定义的一个简单的例子。该函数max求两个整数(作为参数)的较大值(作为返回值)。intmax(inta,intb)/*函数头:函数类型函数名(函数参数列表)*/{/*函数体开始*/intx;/*函数中要用到的临时变量*/if(a>b)x=a;/*判断a、b的大小,将x赋值为值大的一个*/elsex=b;returnx;/*结束函数调用并返回x*/}/*函数体结束*/有了程序的定义后,就可以在程序的其它地方调用这个函数。例如,可以在程序的某个地方写上“m=max(2,3);”。当程序执行到这里时,首先会调用函数max()并把实际参数2和3分别传给函数定义中的形式参数a和b,使a、b的值分别为2和3;然后,开始执行函数max()所定义的语句;当在函数中执行到“returnx;”时,函数结束并把x的值3作为返回值;随后,程序的控制回到函数调用的地方“m=max(2,3);”,从而m获得结果3。(5)关于输入输出:C语言没有输入输出语句,它通过编译系统库函数中的有关函数,如printf()和scanf()函数,实现数据的输入与输出。这种处理方式为C语言在不同硬件平台上的可移植性提供了良好的基础。例如:printf("Thisintegervalueis%d",123)将输出:Thisintegervalueis123。printf()函数的第一个参数是输出格式说明,%d代表将后面的数据123按十进制整数输出,其他字符串按原样输出。对于以下输入语句:scanf("%d",&i);将从(键盘)输入中读进一个整数,并把它存到变量i中。其中,scanf()函数的第一个参数也是输入格式说明。9\n1.2.4程序的编译与编程环境1.程序的编译其实,计算机硬件真正能理解的只是计算机的指令。用程序设计语言编写的程序并不能为计算机所直接接受。这就需要一个软件能把相应的程序转换成计算机直接能理解的指令序列。对C语言等许多高级程序设计语言来说,这种软件就是编译器(Compiler)。编译器首先要对源程序进行词法分析,然后进行语法与语义分析,最后生成可执行的代码。如果程序中有语法错误,编译器会直接指出程序中的语法错误。当然,由编译器生成可执行的代码后并不意味着你的程序就没有错误了。对于程序中的逻辑错误,编译器是发现不了的,必须通过程序的调试进一步发现。2.编程环境要编写一个程序需要做很多工作,包括编辑程序(Edit)、编译(Compile)、调试(Debug)等过程。所以,许多程序设计语言都有相应的编程环境。程序员可以直接在该环境中完成上述工作,以提高编程的效率。总的来说,要掌握一门程序设计语言,最基本的是要根据语言的语法要求,掌握如何用程序设计语言表达数据、如何实现程序的控制,并会使用编程环境进行程序设计。1.3C语言的发展历史与特点C语言作为计算机编程语言,功能强、语句表达简练、控制和数据结构丰富灵活、程序时空开销少。它既具有诸如Pascal、Fortran、COBOL等通用程序设计语言的特点,又具有汇编语言(AssembleLanguage)中位(bit)、地址(Address)、寄存器(Register)等其他许多高级语言所没有的低级操作能力;它既适合于编写系统软件,又可用来编写应用软件。它的这些特点是与其发展的过程分不开的。早期系统软件(包括操作系统)主要是用汇编语言编写的,因而程序与计算机硬件关系十分密切,使程序编写困难、可读性差、难于移植。这样就要求有一种与硬件关系不紧密的高级语言(High-LevelProgrammingLanguage)用于编程,但早期高级语言缺少汇编语言的某些操作功能,使系统软件的编写十分困难。1972年工作于贝尔实验室的DennisRitchie在B语言的基础上设计并实现了C语言。随后,D.Ritchie又和KenThompson一起设想C语言来构造一批软件工具作为软件工作者的开发平台。这些平台包括不太依赖于计算机硬件的操作系统和语言编译软件。由于UNIX操作系统也是由他们两人用汇编语言编写而成的,并作为一种典型的分时操作系统,因而他们在1973年对UNIX作了重写,其90%以上的代码是用C语言改写的,增加了多道程序设计能力,同时大大提高了UNIX操作系统的可移植性和可读性。在以后的若干年中,C语言又作了多次修改,并渐渐地形成了不依赖于具体机器的C语言编译软件,成了如今广泛应用的计算机语言之一。目前,在不同型号计算机、不同操作系统下,都出现了不同版本的C语言编译程序。这些10\nC语言编译程序有各自的特点。一般来说,1978年B.W.Kernighan和D.Ritchie(简称K&R)合著的《TheCProgrammingLanguage》是各种C语言版本的基础,称之为旧标准C语言。1983年,美国国家标准化协会(ANSI)制定了新的C语言标准,称ANSIC。现在出现的如MicrosoftC、TurboC等语言把ANSIC作为它们各自的一个子集,并在此基础上做了合乎它们各自特点的扩充。但无论是哪种版本的C语言,它们都具有如下一些共同的特点:1.C语言是一种结构化语言C语言的主要成份是函数。函数是C语言程序的基本结构模块,程序的许多操作可由不同功能的函数有机组装而成,从而容易达到结构化程序设计中模块的要求。另外,C语言还提供了一套完整的控制语句(如循环、分支等)和构造数据类型机制(如结构——Structure、数组——Array等),使程序流程与数据描述也具有良好的结构性。2.C语言语句简洁、紧凑,使用方便、灵活C语言一共只有32个关键字(Keyword),9种控制语句,程序书写形式自由,压缩了一切不必要的成份。如用大括号{和}代替复合语句的开始与结束,用++和--运算符号表示加1和减1,用三目运算符?:来表示一个简单的if-else语句,一行中可书写多个语句或一个语句可书写在不同行上,可采用宏定义和文件包含等预处理语句,等等。这些都使C语言显得非常简洁、紧凑。3.C语言程序易于移植这是因为C语言将与硬件有关的因素从语言主体中分离出来,通过库函数或其他实用程序实现它们。这特别体现在有关输入输出操作上,因为C语言不把输入输出作为语言的一部分,而是作为库函数由具体实用程序实现,这大大提高了程序的可移植性(Portability)。4.C语言有强大的处理能力由于C语言引入了结构、指针(Pointer)、地址、位运算、寄存器存储功能,在许多方面具有汇编语言的特点,从而大大提高了语言的处理能力。5.生成的目标代码质量高,运行效率高用C语言编写的程序,经编译后生成的可执行代码比用汇编语言直接编写的代码运行效率仅低15%~20%。这是其他高级语言无法比拟的。当然,C语言也有一些不足之处,这主要表现在数据类型检查不严格,表达式出现二义性,不具备数据越界自动检查功能,运算符的优先级与结合性对初学者难于掌握,等等。这些不足,要求在你学习C语言时引起充分的注意,否则会经常出现一些问题,而且对这些错误的查找也较为困难。1.4实现问题求解的过程下面我们通过求解一个具体的例子来说明程序设计的主要过程。问题:求1~100间所有偶数的和。11\n1.问题分析与算法设计本问题要求在一定范围内(1~100)、满足一定条件(偶数)的若干整数的和,这是一个求累加和的问题。这种问题的基本解决方式是:设置一个变量(如sum),将其初始值设为0,然后在指定的范围(1~100)间寻找满足条件(偶数)的整数,将它们一个一个累加到sum中。为了处理方便,将正在查找的整数也用一个变量表示(如i)。所以,一步累加过程可以用C语言的语句表示为:sum=sum+i;它表示把sum的值加上i后再重新赋给sum。上述这个累加过程需要重复地做,这就需要用程序设计语言的循环控制语句来实现。在循环过程中:(1)需要判别i是不是满足问题要求的条件(偶数)。我们只将满足条件的整数累加到sum中,这可由分支控制语句来实现。(2)需要对循环次数进行控制。这可通过i值的变化进行控制,即:i的初值设为1,每循环一次加1,一直加到100为止。基于上述解决问题的思路,我们就可以逐步明确解决问题的步骤,即确定解决问题的算法。算法(Algorithm)是一组明确的解决问题的步骤,它产生结果并可在有限的时间内终止。我们可以用多种方式来描述这种解决问题的步骤,包括用自然语言、伪代码(Pseudocode)或流程图(FlowChart)。下面主要介绍流程图的基本内容。流程图是算法的图形表示法,它使用图的形式掩盖了算法的所有细节,只显示算法从开始到结束的整个流程。最典型的关于1.2.1节中3种控制结构的表示如图1.1所示。对于求1~100偶数和的问题,基于前面的分析,可以用流程图来描述解决步骤(算法),如图1.2所示。假真假判断语句i判断真语句i+1语句模块i语句模块j语句模块i语句i+2(a)顺序结构(b)分支结构(c)循环结构图1.13种控制结构的流程图12\nsum=0;i=1;假i<=100?真真假i是偶数?sum=sum+i;i=i+1;打印sum图1.2“求1~100偶数和”的流程图2.编辑程序当确定了解决问题的步骤后,就可以开始编写程序了。一般是在编程环境中,应用其中的编辑功能直接来编写程序,生成程序的源文件(对C语言来说,一般源文件的后缀为.c)。相应的程序如下:#includevoidmain(){inti,sum=0;/*(1)*/for(i=1;i<=100;i++)/*(2)*/if(i%2==0)sum=sum+i;/*(3)*/printf("%d",sum);/*(4)*/}13\n说明:(1)inti,sum=0;定义了两个整数类型(int)的变量i和sum,同时把sum初试值为0。(2)for(i=1;i<=100;i++)是一个循环,它表示从i等于1的时候开始循环,每循环一次i加上1(i++),只要i的值小于等于(<=)100,这个循环就一直进行(也就是说i等于101时循环就退出了)。每次循环执行的内容就是它后面的if语句。(3)if(i%2==0)sum=sum+i;表示:如果i是偶数,就将i累加到sum中。%是一个针对整数的运算,代表求余,如果i被2除后的余数为0,则说明它是一个偶数。在C语言中,相等的判断用两个等号(==)来表示,不相等的判断用!=来表示。(4)当循环退出时就调用C编译系统事先定义好的函数printf()将所要的结果值(sum)输出。输出时要求按十进制整数方式(由%d来说明)输出。(5)许多程序设计语言(包括C语言)都有一个原则:若想使用一个对象,需要先说明(或定义)该对象,除非有某种默认规则。所以,一般变量的定义放在具体语句的前面、在调用一个函数前先声明(Declare)或定义(Define)这个函数。由于编程时会经常使用编译系统事先定义好的一些函数,所以编译系统会事先把各种类型的函数声明组织在一个文件中,如关于输入输出方面的函数就组织在一个叫stdio.h的文件中,程序员只要在程序的开头写上#include,就可以直接调用该文件中声明的所有函数。3.程序编译当编辑好程序后,下一步工作就是应用该语言的编译程序对其进行编译,以生成二进制代码表示的目标程序(一个二进制文件,一般文件后缀为.obj)。实际上,还不能直接运行该目标程序,它需要与编程环境提供的库函数进行连接(Link)形成可执行的程序(文件后缀为.exe)。当然,如果你的程序有语法错误,编译程序就会指出该语法错误之所在,而不生成二进制代码。4.运行与调试当程序通过了语法检查、编译生成执行文件后,就可以在编程环境或操作系统环境中运行(Run)该程序。当然,该程序运行所产生的结果有可能不是你想要的结果,这是程序的语义错误(逻辑错误)。比如,在上述程序中,如果把if(i%2==0)sum=sum+i;中的两个等号==写成!=(代表“不等于”),该程序当然也能通过语法检查,但运行结果却是求1~100间所有奇数的和。如果程序有语义错误就需要对程序进行调试。调试是在程序中查找错误并修改错误的过程。调试最主要的工作是找出错误发生的地方。一般程序的编程环境都提供相应的调试手段。调试最主要的方法是:设置断点并观察变量。(1)设置断点(BreakPointSetting):可以在程序的任何一个语句上做断点标记,将来程序运行到这里时会停下来。(2)观察变量(VariableWatching):当程序运行到断点的地方停下来后,你可以观察各种变量的值,判断此时的变量值是不是你所希望的。如果不是,说明该断点之前肯定有错误发生。这样,你就可以把找错的范围集中在断点之前的程序段上。另外,还有一种常用的调试方法是单步跟踪(TraceStepbyStep),即一步一步跟踪程序的执行过程,同时观察变量的变化情况。14\n调试是一个需要耐心和经验的工作,也是程序设计最基本的技能。有关编程环境的操作指导见附录1。练习1.对C语言来说,下列标识符中哪些是合法的,哪些是不合法的?total,_debug,Large&Tall,Counter1,begin_2.改写本章1.4节中的流程图,求1~100中能被6整除的所有整数的和。3.改写本章1.4节中的程序,求1~100中能被6整除的所有整数的和,并在编程环境中验证该程序的运行结果。4.对于给定的整数n(n>1),请设计一个流程图判别n是不是一个素数(只能被1和自己整除的整数),并分析该流程图中哪些是顺序结构、哪些是分支结构与循环结构(如果有的话)。15

相关文档