??(C??????)????2005

Document Sample
??(C??????)????2005 Powered By Docstoc
					普通高等院校计算机基础教育试用教材




                            Computer Programming Foundation

                           Experiment Teaching Material




计算机程序设计基础(C 语言)实验指导书

               编著   余有明     刘华伟

               主审   田   野 刘建东




         北京石油化工学院信息基础教研室
                    2005 年 9 月
                                 目      录


第一章 C 语言集成环境与程序调试方法 ....................................... 1
   1.1 Turbo C 2.0 ....................................................... 1
   1.2 Turbo C 3.0 ....................................................... 1
   1.3 Visual C++ 6.0 .................................................... 3
第二章 课内上机实验内容(基础实验) ...................................... 4
   2.0 预备实验 熟悉运行 C 语言源程序的过程 ............................... 4
   2.1 实验一 简单程序设计 ............................................... 5
   2.2 实验二 选择结构程序设计 ........................................... 8
   2.3 实验三 循环结构程序设计 .......................................... 13
   2.4 实验四 一维数组 .................................................. 15
   2.5 实验五 二维及字符数组 ............................................ 18
   2.6 实验六 函数 ...................................................... 20
   2.7 实验七 指针 ...................................................... 26
   2.8 实验八 结构体 .................................................... 30
   2.9 实验九 文件操作 .................................................. 33
第三章 课外上机实验内容(提高实验) ..................................... 38
   3.1 综合实验一 ....................................................... 38
   3.2 综合实验二 ....................................................... 43
附录一 二级 C 语言程序设计考试大纲(2005 年) ............................. 53
附录二 Turbo C 编译出错信息解析 .......................................... 55
附录三 C 语言的学习方法、注意事项与实验要求 .............................. 59
                         计算机程序设计基础(C 语言)实验教材



                  第一章 C 语言集成环境与程序调试方法

    C 语言是目前流行的通用程序设计语言,是计算机专业人员和计算机爱好者开发软件的首选开
发工具。C 语言源程序必须经过某种编译工具翻译成为目标机器语言程序才能够在计算机上执行。
然而随着程序编写规模的扩大,顺利编写出正确的程序决非一件容易的事情,早期的许多编译工具
仅仅提供翻译功能,已满足不了应用的要求,编程人员需要一种功能全面并高度集成的编译环境。
    程序是一段具有一定功能的代码,编写程序的目的是解决问题。当程序人员写完程序后,其实
并不起作用,只有当编写的程序经过一系列的处理后,能够解决问题时,程序才成为真正的程序,
这一系列的处理过程,一般就是编辑、编译、连接、调试与运行等。目前最成熟的 C 语言集成环境
主要有 Turbo C2.0 和 Turbo C 3.0(简称 TC30)或 Borland C++3.1(简称 BC31)以及 Visual C++ 6.0。

1.1 Turbo C 2.0

    Turbo C 2.0 是一个集成的开发环境,可以直接在其中进行程序的编辑、编译、连接和调试等,
具有运算快捷、功能强大、使用方便等特点。现在流行的 Turbo C 有两个版本,一是 DOS 环境下的
Turbo C 2.0,不支持鼠标操作。另外是 Turbo C 3.0,支持鼠标操作,但是各有其它特点。在熟悉了
Turbo C 编程环境后,自然就会知道它们还有哪些特色,由于 Turbo C 2.0 的基本用法在一般参考书
中都有介绍,这里就不再赘述了。

1.2 Turbo C 3.0

1.2.1 TC30 集成开发环境

    TC30 集成开发环境(英文缩写为 IDE)是 Borland 公司为 C 语言程序员提供的一个较完善的程
序开发平台。在 TC30 的 IDE 中,将源码编辑、编译、连接、程序调试等本来是独立的工具,有机
的结合在统一友好的界面之下。
                                        (1)支持多窗口:在统一的框
    在 TC30 的 IDE 中融合了许多 DOS 的编程软件所不具备的特色:
                                         (2)
架之下,所有的程序编辑和信息显示都统一以窗体表达,且每个窗体都可移动、可重定义尺寸。
鼠标支持:在 TC30 中大多数操作都可通过鼠标实现,在很大程度上提高了系统的易用性,也从而
减免了记忆各个系统命令按键的负担。(3)对话框:在系统需要从交互式操作中获取数据时,IDE
采用了对话窗体来同用户交互,且设计了表达各种用户反馈信息的标准组件,具有良好的人性化特
征。(4)使用剪贴板:可支持多个编辑窗口之间方便的传递文本。(5)编辑完全可逆:通过提供完
                                   (6)成熟的帮助系统:可通过定
全的 Undo 和 Redo 操作可自由的恢复以往的任何一个误操作行为。
位关键词快速获得有关的帮助,且帮助中包含完整的程序示例,并可复制示例程序。(7)强大的调
试能力:支持 C 语言源码级的调试,具有随处可设置断点,单步程序执行、变量内容动态显示等程
序员必需的调试支持,可帮助程序员迅速定位错误和完成程序。
1.2.2 TC30 的安装、启动和退出

    在 Borland 公司发行的 TC30 安装盘中有一个安装程序 install.exe。在 DOS 下运行安装程序,出
现安装界面,按照安装过程的提示信息,一步步进行,在安装过程中可选装需要的部分,对于不需
要的部分则不选。完成安装后,在硬盘中会发现 TC30 的可执行程序的主目录,并自动设置了 TC30
                 ,这样程序可在任意路径下执行。在没有安装盘的情况下,也可
程序的执行路径(PATH 环境变量)
以通过将硬盘中已经安装的 TC30 备份并在新计算机的硬盘中按原来的目录进行恢复的办法手工处
理安装,再将程序目录加入到 Path 中即可。
    安装完成后,就可以运行 TC30 中的程序了。进入 DOS 系统,在执行 TC30 的程序前,先将目
录转换到自己的 C 语言程序的存放目录中,然后启动 TC30 的 IDE 环境。

                                      -1-
                        计算机程序设计基础(C 语言)实验教材



    启动时,先进入 TC 的 bin 子目录,运行
TC.EXE 就进入了 TC30 的集成开发环境的主
框架界面,如图 1-1 所示。
    从 TC30 的 IDE 集成开发环境中退出或
回到 DOS 环境中,可按以下步骤执行:
    (1)选择菜单项 File|Quit。
    (2)按下快捷键 ALT+X。
    退出 IDE 环境时,文件如还未保存,则
提示保存。
1.2.3 TC30 的 IDE 界面说明

    IDE 窗口分为三个可见部分:顶端的菜单条,中间的桌面区和底部的状态行。
    (1) 菜单条和菜单项
    菜单条是选取和执行命令的基本途径。菜单条总是处于屏幕的顶端,且除了只有在显示程序输
出或执行另外的程序时才不可见。
    在菜单项中,菜单命令后跟省略号(…)表示执行该菜单命令将出现对话框,如后有箭头表示命令
会带出下一级弹出式菜单,如不跟省略号或箭头则表示选择该菜单项时执行该菜单相应的操作。
    菜单命令的选取支持鼠标和键盘两种方式。用键盘选取菜单的方法为:按下 F10,使菜单条处
于活动状态,按下左右的方向键在主菜单栏上移动,按下上下的方向键,在菜单栏的菜单项间上下
移动,按下回车键(Enter)打开子菜单、对话框或执行对应的命令,按下 ESC 键取消菜单操作。
    为了达到快速操作 IDE 命令的目的,TC30 许多的菜单项命令都关联了键盘功能键,这些功能键
称为“热键(HotKey)”,菜单项关联的热键提示信息出现在菜单项名称的最右边,如打开文件的菜
单项“File|Open...   F3”,其中“F3”即为热键,表示按下功能键<F3>就等价于选取了打开文件的菜单
项。在学习 C 语言编程的过程中,熟练掌握这些热键会极大地提高编程的效率,对初学者而言,尤
其应注重这方面的训练。
    (2)桌面区
    IDE 桌面是 TC30 所有窗口的显示和操作区域,打开的所有窗口,其大小和位置都只能限制在桌
面区域中,其任何一边界都不能超出桌面以外。在桌面之上可能同时打开多个窗口,但只存在一个
当前激活的窗口,位于所有窗口的顶层,其余窗口按覆盖关系逐层排列在下。
    (3)状态行
    状态行在 IDE 中起到两个方面的作用:①对当前定位的菜单项目进行简单的注解;②对当前激
活的窗口,提供最常用的快捷操作命令提示。
    在 TC30 的 IDE 环境下进行的文件录入、编辑、保存、查找、编译、调试、工程文件使用、窗
口等功能将结合资料在课堂上介绍并在实验课中辅导。
1.2.4 使用 TC30 编写程序的过程

    用 C 语言编写一个计算机程序,不管程序的规模如何,都会按照一个流程来进行。首先是编辑
工作,完成源程序并录入到计算机;接着对源程序进行编译、连接,如果发现语法问题,则需要重
新进行编辑工作;然后对程序进行试运行,在试运行中发现逻辑错误,则需要对程序进行调试,在
调试中发现存在的错误后,仍需要重新开始进行编辑工作(但已经比开始阶段的编辑工作前进了一
步);运行与测试完全成功后,本次编写程序工作结束。整个过程如图 1-2 所示。
    早期没有出现集成的 C 语言编程环境的时候,按这样的流程编写一个 C 语言计算机程序必须对
编辑、编译、连接、试运行、调试等过程都执行一个单独程序,整个过程完全一步步的紧扣下来。
    而在 TC30 的集成开发环境中,所有的功能全部以菜单命令方式来驱动,可随时执行任何的命


                                -2-
                          计算机程序设计基础(C 语言)实验教材



令完成特定的功能,而且运行、调试也直接在 IDE 下完成,完全不需要切换程序。尽管如此,作为
编写 C 语言程序的整个过程还是基本一致的,但有了 IDE 环境,却使得整个编程过程显得简单、灵
活和高效,这正是 IDE 环境的优势所在,初学者应着重培养在 IDE 中控制整个过程的能力。
    另外在使用 IDE 开发环境编写程序时有些操作要引起注
意。尽管 TC30 是较成熟的产品,然而由于运行环境的复杂性
也经常导致环境本身崩溃,如果在崩溃前,用户对文件进行的
编辑修改工作还未来得及保存,则修改的任何信息都会丢失。
在此特提出建议,在编辑修改了文件之后,请切记立即保存,
在保存成功之后,再进行其他的操作。
1.2.5 C 语言文件组织与管理

    在用 C 语言编写程序过程中,我们经常要同许多与程序
或环境有关的文件打交道,这些文件有些是源程序文件、源程
序管理文件,有些则是目标文件或可执行文件,甚至是各种各
样的临时文件。对于这些文件如果没有一个很好的组织和管
理,随着编写程序的增多,目录下存在大量难以分辨的各种文
件,对于查找和维护造成混乱。因此,为了避免这种低效率事
件的发生,按照一定的方法来组织管理文件从一开始就显得非
常必要。
    为了能快速组织和管理好 C 语言有关文件,就要求对编程中常见的文件类型首先能有比较清楚
的认识。以下,通过表 1-1 列出了 C 语言编程有关的各种常用的文件类型。
                               表 1-1 C 语言的各种文件类型
     类型名称                            类型说明                文件类型
     .H,.HPP         C/C++头文件,源程序的一种,在 TC30 编辑器中创建和编辑    文本文件
     .C,.CPP         C/C++源代码,源程序的一种,在 TC30 编辑器中创建和编辑    文本文件
       .BAK            备份文件,使用 TC30 修改程序时,自动做原文件的备份      文本文件
       .OBJ              目标文件,对 C 源程序编译时产生,在连接时使用       二进制文件
       .PRJ            工程文件,TC30 进行多个源文件的应用程序的管理文件      二进制文件
       .SWP              临时文件,TC30 运行环境临时使用,正常退出删除      二进制文件

1.3 Visual C++ 6.0

    在应用 Visual C++ 6.0 进行程序的调试和运行时,基本过程为:文件→新建→工程→Win32 控制
台程序→输入工程文件名 yym1→确定→选择简单程序→确定→确定→打开左侧工作区里的 FileView
页面→打开 yym1 files 中的 Source Files 下的 yym1.cpp。
    在此文件中录入和编辑程序文件,参考有关书籍进行程序的编译和调试。




                                      -3-
                        计算机程序设计基础(C 语言)实验教材



                  第二章 课内上机实验内容(基础实验)

                   2.0 预备实验 熟悉运行 C 语言源程序的过程

【实验目的】
  1. 了解 Dos 与 Windows 环境下 C 语言的运行环境,了解所用的计算机系统的基本操作方法,学
会独立使用该系统。
  2. 了解在该系统上如何编辑、编译、连接和运行一个 C 程序。
  3. 通过运行简单的 C 程序,初步了解 C 源程序的特点。

【实验内容】

  在课程的上机实验前,要求每个同学自己提前上机熟悉 C 语言的程序录入、文件编辑、程序调
试环境,重点掌握 TC20、TC30 或 BC31 的集成开发环境 IDE,熟悉 Visual C++ 6.0 的程序调试环境。
  在 Turbo C 环境下运行 C 语言源程序的步骤如下:
1.编辑源程序文件

  在主菜单下,直接按 Alt+F 键,或按 F10 后将光带移到“File”选项上,按回车键,在“File”下面
出现一个下拉菜单,菜单中有以下选项:
  Load F3         表示加载或装入一个文件
  Pick Alt+F3     从指定的文件列表中选择文件装入编辑器。
  New             表示新文件,缺省文件名为 NONAME.C。
  Save F2         将正在编辑的文件存盘。
  Write to        将正在编辑的文件写入指定的文件中,若文件名已存在,则重写。
  Directory       表示文件目录。
  Change Dir      改变驱动器及目录
  OS shell        进入 Turbo C 命令行模式,命令 EXIT 可返回集成环境
  Quit    Alt+x   退出 Turbo C,返回 DOS 状态。
  建立一个新文件,“File”→“New”,按回车键,即可打开编辑窗口。屏幕右上角显示缺省文件名
为 NONAME.C,用 F2 或选择“Save”或“Write to”进行存盘操作,此时系统将提示用户将文件名修改
成为合适的文件名,一般以自己的姓名缩写加序号如 yym01 或 zhsan01 等表示。
2. 源程序的编译、连接

  直接按 F9 键,或将菜单“Compile”中的光带移到“Make EXE file”项上,按回车键,实现对源程
序的编译、连接。若有错误,则在信息窗口显示出相应的信息或警告,按任意键返回编辑窗口,光
标停在出错位置上,可立即进行编辑修改。修改后,再按 F9 键进行编辑、连接。如此反复,直到没
有错误为止,即可生成可执行文件。
  注意:C 程序的连接是在编译后自动完成的。
3. 执行程序

  直接按 Ctrl+F9 键执行.EXE 文件;或按 F10 进入主菜单,将光带移到“Run”选项回车,在弹出
的菜单里选择“Run”选项,回车。
4. 查看结果

  运行程序结束后并不能直接看输出结果。只有按复合键 Alt+F5,或选择“Run”菜单中的“User
Screen”选项,出现用户屏幕时,才能看到输出的结果。按任意键返回 TC 集成环境。
  如果程序需要输入数据,则运行程序后光标停留在用户屏幕上,要求在用户输入数据,数据输
                                  -4-
                            计算机程序设计基础(C 语言)实验教材



入完成后程序继续运行,直至输出结果。
   如果运行结果不正确或其他原因需要重新修改源程序,则需重新进入编辑状态。修改源程序,
重复以上步骤,直到结果正确为止。
5. 退出 Turbo C 集成环境

   在主菜单选择“File”菜单的“Quit”选项,或者直接按 Alt+x 退出 Turbo C 环境。同时系统将检查
当前编辑窗口的程序是否已经存盘,若未存盘,系统将弹出一个提示窗口,提示是否将文件存盘,
若按“Y”则将当前窗口内的文件存盘后退出;若按“N”则不存盘退出。
6. 基本操作要求

   熟练掌握 TC 环境下的文件建立、保存、打开、另存和改变路径的文件操作的键盘与鼠标用法;
   熟练掌握运行程序的键盘、鼠标操作方法;
   熟练掌握查看程序运行结果的键盘、鼠标操作方法;
   掌握“出现找不到 stdio.h、conio.h 等 include 文件”的路径“选项 Options->Directories”的设置方法。
7. 调试程序
   通过下面的简单程序的调试基本了解和掌握 C 语言上机编程的过程。
   main()
   {
      printf(“********************”);
      printf(“ Welcome to turbo c ”);
      printf(“ I am a student ”);
      printf(“********************”);
   }
   通过调试该程序,学会如何进行上述的一些基本操作,分析程序的结构。


                                 2.1 实验一 简单程序设计
【实验目的】
   1. 掌握 C 语言数据类型的定义和赋值整型、字符型、实型变量的方法;
   2. 了解基本数据类型在数据输出时所用的格式转换符;
   3. 学会使用 C 的有关算术运算符,以及包含这些运算符的表达式;
   4. 进一步熟悉 C 程序的编辑、编译、连接和运行的过程,理解 C 语言程序的顺序结构。

【实验内容】
1.调试程序实现按格式要求输入/输出数据。
【参考源程序】
   #include "stdio.h"
   main()
   {
      int a,b;
      flost x,y;
      char c1,c2;
      scanf(“a=%d,b=%d”,&a,b);
      scan(“%f, %e”,&x,&y);
      scanf(“&c &c”,&c1,&c2);
      printf(“a=%d,b=%d,x=%f,y=%f,c1=%c,c2=c\n”,a,b,x,y,c1,c2);
   }
   运行该程序,必须按如下方式在键盘上输入数据
                                           -5-
                            计算机程序设计基础(C 语言)实验教材



  a=3,b=7 ↙
  8.5,71.82 ↙
  a A↙
  请写出输出结果。
2.调试程序实现输入三角形三边长,求三角形面积。
【参考源程序】
  #include “math.h”
  main()
  {
       float a,b,c,s,area;
       scanf(“%f ,%f,%f”,&a,&b,&c);
       s=1.0/2*(a+b+c);
       are=sqrt(s*(s-a)*(s-b)*(s-c));
       printf(“area=%f”,area);
  }

  输入数据并写出程序运行结果。
3.已知圆半径,圆柱高,求圆周长,圆柱体积。
【参考源程序】
  main()
  {
     float r,h,l,v,pi;
     pi=3.1415926;
     scanf(“%f,%f”,r,&h);
     l=2*pi*r;
     v=pi*r*r*h;
     print(“圆周长为:%6.2f\n”,l);
     printf(“%圆柱体积为:6.2f”,v);
  }
  输入数据并写出程序运行结果。
4.编写程序由键盘输入学生三门课(英语、数学和程序设计)成绩,计算并输出总成绩、平均成绩。
【编程解析】
(1) 程序的输入与输出:输入三门课的成绩 English、math、program,输出总成绩 sum 及平均成绩
average。
(2) 数据结构:int English,math,program,sum;float average;
(3) 解决问题的关键算法:
     求总成绩:三门课成绩相加;求平均成绩:总成绩除以 3。
【算法流程图】如图 2-1 所示。
【参考源程序】
  #include <stdio.h>
  main()
  {
     inte english,math,program,sum;
     float average;
     printf("Enter the score of English,math and program:\n");
     scan("%d%d%d",&English,&math,&program);
     sum=English+math+program;
     average=sum/3.0;
     printf("sum=%d\t",sum);
                                            -6-
                             计算机程序设计基础(C 语言)实验教材



      printf("average=%5.1f\n",average);
  }
  程序运行结果如下:
  Enter the score of English,math and program:
  80 69 97↙
  sum=246 average= 82.0

  在解题时要选取能够完全达到实际应用的数据类型,并注意计算过程中隐含的数据类型转换。


5.编写一个程序,输入一个三位正整数,要求反向输出对应的整数,如输入 789,则输出 987。
【编程解析】

  (1) 程序的输入与输出:程序要求输入一个三位正整数 n,并反向输出对应的数 result。
  (2) 数据结构 int n,result,n3,n2,n1。
  (3) 算法分析:
  主框架将指定数的百位、十位、个位分离并重组成一个新数。将分离出的数重组成一个新数
result,将原数的个位、十位、百位分别乘以 100、10、1 即可得到新数。子框架:分离百位、十位、
个位的方法。设置 3 个整型变量 n1,n2,n3,分离百位数可以用整除实现,然后从指定数中除掉百
位数,余下的数存入 result 中,然后将 result 整除 10 即可得到十位数,再从 result 中除掉十位数,余
下的数就是个位数。
【算法流程图】如图 2-2 所示。




【参考源程序】
  #include <stdio.h>
  main()
  {
       int n,n1,n2,n3,result;
       print("Enter an integer between 100 and 999:\n");
       scanf("%d",&n);
       n3=n/100;
       result=n-n3*100;
       n2=result/10;
       result-=n2*10;
       nl=result;
       result=n1*100+n2*10+n3;
                                             -7-
                               计算机程序设计基础(C 语言)实验教材



      printf("%d==>%d\n",n,result);
  }
  程序运行结果如下:
  Enter an integer between 100 and 999:
  568↙
  568==>865

  本问题的求解方法可扩展到求分离正整数的问题上。思路是首先判断是几位数,用整除方法依
次分离出整数的各位,重新组成新数。此题也可用求余的方法由低位到高位依次来分离个位数。
6.设计程序(根据教学内容选做)
  ① 输入圆半径和圆心角,输出圆的周长、面积。
  ② 输入一个字符,找出它的前驱或后继字符,分别以字符形式和整型格式输出。
  ③ 编制如下菜单(汉字部分可以用英文或者汉语拼音来代替)               :
             |*******************************|
                           |    小学生算术运算测试系统               |
                           |       + ----- Add 加法         |
                           |       - ----- Sub 减法         |
                           |       * ---- mul 乘法          |
                           |       / ---- div 除法          |
                           |       e ---- exit 退出         |
                           |      请输入你的选择:                |
                           |*******************************|

【思考与提高】
 1. 如何用 windows 中的记事本程序来编辑 C 文件?
 2. 用 TC 运行 C 文件和查看 C 文件的运行结果有什么不同之处?
 3. scanf 函数的各个部分在执行程序时起什么作用?“&”符号什么意思?记住该函数用到了“&”,
而输出函数 printf 则没有用到“&”。
 4. 对于 scanf 函数和 printf 函数中,输入输出的各种格式要熟悉,特别是%d 和%f 分别代表什么
意思,要仔细弄清楚。


                               2.2 实验二 选择结构程序设计

【实验目的】
  1. 了解 C 语句表示逻辑量的方法,0 代表假和 1 代表真;
  2. 正确使用关系表达式和逻辑表达式表达条件。
  3. 熟练掌握 if 语句和 switch 语句。
  4. 进一步熟悉 TC 集成环境的使用方法,学习 TC 环境提供的调试工具。

【实验内容】
1.调试程序实现:已知三个数 a,b,c,找出最大值放于 max 中。
【参考源程序】
  #include "stdio.h"
  main()

                                          -8-
                              计算机程序设计基础(C 语言)实验教材



  {
      int a,b,c,Max;        /*定义四个整型变量*/
      scanf(“a=%d,b=%d,c=%d”,&a,&b,c);
      if (a>=b)
         max=a;              /*a>=b*/
      else
         max=b;              /*a<b*/
      if (c>max)
         max=c;              /*c 是最大值*/
      printf("max=%d",max);
  }
 若输入下列数据,分析程序的执行顺序并写出运行结果
  (1)a=1,b=2,c=3
  (2)a=2,b=1,c=3
  (3)a=3,b=2,c=1
  (4)a=3,b=1,c=2
  (5)a=3,b=3,c=2
  (6)a=2,b=1,c=2


2.调试程序实现:输入某学生的成绩,经处理后给出学生的等级,等级分类如下:
      90 分以上(包括 90) A:
      80 至 90 分(包括 80):B
      70 至 80 分(包括 70):C
      60 至 70 分(包括 60):D
      60 分以下:          E
方法一:用 if 嵌套
【编程解析】

  由题意知如果某学生成绩在 90 分以上,等级为 A;否则,如果成绩大于 80 分,等级为 B;否
则,如果成绩大于 70 分,等级为 C;否则,如果成绩大于 60 分为 D;否则,如果成绩小于 60 分,
等级为 E;但当我们输入成绩时也可能输错,出现小于 0 或大于 100,这时也要做处理,输出出错信
息。因此,再用 if 嵌套前,应先判断输入的成绩是否在 0~100 之间。
【参考源程序】
  #include "stdio.h"
  mian()
  {
     int score;
     char grade;
     printf("\nplease input a student score:");
     scan("%f",&score);
     if(score>100||score<0)
        printf("\ninput error!");
     else
        { if(score1>=90)
           grade='A';
         else
           { if(score>=80)
              grade='B';
             else
              {if(score>=70)

                                                  -9-
                                 计算机程序设计基础(C 语言)实验教材



                  grade='C';
            else
               { if(score>=60)
                  grade='D';
               else grade='E';
               }
            }
           }
      printf("\nthe student grade:%c",grade);
       }
  }

  输入测试数据,调试程序。测试数据要覆盖所有路径,注意临界值,例如此题中得 100 分,60
分,0 分以及小于 0 和大于 100 的数据。
方法二:用 switch 语句
【编程解析】

  switch 语句是用于处理多分支的语句。注意 case 后的表达式必须是一个常量表达式,所以在用
                                                  ,B,C,D
switch 语句之前,必须把 0~100 之间的成绩分别转化成相关常量。所有 A(除 100 以外)
类的成绩的共同特点是十位数相同,此外都是 E 类。则由此可得把 score 除十取整,化为相应的常
数。
【参考源程序】

  #include "stdio.h"
  main()
  {
    int g,s;
    chare ch;
    printf("\n Input a student grade:");
    scanf("%d",&g);
    s=g/10;
    if(s<0||s>10)
          printf("\ninput error!");
    else
        { switch (s1)
           { case 10:
             case 9: ch='A'; break;
             case 8: ch='B'; break;
             case 7: ch='C'; break;
             case 6: ch='D';
             default: ch='E';
           }
        printf("\nthe student scort:%c",ch);
        }
  }
输入测试数据,同方法一一样调试程序并写出结果。


3.有一个函数,定义如下。用分支结构编写一程序,根据用户输入的自变量 x 的值,计算函数值。
                                                -10-
                                  计算机程序设计基础(C 语言)实验教材



                                                     0 ( x  0)
                                                     
                                                     
                                       y  f ( x )   x (0  x  50)
                                                      2
                                                      x ( x  50)
                                                     
【参考源程序】
       #include "stdio.h"
       void main()
       { flost x;
          pintf(“input x:\n”);
          scanf(“%f”,&x);
          if(x<0.0)
             printf(“y=0\n”);
          else if(x>=0.0 && x<=50.0)
             printf(“y=%f\n”,x);
          else
          printf(“y=%f\n”,x*x);
   }
4.编写一个程序,要求输入一个字符并判断它是字母字符、数字字符、还是其他字符。
【编程解析】
       (1) 程序的输入与输出:程序要求输入一个字符 ch。程序要求输出字符的类型,即字母(alpha) 、
       数字(numeric)或其他字符。
       (2) 数据结构:char ch
       (3) 解决问题的关键算法:判断字符的类别:若字符在’a’到’z’之间或者在’A’到’Z’之间,则字
       符为字母字符;若字符在'0'到'9'之间,则为数字字符;否则,为其他字符。
【算法流程图】如图 2-3 所示。
【参考源程序】
  #include<stdio.h>
  main()
  {
      char chr;
      printf("Enter an character:");
      scanf("%c",&ch);
      if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')
         printf("%c is an alpha\n",ch);
      else
         if(ch>='0'&&ch<='9')
            print("%c is a numeric\n",ch);
      else
            printf("%c is other character\n",ch);
  }
程序运行结果如下:
  Enter an character : a↙
  a is an alpha
或者
  Enter an character : *↙
  * is other character

  此问题求解是比较简单的分支问题,熟悉简单的分支语句就可以为解决复杂的分支语句奠定基础。

5.编写一个程序,求一元二次方程 ax  bx  c  0 的根。
                                          2




                                                    -11-
                              计算机程序设计基础(C 语言)实验教材



【编程解析】
  (1) 程序的输入与输出:程序要求输入 a,b,c 三个数,输出方程根的情况。
  (2) 数据结构: float  a,b,c,disc;double p,q;
  (3) 解决问题的关键算法:求解方程的根,有几种情况:当 a=0,b=0 时,方程无根;当 a=0,
  b≠0 时,方程只有一个实根 -c/b;当 a≠0 时,方程有两个根,其中当 b2-4ac≥0 时有两个实根,当
  b2-4ac<0 时有两个虚根。
【参考源程序】
  #include<math.h>
  main()
  {
       float a,b,c,disc;
       double p,q,r;
       printf("Enter a,b,c:");
       scanf("%f%f%f",&a,&b,&c);
       if(a==0)
            if(b==0)
                   printf("no answer dule to input error\n");
            else
                   printf("the single root is %f\n",-c/b);
       else
         {
            disc1=b*b-4*a*c;
            p=-b/(2*a);
            q=sqrt(fabs(disc))/(2*a);
            if(disc<0)
                   {
                       printf("The complex roots are:\n");
                       printf("%6.2f+%6.2fi\n",p,q);
                       printf("%6.2f-%6.2fi\n",p,q);
                     }
           else
                if (disc==0)
                     printf("two equal roots:%6.2f\n",p);
                else
                printf("two real roots:%6.2f and %6.2f\n",p+q,p-q);
     }
  }
 程序运行结果如下:
  Enter a,b,c: 2 4 6↙
  The complex roots are:
   -1.00+ 1.41i
   -1.00- 1.41i
 或者
  Enter a,b,c: 1 2 1↙
  two equal roots: -1.00

  此问题是比较复杂的分支问题,C 语言规定,在 if 语句中内嵌 if 语句时,else 子句总是与距离
它最近且没有配对的 if 相结合,而与书写格式无关,使用中应避免引起逻辑上的错误。
6.设计程序(根据教学内容选做)
                                             ,求出它的前驱和后
  ① 键盘输入一个字符(用 getchar()函数输入,体会#include 语句的作用)
  继字符,同时将三个字符按顺序在屏幕上显示(用 IF 语句实现)        。
  ② 键入 a、b、c 三个整数,求最小值,写出调试过程。
                                              -12-
                                  计算机程序设计基础(C 语言)实验教材



  ③ 在上题的基础上,进行三个数的排序,按从小到大的顺序输出。
  ④ 某托儿所收 2 岁到 6 岁的孩子,2 岁、 岁孩子进小班 3                   ;
                                          (Lower class) 4 岁孩子进中班   (Middle
        ;5
  class) 岁、6 岁孩子进大班(Higher class)   。编写程序(分别用 switch 语句和 IF 语句两种方
           ,
  式编程) 输入孩子年龄,                         如:
                         输出年龄及进入的班号。 输入: 输出: 3,            3,
                                                      age: enter Lower class。
  ⑤ 简单计算器。请编写一个程序计算表达式:              (选作题)
       data1 op data2 的值。其中 op 为运算符+、—、*、/。
    (例如:用户输入:                3.14*2     程序会显示结果:3.14*2=6.280000)
【思考与提高】

 1. 什么类型问题适合于 if…else…语句,什么类型问题适合用 switch…case…语句来选择?
 2. switch…case…语句中的 break 有何作用?如果没有 break,程序运行步骤会发生什么变化?


                                  2.3 实验三 循环结构程序设计

【实验目的】
  1.学习循环语句 for、while 和 do-while 语句的使用方法;
  2.学习用循环语句实现各种算法,例如穷举法、迭代法等;
  3.进一步熟悉 TC 集成环境的使用方法。
【实验内容】
1.调试程序实现求和 s=1!+2!+3!
【参考源程序】
  mian( )
  {
     int n,s=0,t=1;
     for(n=1,n<=3;n++)
     {
         t=t*n;
         s=s+t;
     }
     print(“%d”,s);
  }
2.使用 while 循环求两个正整数的最小公倍数。
【参考源程序】
  #include "stdio.h"
  void main()
  { int m,n,result,m;
    printf(“input two integers:”);
    scanf(“%d%d”,&m,&n);
    result1=m<n?n:m;
    while(!(result%m==0 && result%n==0))
      result++;
    printf(“The least common multiple of m and n is %d\n”,result);
  }
  如果将题目改成求两个数的最大公约数,将如何调试?
                     2   2    2   2         2
3.利用 for 循环计算 1 +2 +3 +4 + …… +100 。
【参考源程序】
  #include "stdio.h"
  void main( )

                                                -13-
                                 计算机程序设计基础(C 语言)实验教材



    { int k;
      long result=0;
      for(k=1;k<=100,k++)
       result+=k*k;
       printf(“The result is: %ld\n”, result);
    }

如果将题目改成:利用 for 循环计算 12-22+32-42+52-62+72-82+…+992-1002,将如何调试?
4.打印 500 以内的“水仙花数”。“水仙花数”是一个三位数,其各位数立方和等于该数本身。
    main()
    {
        int i,j,k,n;
        for(n=100, n<=500;n++)
        {
           i=n/100;
           j=n/10-i*10;
           k=n%10;
           if(n= =i*i*i+j*j*j+k*k*k)
              printf(“ %d”,n),
        }
    }
5.编写一个程序,把用户输入的数据累加,直到输入零为止,输出累加的结果。
【编程解析】
(1) 程序的输入与输出:输入若干个数(正数或负数)    ,以 0 结束输入。输出输入数据的累加和。
(2) 数据结构:float sum,d。
(3) 关键算法:求累加和,先将 sum 初始化为 0,每输入一个数 d,判断它是否为 0,若为 0 就跳出
循环,否则将其累加到 sum 中。
【算法流程图】如图 2-4 所示。
【参考源程序】
  main()
  {
    floart sum=0,d;
    printf("Enter a serial of numbers ended by 0:\n");
    for( ; ; )
    {
       scanf("%f",&d);
       if(d==0) break;
       sum+=d;
    }
    printf("sum=%g\n",sum);
  }
程序运行结果如下:
  Enter a serial of numbers ended by 0:
  12 45.6 24.5 30 6 9 0↙
  sum=127.1

    该程序实现了累加器的功能。此思路可扩展到实现任意数的累加、连乘等功能。
6.编写一个程序,输入一个正整数 n,求 sum=1+(1+2)+(1+2+3)+…+(1+2+3+…+n)的值。
【编程解析】
   (1)   程序的输入与输出:输入一个正整数 n,输出 1+(1+2)+(1+2+3)+…+(1+2+3+…+n)的值。

                                                 -14-
                             计算机程序设计基础(C 语言)实验教材



    (2)   数据结构:int i,j,n,s1,sum
    (3)   解决问题关键算法:求和。采用两层循环求解,外层循环 i 从 1 到 n,内层循环 j 从 1 到 i。
【算法流程图】如图 2-5 所示。
【参考源程序】
  #include <stdio.h>
  main()
  {
    int i,j,n,s,sum=0;
    printf("Enter an integer:");
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        s1=0;
        for(j=1;j<=i;j++)
          s1+=j;
        sum+=s1;
    }
    print("sum=%d\n",sum);
  }
程序运行结果如下:
  Enter an integer: 10↙
  sum=220

     此题用到循环的嵌套。多重循环中要处理好各循环之间的依赖关系。
7.设计程序(根据教学内容选做)
①    输入 1 到 10 之间的任何一个整数,求出该数阶乘并输出。
②    键盘输入字符,分别统计字符(不分大小写)        、数字、空格和其它符号的个数,遇!号结束。
③    用梯形法求 sin x 在 0~180 度间的定积分。(提高题)
④    综合题:小学生算术运算测试系统 (提高题)
     当选项不为“E”时,反复出题。      并在某一个选项时,随机产生 100 以内的算术题,根据用户输入,
     判断对错,并统计。按“ESC”时,给出总题数,正确数和得分,退到主菜单。
【思考与提高】
     1.什么时候用 while 语句比较方便,什么时候用 for 语句比较方便?
     2.为什么用 for 语句可以完全代替 while 语句?


                                   2.4 实验四 一维数组

【实验目的】
     1.掌握一维数组的定义、赋值和输入输出的方法;
     2.掌握字符数组和字符串处理函数的使用;
                                         ;
     3.学习用数组实现相关的算法(如排序、求最大和最小值、对有序数组的插入等)
     4.熟悉 TC 集成环境的调试数组的方法。
【实验内容】
1.调试程序实现功能:青年歌手参加歌曲大奖赛,有 10 个评委对她的进行打分,试编程求这位选
手的平均得分(去掉一个最高分和一个最低分)。
分析:本题的核心是排序。将评委所打的 10 个分数利用数组按增序(或降序)排列,计算数组中除
第一个和最后一个分数以外的数的平均分,其中排序部分这里用选择法实现。


                                        -15-
                               计算机程序设计基础(C 语言)实验教材



【参考源程序】
    main()
    {
       int i,j,min,max;
       float temp,ave=0;
       float a[11];
       printf("\n 输入评委所打的分数:\n");
       for(i=1;i<=10;i++)
       scanf("%f",a[i]);
       for(i=1;i<=9;i++)
         {
           min=i;
           for(j=i+1;j<=10;j++)
             if(a[min]>a[j])
                min=j;
                temp=a[i];
                a[i]=a[min];
                a[min]=temp;
           }
       for(i=2;i<=9;i++)      /*注意 i 值的变化范围*/
           ave=ave+a[i];
       printf("选手所得最后分数:%6.1f",ave/8);
       printf("\n");
    }
 2.输入一串字符,计算其中空格的个数。
【参考源程序】
    #include      <stdio.h>
    main( )
    { char c[30];
       int i,sum=0;
       gets(c);
       for(i=0;i<strlen(c);i++)
          if(c[i]==' ')
             sum=sum+1;
       print("空格数为:%d \ n",&sum);
    }
3. 有 一 递 推 数 列 , 满 足 : f (0)  0, f (1)  1, f (2)  2, f (n)  f (n  1)  2 f (n  2) f (n  3)
    (n  3) 。使用数组编写程序,顺序打印出 f (0)到f (10 ) 的值。
【参考源程序】
  #include "stdio.h"
  void mian( )
  {
    int f[11],k;
    f[0]=0; f[1]=1; f[2]=2;
    for(k=3;k<11; k++)
           f[k]=f[k-1]+2*f[k-2]*f[k-3];
    for(k=0;k<11;k++)
           print(“%d,”,f[k]);
  }
根据该例题思路,显示出数列 1,1,2,3,5,8,13,21……的前二十项,每五项一行,
4. 请用户输入一个含有 12 个浮点数的一维数组,分别计算出数组中所有的正数的和以及所有的负
   数的和。

                                               -16-
                           计算机程序设计基础(C 语言)实验教材



【参考源程序】
  #include "stdio.h"
  void main( )
  { float data[12];
     float result1=0.0; result2=0.0;
     int i;
     printf(“please input 12 float numbers:\n”);
         for(i=0;i<12;i++)
           scanf(“%f”, &data[i]);
         for(i=0,i<12,i++)
         {
           if(data[i]>0.0)
             result1+=data[i];
           else
             result2+=data[i];
       }
       printf(“The sum of the positive numbers is %.3f\n”,result1);
       printf(“The sum of the negative numbers is %.3f\n”,result2);
  }
  将题目要求改成:输入 9 个整数,然后将这 9 个整数分 3 行显示,分别求出并显示各列的和。
5.在键盘上输入 N 个整数,试编制程序使该数组中的数按照从大到小的次序排列。
分析:C 中数组长度必须是确定大小,即指定 N 的值。排序的方法有多种,下面列出两种方法。
方法一:冒泡排序
  从第一个数开始依次对相邻两数进行比较,如次序对则不做任何操作;如次序不对则使这两个
数交换位置。第一遍的(N-1)次比较后,最大的数已放在最后,第二遍只需考虑(N-1)个数,以
此类推直到第(N-1)遍比较后就可以完成排序。
【参考源程序】
  #define N 10
  #include"stdio.h"
  main()
  {
  int a[N],i,j,temp1;
  printf("please input %d numbers\n",N);
  for(i=0;i<N,i++)
    scanf("%d",&a[i]);
  for(i=0;i<N-1;i++)
        for(j=0;j<N-1-i;j++)
        {
            if(a[j]>a[j+1])
            {
                temp=a[j];
                a[j]=a[j+1];
                a[j+1]=temp;
            }
        }
  printf("the array after sort:\n");
  for(i=0;i<N;i++)
    print("%5d",a[i]);
  }
方法二:选择排序
  首先找出值最小的数,然后把这个数与第一个数交换,这样值最小的数就放到了第一个位置;
然后,在从剩下的数中找值最小的,把它和第二个数互换,使得第二小的数放在第二个位置上。以
                                           -17-
                           计算机程序设计基础(C 语言)实验教材



此类推,直到所有的值从小到大的顺序排列为止。
  #include"stdio.h"
  #define N 10
  main()
  {
     int a[N],i,j,r,temp;
     printf("please input %d numbers\n",N);
     for(i=0;i<N;i++)
        scanf("%d",&a[i]);
     for(i=0;i<N-1,i++)
        { r=i;
         for(j=i+1;j<N;j++)
             if(a[j]<a[r])
                r=j;
             if(r!=i)
                {
                    temp=a[r];
                    a[r]=a[i];
                    a[i]=temp;
                  }
           }
     printf("the array after sort:\n");
     for(i=0;i<N;i++)
         print("%5d",a[i]);
     printf("\n");
  }
6.设计程序(根据教学内容选做)
① 编写程序实现功能:输入 10 个整数,按每行 3 个数输出这些整数,最后输出 10 个整数的平均
值。写出调试过程。
② 设某班最多 20 人,写一程序录入某门课的成绩,当输入成绩为负时,输入结束,统计 90~100,
80~89,70~79,60~69 及不及格的人数分布,以数字显示,
③ 编写程序,任意输入 10 个整数的数列,先将整数按照从大到小的顺序进行排序,然后输入一个
整数插入到数列中,使数列保持从大到小的顺序。
【思考与提高】
  1.用数组表示数据和用变量表示数据的主要区别是什么?数组相对于变量有哪些优越性?什么
  类型的题目用数组来解决比较合适?
  2.一维数组各项在内存中的存储结构是什么样子的?


                          2.5 实验五 二维数组及字符数组

【实验目的】

      1.掌握二维数组的定义、赋值和输入输出的方法;
      2.掌握字符数组的使用;
      3.掌握与数组有关的算法。
【实验内容】
1.调试程序实现对一个 3×4 矩阵,输出其中值最大的元素值,以及它的行号和列号。
【参考源程序】
   #define M 3
   #define N 4

                                        -18-
                               计算机程序设计基础(C 语言)实验教材



  main( )
  {
     int max,min,i,j,r,c;
     statis int a[M][N]={{123,94,-10,218},{3,9,10,-83},{45,16,44,-99}};
     max=a[0][0];
     for(i=0;i<M;i++)
         for(j=0;j<N;i++)
            if ( a[i][j]>max)
              { max= a[i][j];
                 r=i;
                 c=j;
              }
     printf(“max=%d , row =%d , colum=%d \n”,max , r, c);
  }
2.打印下面的图案:
                                             *****
                                             *****
                                             *****
                                             *****
                                             *****
【参考源程序】
  main( )
  {chare a[5]={' * ' , ' * ' , ' * ' , ' * ' , ' * '};
    int i,j,k;
    char space2=' ';
    for(i=0;i<5;i++) /*输出 5 行*/
     {printf("\n"); /* 输出每行前先换行* /
      printf(" "); /* 每行前面留 5 个空格 */
      for (j=1;j<=i;j++)
          printf("%c",space); /* 每行再留 1 个空格*/
      for ( k=0;k<5;k++)
          printf("%c",a[k]); /*每行输入 5 个*号*/
      }
  }
3.求矩阵下三角形元素之和。
【参考源程序】
  #define N 6
  main()
  { int i,j,sum=0;
      int a[N][N]={0};
      printf("input 5×5 data:\n");
      for(i=1;i<N;i++)
        { printf("Input the %d line data:\n",i);
          for(j=1;j<N;j++)
          scan("%d",&a[i][j]);
        }
    for(i=1;i<N;i++)
      { for(j=1;j<N;j++)
            printf("%5d",a[i][j]);
        printf("\n");
      }
  for(i=1;i<N;i++)
    for(j=1;j<=i;j++)
                                                   -19-
                            计算机程序设计基础(C 语言)实验教材



      sum==sum+a[i][j];
  printf("sum=%d\n",sum);
  }
4. 输入一个含若干个字符的字符串,分别搜索出其中的字母和数字,其余的字符一概忽略。将字
母序列和数字序列分别输出。
【参考源程序】
  #include "stdio.h"
  void main()
  { char str[100],str2[100];      //str1 用于存放输入的数字,str2 用于存放输入的字母
      chars c;                        //c 用于存放临时数据的变量
      int i=0,j=0;
      print("\nPlease input a $(0-99):\n");
      while((c=getchar())!='\n' && i<99 &&j<99)   //输入字符串,遇回车符结束
    {
        if(c>=48&&c<=57)
        str1[i++]=c;
        else if(c>=65&&c<=90||c>=97&&c<=122)    //对是否是英文字母进行判断
        str2[j++]=c;
        else;
    }
    str1[i]='\0';                                //加字符串结束标志
    str2[j]='\0';
    printf("The number array:%s\n",str1);
    printf("The number array:%s\n",str2);
  }
  在此程序基础上,实现以下功能:
  每十个字符为一行输出,每五个数字为一行输出。
5.设计程序(根据教学内容选做)
① 编写程序,   输入字符串 s1 和 s2 以及插入位置 f,在字符串 s1• 中的指定位置 f 处插入字符串 s2。
如:输入"BEIJING"、"123"和位置 3,则输出:"BEI123JING123"。
【思考与提高】
  1.多维数组各项在内存中的存储结构是什么样子的?多维数组在人的脑海中是多维的概念,在
    内存中存放的结构是否也是多维的呢?为什么用计算机的一维结构可以表示多维的数据?
  2.理解字符数组与字符串的联系和区别,如何用字符数组表示字符串?




                                2.6 实验六 函数

【实验目的】
  1.学习 C 语言中函数的定义和调用方法。
  2.掌握通过参数在函数间传递数据的方法。
  3.学习使用设置断点的方法调试程序。
  4.掌握含多个源文件的程序的编译、连接和调试运行的方法
  5.学习递归程序设计,掌握递归函数的编写规律。
  6.熟悉 TC 集成环境对包含函数调用的程序的调试方法。
【实验内容】
1.写两个函数,分别求两个正数的最大公约数和最小公倍数,用主函数调用这两个函数并输出结
果。两个正数由键盘输入。

                                    -20-
                           计算机程序设计基础(C 语言)实验教材



【参考源程序】
  #include "stdio.h"
  hcf(int u,int v)
  {
       int a,b,t,r;
       if(u>=v)
       {
          t=u; u=v; v=t;
       }
       a=u; b=v;
       while((r=b%a)!=0)
       {
          b=a; a=r;
       }
       return(a);
  }

  lcd(int u,int v,int h)
  {
      return(u*v/h);
  }

  mian()
  {
      int u,v,h,l;
      scanf("%d,%d",&u,&v);
      h=hcf(u,v);
      printf("H.C.F=%d\n",h);
      l=lcd(u,v,h);
      print("L.C.D=%d\n",l);
  }
2.写一函数,用“冒泡法”对输入的 10 个字符按由小到大顺序排序。
【参考源程序】
  #define N 10
  char str[N];
  main()
  {
       int i,flag;
       for (flag=1; flag = =1;)
       {
         printf(“\n 输入字符串,长度为 10:\n”);
         scan(“%s”,&str);
         if (strlen(str)>N)
             printf(“超过长度,请重输!     ”);
         else
         flag = 0;
       }
       sort(str);
       printf(“\n 排序结果:        ”):
       for (i=0;i<N;i++)
         printf(“%c”,str[i]);
  }

       sort(str)
       char str[N];

                                   -21-
                                    计算机程序设计基础(C 语言)实验教材



        {
            int i,j;
            char t;
            for (j=1;j<N;j++)
            for (i=0;(i<N-j)&&(str[i]!=’\0’);i++)
            if (str[i]>str[i+1])
              {
                    t=str[i]; str[i]=str[i+1]; str[i+1]=t;
              }
        }
3. 编制求两数相乘的函数。
【参考源程序】
  #include "stdio.h"
  float mul(float x,float y)
  {
     float z;
     z=x*y;
     return(z);
  }

  main()
  {
  float x,y,z,m;
  scanf("%f,%f",&x,y);
  z=mul(x,y);
  printf("The result is %f",&z);
  }

4. 求 100 名职工的平均工资。
【参考源程序】
  #include "stdio.h"
  float average(float array[ ])
  {
     int i;
     float aver,summ=array[0];
     for(i=1;i<100;i++)
        sum=sum+array[i];
        aver=sum/100;
        return(aver);
  }

  main( )
  {
    float salary[100],aver;
    int i;
    printf("Please enter 100 salaries:\n");
    for(i=0;i<100;i++)
        scanf("%f",&salary[i]);
    printf("\n");
    aver=averag(salary);
    printf("Average salary is %6.3f",aver);

    }


                                                       -22-
                          计算机程序设计基础(C 语言)实验教材



  将此题目改成求工资较高的前 5 名工资并打印输出。
5.编写程序实现求魔方。对于 n 行 n 列的方阵(n 为奇数),将 1~n2 共 n2 个数填于此方阵中,如果
所得方阵中的每一行、每一列与两对角线上各数之和均相等,则称此方阵为魔方纵横图。            (提高题)
【编程解析】
   根据结构化程序设计自顶向下的方法,可以将从键盘输入 n 值的操作放在主函数 main()         ,将
计算魔幻纵横图的任务由自定义函数 magic( )来完成,自定义函数 magic( )的传递参数为正整
数 n、整数数组 square[ ][ ],无函数返回值。另外将输出魔幻纵横图的任务由自定义函数 put_magic
()来完成,自定义函数 put_magic()的传递参数同样为正整数 n、整数数组 square[ ][ ],无函数
返回值。
  计算魔幻纵横图的一个简便算法为:从第一个数 1 开始,然后为 2,3…直至 n2 依次放置。放
置规则为:① 放在方阵正中央的正下方。
      1
      从
     ② 2 开始,依次放在前一数的下一行、下一列处。
     ③如前一数已在最下行,则第一行作为下一行。
     ④如前一数已在最右列,则第一列作为下一列。
     ⑤如欲放置处已放置有数,则另放在前一数所在处同列的下两行处。
【算法流程图】
  主函数 main( )流程图如图 2-6 所示。
  计算魔幻纵横图的自定义函数 magic( )的流程图如图 2-7 所示。函数传递参数:n 为整型,
方阵长度,行、列的最大限制值。square[ ][ ]:二维整型数组,存放方阵中数据。调用时,用数组名
作函数参数传送整个数组,是“传址”方式,请注意其用法。无函数返回值。
  输出魔方纵横图的自定义函数 put_magic()的流程图如图 2-8 所示。函数传递参数:n 整型,
方阵长度,行、列的最大限制值。square[ ][ ] :二维整型数组,存放方阵中数据。无函数返回值。
【参考源程序】
  #define MAX 16               /* 数组下标从 0 开始,MAX 定义为 16,则数组下标为 0~15 */
  #include <stdio.h>
  void magic(int square[ ][MAX],int n);            /* 计算魔幻纵横图 */
  void put_magic(int square[ ][MAX],int n);        /* 输出魔幻纵横图 */
  void main( )
  { int n,square[MAX][MAX]={0};            /* 数组元素初值全赋 0,表示空方阵 */
     do{
           printf("input n=",&n);scanf("%d",&n);         /* 保证从键盘输入的 n 值在  */
        } while(n<2 || n>MAX || !(n%2));           /* 3~15 之间,且为奇数      */
     magic(square,n);                          /* 调用函数 magic( ),填写魔幻纵横图 */
     put_magic(square,n);                  /* 调用函数 put_magic( ),打印魔幻纵横图 */
  }




                                        -23-
                           计算机程序设计基础(C 语言)实验教材




void magic(int square[MAX][MAX],int n)
     { int mid,order,i,j,j1;
        mid = n/2+1;                                    /* 计算方阵中心坐标值 */
        order = 1;                                      /* 初值 :1      */
        i = mid+1;                                      /* 行坐标初值 :方阵中心下一行 */
        j = mid;                                        /* 列坐标初值 :方阵中心列     */
        square[i][j] = order;                           /* 置放第一个数 :1  */
        while (order < n*n)
        { order ++;                                     /* 下一个数       */
           i=i % n + 1;                  /* 下一个数的行坐标,如前数坐标=n,则此时计算得 1 */
           j1=j; j=j % n + 1;            /* j:下一个数的列坐标,j1:前一个数的列坐标       */
           if (square[i][j] != 0)
             { j =j1; i=i % n + 1;} /* 欲放置处已有数,调整坐标值 */
               square[i][j] = care ;                /* 置放下一个数      */
        }
     }

     void put_magic(int square[MAX][MAX],int n)
     { int i,j;
        for(i=1;i<=n;i++)
         { for(j=1;j<=n;j++)
              printf("%5d",square[i][j]);
              printf("\n");
         }
     }
     操作及结果 此程序运行时的输入、输出的界面为:
input n=5
         11 24         7 20      3
           4 12 25          8 16
         17      5 13 21         9
                                        -24-
                             计算机程序设计基础(C 语言)实验教材



        10    18    1   14   22
        23     6   19    2   15
     或者:
input n=7
        22    47   16   41   10   35    4
          5   23   48   17   42   11   29
        30     6   24   49   18   36   12
        13    31    7   25   43   19   37
        38    14   32    1   26   44   20
        21    39    8   33    2   27   45
        46    15   40    9   34    3   28
…
小结 :
    ① 这是一个有趣但结构、编程均比较简单的例子,从主函数流程图可以清楚的看出来。
    ② 计算魔幻纵横图的算法也是清楚、简便的,但要归纳出此算法恐怕也不是一件容易的事。
    ③ 方阵中的每一个数输出时占 5 位, MAX 定义为 16,限制输入 n 的取值在 3~15 范围内,
    是考虑到在输出屏幕为 80 字符的情况下,输出的魔幻纵横图完整、清晰。理论上不存在 n 的取
    值限制。但在 C 语言无符号长整数的范围内,n2 应小于 4294967295。
    ④ 本例涉及 C 语言程序的模块化结构(模块划分) 、用于函数声明的函数原型、函数定义、函
    数调用以及函数间的数据传送:形参与实参、数组作为函数参数等方面的知识。另外,也使用
    了全局变量 MAX,以区别于局部变量的作用范围。
6.设计程序(根据教学内容选做)
    ① 设计一个求三个数最大值的函数,然后输入 7 个数,通过调用该函数的方式求出 7 个数的
    最大值并且输出。
    ② 调试下列程序,使之具有如下功能:fun 函数是一个判断整数是否为素数的函数,使用该函
    数求 1000 以内的素数的个数以及它们的平均值。
       #include "math.h"
       main( )
       {    int a=0,k; /* a 保存素数之和 */
            float av; /* av 保存 1000 以内素数的平均值 */
            for(k=2;k<=1000;k++)
              if(fun(k)) /* 判断 k 是否为素数 */
                a+=k;
              av=a/1000;
              printf("av=%f\n",av);
       }
       fun(int n) /* 判断输入的整数是否为素数 */
       {    int i,y=0;
            for(i=2;i<n;i++)
            if(n%i==0) y=1;
            else y=0;
         return y;
       }
    ③ 任意输入一个 4 位自然数,调用函数输出该自然数的各位数字组成的最大数。      (选做题)
    ④ 用函数的方法重新规划小学生算术测试系统(提高题)
    ⑤ 汉诺塔(Hanoi Tower)问题(提高题)

【思考与提高】
    1.函数一般可解决什么类型问题?该类问题如果不用函数可以解决吗?函数的优点在哪里?
    2.函数的定义有几种方法?调用过程中有什么注意事项?形式参数和实际参数间的关系是什么?


                                            -25-
                           计算机程序设计基础(C 语言)实验教材



                                  2.7 实验七 指针

【实验目的】
  1.掌握指针变量的定义与引用;
  2.掌握指针与变量、指针与数组的关系;
  3.掌握用数组指针作为函数参数的方法;
  4.熟悉 TC 集成环境的调试指针程序的方法。
【实验内容】
1.调试下列程序,使之具有如下功能:用指针法输入 12 个数,然后按每行 4 个数输出。写出调试
过程。
【参考源程序】
  main()
  { int j,k,a[12],*p;
    for(j=0 ,j<12;j++)
      scanf("%d",p++);
    for(j=0;j<12;j++)
    { printf("%d",*p++);
        if (j%4 = 0)
       printf("\n");
    }
  }
  调试此程序时将 a 设置为一个"watch",数组 a 所有元素的值在一行显示出来。调试时注意指针
变量指向哪个目标变量。
2.调试下列程序,使之具有如下功能:任意输入两个数,调用两个函数分别求:
 ⑴ 两个数的和,
 ⑵ 两个数交换值。

  要求用函数指针调用这两个函数,结果在主函数中输出。
【参考源程序】
  main()
  { int a,b,c,(*p)();
     scanf("%d,%d",&a,b);
     p=sum;
     *p(a,b,c);
     p=swap,
     *p(a,b);
     printf("sum=%d\n",c);
     printf("a=%d,b=%d\n",a,b);
  }

  sum(int a,int b,int c)
  { c=a+b;}

  swap(int a;int b)
  { int t;t=a;a=b;b=t;}
调试程序时注意参数传递的是数值还是地址。
3.使用指针对数组元素进行输入输出。

                                      -26-
                             计算机程序设计基础(C 语言)实验教材



【参考源程序】
  #include <stdio.h>
  void main()
  {
    float data[5],*pf=data;
    int k;
    print("Input datas:\n");
    for(k=0;k,5;k++)
       scanf("%f",pf+k);
    for(k=0;k<5;k++)
       {
       printf("%.1f",*pf);
       pf++;
       }
       pf=data;
       printf("\n");
       for(k=0;k<5,k++)
           printf("%.1f,",*(pf+k));
       printf("\n");
  }
  如果取消第 14 行:pf=data,程序运行结果是什么?为什么会出现这样的结果?
4.有 n 个人围成一圈,顺序编号。从第一个人开始报数(从 1 到 m),凡报到 m 的人退出圈子,问最
后一个圈中的人的编号?
【编程解析】
(1) 可以用一个数组保存 n 个人的编号,当此人退出圈子时
将编号变为 0;
(2) 用一个计数器 i 模拟每个人的编号,     如果此人已出圈 (即
编号为 0) ,则跳过此人不计数,否则进行累加,当报完一圈
后将 i 置 0,重新计数;
(3) 用一个计数器 k 模拟报数,当 k==m 时,将 k 置 0 再从
头报数。
(4) 用一个变量 quit_num 记录出圈的人数,  当圈中只剩一个
人时,即 quit_num == n-1,停止报数,输出结果。
(5) 对数组进行搜索,查找编号不为零的人(留在圈中的人),
输出他的编号。
【算法流程图】见图 2-9 所示。
【参考源程序】
  #include "stdio.h"
  void main()
  {
       int i = 0;              //循环变量
       int k = 0;              //报数的计数器
       int quit_num = 0;       //退出的人数
       int n;                  //总人数
       int m;             //报数的最大数
       int numm[100]; //保存所有人的编号
       int *p = num; //初始化指针,使其指向 num 数组
       printf("Please input number of person: n = ");
       scanf("%d", &n);
       printf("Please input the number m = ");
       scanf("%d", m);
                                            -27-
                             计算机程序设计基础(C 语言)实验教材



        /*给所有的人编号为 1 到 n */
        for (i = 0 ; i < n ; i ++ )
        { *(p + i) = i + 1; }
        i = 0;

       /*当未退出人数大于 1 时 执行循环*/
       while(quit_num < n - 1)
       {     if(*(p+i) != 0) k++; //已经出圈的人不参与报数//
    //报数为 m 时
       if( k == m )
         {
                   *(p + i) = 0;  //退出圈子时将此人编号置 0
                   quit_num ++;
                   k = 0;        //重新报数
             }
             i ++;
             if (i == n) i = 0; //一圈报完后,再从头循环
       }
       while (*p == 0) p ++;            //查找留在圈中的人
       printf("The last one’s number is : %d\n" , *p);
    }

操作及结果:
  Please input number of person: n = 15
  Please input the number m = 7
  The last one’s number is: 5

另外考虑一下,如果要输出所有人出圈的顺序,程序应该怎么写?
5. 输入一段文字,将其中连续的数字作为整数存放在另一数组中,并统计整数的个数。
如:输入 ads67df-u823; sa(hg)673 6ssd23
则其中整数个数为 5,分别为:67 823 673 6 23
【编程解析】
(1) 对字符串从头到尾对每个字符进行扫描,即利用循环,每次读取一个字符,直到遇到字符串结
束标志’\0’为止。
(2) 利用一个变量 j 记录连续数字的个数,每遇到数字将 j 加 1,遇到其他字符,则将 j 置 0,以后
可以利用 j 计算连续数字的值。
(3) 扫描时,每当遇到非数字字符,而 j>0 时,表示一个数字结束,如 j==0 则表示前面也不是数字
字符。
(4) 利用一个变量 digit_num,统计数的个数,当数字结束时 digit_num 加 1。
(5) 对于连续的几个数字字符,由于扫描到的是一个一个数字字符,没有实际的值,因此在一个数
字结束,要通过一个函数 digitvalue()来计算连续数字字符的值。
(6) 用一个数组 a 保存得到字符数字的值,一个数组元素保存一个数。
(7) 如果字符串是以数字结束的,由于遇到字符串结束标志’\0’就退出了循环,最后一个数字还没有
处理到,因此,退出循环后还要再进行一次判断(判断最后是否为数字)和计算。
(8) 最后将数组 a 中的每个元素输出。
【算法流程图】如图 2-10 所示。
【参考源程序】
    #include "stdio.h"
    void main()
    {
         char str[100];
                                          -28-
                         计算机程序设计基础(C 语言)实验教材



    char *pstr = str;
    int i = 0;
    int j = 0;           //保存连续数值的位数
    int digit_num = 0; //用于统计整数的个数
    int a[10] , *pa = a; //用于保存整数
    print("Please input a string:");
    get(str);
    printf("\n");

while (*(pstr + i) != '\0')
      {
            if (*(pstr + i) >= '0' && *(pstr + i) <= '9')
                  j ++;
            else
            {
                  if(j > 0) //j>0 表示有数存在
                  {
                        *pa = digitvalue(j,pstr,i);
                        digit_num ++;
                        pa ++;
                        j = 0;
                  }
            }
            i ++;
      }
//处理以数字结尾字符串的最后一个数据
      if (j > 0)
      {
            *pa = digitvalue(j,pstr,i);
            digit_num ++;
            pa ++;
            j = 0;
      }
      printf("There are %d numbers in the string.\n",digit_num);
      pa = a;
      printf("The number is :");
      for (i = 0 ; i < digit_num ; i ++)
            printf("%d " , *(pa + i));
      printf("\n");
}
// 功能:计算连续数字字符的值。
// 参数:j 是数字字符的位数;
// *pstr :字符串,
// i        :连续的数字字符在字符串中的位置
// 返回值            :连续的数字字符串的数值
int digitvalue(int j, char *pstr,int i)
{
      int digit;                                 //保存从字符串中读取的整数
      int k = 1;
      int e10;
      int m;
      digit = *(pstr + i - 1) - '0';                //将数保存在 digit 中
      k = 1;                                        //已经处理了的数字的位数
      while (k < j)                                 //连续的数字还没处理完
      {
            e10 = 1;                                //代表该位数应乘的因子

                                        -29-
                                   计算机程序设计基础(C 语言)实验教材



              for (m = 1 ; m <= k ; m ++)
                   e10 = e10 * 10;
              digit = digit + (*(pstr + i - 1 - k) - '0') * e10;
              k ++;
         }
         return digit;
     }
     操作及结果:
     Please input a string: ads67df-u823; sa(hg)673 6ssd23
     There are 5 numbers in the string.
     The number is : 67 823 673 6 23

6.设计程序(根据教学内容选做)
① 用指针法输入 12 个数,然后按每行 4 个数输出。
                                  。例如:
② 请编程读入一个字符串,并检查其是否为回文(即正读和反读都是一样的)
  读入:MADA M I M ADAM. 输出:YES
  读入:ABCDBA. 输出:NO
【思考与提高】
1.   弄清楚指针、地址的概念以及它们与其存放数据的关系,不要混淆指针和指针所指向的数据。
2.   用指针对数组进行操作时,清楚指针自加或自减后所指向的数组的项并清楚其原理。
3.   指针是 C 语言的重要特色,为什么说指针具有很大优势?编程时用指针又具有很大隐患?




                                     2.8 实验八 结构体(结构)

【实验目的】
     1.掌握 C 语言中结构体类型的定义和结构体变量的定义和引用;
     2.掌握用结构体指针传递结构数据的方法;
     3.熟悉 TC 集成环境的调试结构程序的方法。
【实验内容】
1. 统计全年级男女生人数及 1997 年到 1980 年出生的人数(含 1977 年和 1980 年)。
【参考源程序】
     #include "stdio.h"
     #include "stdlib.h"
     void main()
     {
       struct studt
       {
         char name[30];
         char sex;
         int year;
       };

       struct stud grade[300];
       int m_num,f_num,total,i;
       for(i=0;i<50;i++)
       {
          printf("\nPlease enter name/sex/year:\n");
          scanf("%s%c%d",grade[i].name,&grade[i].sex,&grade[i].year);

                                                      -30-
                             计算机程序设计基础(C 语言)实验教材



      }
      for(i=0;i<300;i++)
      {
        if((grade[i].year>=1977)&&(grade[i].year<=1980))
          total++;
        if((grade[i].sex=='m')||(grade[i].sex=='M'))
          m_num++;
      else
          f_numm++;
      }
      printf("\n 男生人数:%d",m_num);
      printf("\n 女生人数:%d",f_num);
      printf("\n 1977 年到 1980 年出生的人数: %d",total);
      }

    将程序改成分行输出 1977-1980 年出生的学生的所有信息(姓名、性别、出生年)
2.指向结构体数组指针的应用。
【参考源程序】
    #include "stdio.h"
    struct stud
    {
      char *idnumber;
      char name[30];
      int score;
      };

     struct stud student[3]={{"970001","Kun YI",97},
        {"970002","Liu YANG",98},{"980005","Tie SANG",89}};

     main( )
     {
     struct stud *sp;
     printf("\n\nStudent No.    Name     Score
\n");
     for(sp=student;sp<student+3;sp++)
         printf("%-20s%-20s%4d\n",sp->idnumbe
r,sp->name,sp->score);
     }
3.现有一个班共 30 名学生,每个学生信息包括姓
名、学号、以及期末总成绩。要求编写程序找出其
中总分最高和最低的学生,   并分别打印出其所有信
息。
【编程解析】
     本题定义了一个一维数组来存放这个班所有
的学生,     而数组元素都为同一结构体变量用来存放
每个学生的姓名、学号、以及期末总成绩信息,通
过对这个结构数组的处理完成了题目的要求。
问题解析:
(1) 程序的输入与输出:      输入一维数组各元素的值
info[index],即每个学生的所有信息,输出满足要
求的结构体类型的数组元素。
(2) 数据结构: struct student info[N];int index ,max_loc,min_loc;float max,min;char instring[10];

                                            -31-
                            计算机程序设计基础(C 语言)实验教材



(3) 解决问题的关键算法:程序主框架是对指定的一维数组求最大最小值并输出。
              一维数组赋初值采用单循环语句为一维数组赋初值。
              求最大最小值用循环语句内嵌选择结构找出最大最小值。
【算法流程图】如图 2-11 所示。
【参考源程序】
  #include<stdio.h>
  #include<stdlib.h>
  #define N 30
  struct student
  { char name[15];
      long int xuehao;
      float score;
  };
  main( )
  { struct student info[N];
      int index,,max_loc,min_loc;
      float max,min;
      char instring[10];
      for(index=0;index<N;index++)
    {printf(“Name?”);
      gets(info[index].name);
      printf(“Xuehao?”);
      gets(instring);
      info[index].xuehao=atoi(instring);
      printf(“Score?”);
      gets(instring);
      info[index].score=atof(instring);
        }
    max=min=info[0].score;
    max_loc=min_loc=0;
    for(idex=0;index<N;index++)
  {if(max<info[index].score)
        {max=info[index].score;
  max_loc=index;}
    if(min>info[index].score)
  {min=info[index].score;
    min_loc=index;}
  printf(“\n Max Score Name\n”);
  printf(“%f\t%ld\t%s”,info[max_loc].score,info[max_loc].xuehao,info[max_loc].name);
  printf(“\n Min Score Name\n”);
  printf(“%f\t%ld\t%s”,info[min_loc].score,info[min_loc].xuehao,info[min_loc].name);
  }

  本题的思路可扩大到任何同类型问题上,即我们可以将任何相同的数据类型组织成一个数组类
型,然后利用对数组的处理达到题目的要求。其思路总结为:
(1)正确定义结构体类型、数组类型。
(2)给结构体类型和数组类型变量赋初值。
(3)根据题意选择正确的算法对数组进行运算并输出结果。
4.设计程序(根据教学内容选做)
① 设计一个保存学生情况的结构,学生情况包括姓名、学号、年龄。输入 5 个学生的情况,输出
学生的平均年龄和年龄最小的学生的情况。要求输入和输出分别编写独立的输入函数 input()和输出
函数 output()。
② 使用结构数组输入 10 本书的名称和单价,调用函数按照书名的字母顺序进行排序,在主函数输
                                           -32-
                            计算机程序设计基础(C 语言)实验教材



出排序结果。
【思考与提高】
  1.用结构体主要解决什么类型的问题?该类型问题如果不用结构体,麻烦在哪里?
  2.深入理解和掌握用指针来处理结构体数组的方法。

                                2.9 实验九 文件操作

【实验目的】
  1.掌握 C 语言中文件和文件指针的概念;
  2.掌握 C 语言中文件的打开与关闭及各种文件函数的使用方法;
  3.熟悉 TC 集成环境的调试文件程序的方法。
【实验内容】
1.调试程序实现向 data.dat 文件写入 100 条记录。
【参考源程序】
  #include <stdio.h>
  main()
  {FILE *fp1;
    int i;
    flost x;
    fp=fopen("date.dat","w");
    for(i=1;i<=100;i++)
      {scanf("%f",&x);
        fprintf(fp,"%f\n",x);
      }
    fclose(fp);
  }
2.设有一文件 cj.dat 存放了 50 个人的成绩(英语、计算机、数学),存放格式为:每人一行,成绩
间由逗号分隔。计算三门课平均成绩,统计个人平均成绩大于或等于 90 分的学生人数。
【参考源程序】
  #include <stdio.h>
  main()
  {FILE *fp;
     int num;
     float x , y , z , s1 , s2 , s3 ;
     fp=fopen ("cj.dat","r");
       {fscan (fp,"%f,%f,%f",&x,&y,&z);
         s1=s1+x;
         s2=s2+y;
         s3=s3+z;
         if((x+y+z)/3>=90)
         num=num+1;
       }
    printf("分数高于 90 的人数为:%.2d",num);
    fclose(fp);
  }
3.统计上题 cj.dat 文件中每个学生的总成绩,并将原有数据和计算出的总分数存放在磁盘文件“stud”
中。
【参考源程序】
  #include "stdio.h"

                                     -33-
                             计算机程序设计基础(C 语言)实验教材



  main()
  {
     FILE *fp1,*fp2;
     float x,y,z;
     fp1=fopen("cj.dat","r");
     fp2=fopen("stud","w");
     while(!feof(fp1))
       {
         fscanf (fp1,"%f,%f,%f",&x,&y,&z);
         printf("%f,%f,%f,%f\n",x,y,z,x+y+z);
         fprintf(fp2,"%f,%f,%f,%f\n",x,y,z,x+y+z);
       }
    fclose(fp1);
    fclose(fps);
  }
4.TYPE 命令模拟。在 windows 的 MS-DOS 方式下有一个 DOS 内部命令 TYPE,用于显示文本
文件的内容,其命令使用格式为:TYPE FILE。在此我们使用 C 语言来模拟实现该程序。
【编程解析】
  要求编写的是一个与文件处理相关的程序。该程序以文件作为输入,向屏幕输出文件内容。
该例程序涉及使用命令行参数,但例程在算法上比较简单,只需按文本格式打开文件,并以字符为
单位顺序读出,显示到屏幕上,直至检测到文件结束符(EOF)程序结束。
【算法流程图】




【参考源程序】
  #include <stdio.h>
  #include <stdlib.h>
  void      dispfile(FILE *rtf);
  main(int argc,char *argv[])
  {
       int i;
       FILE *rtfp;
       if (argc!=2)
       {
           printf("Usage: Smpl8_1 TXTFILEPATH");
           exit(-1);

                                             -34-
                                计算机程序设计基础(C 语言)实验教材



         }
         rtfp = fopen(argv[1],"rt");
         if (rtfp==NULL)
         {
               printf("File Open Error,Check File Exist!");
               exit(-2);
         }
         dispfile(rtfp);
         fclose(rtfp);
         return 0;
  }

  void        dispfile(FILE *rtf)
  {
         char     ch1;
         ch1 = fgetc(rtf);
         while (ch1!=EOF)
         {
              putchar(ch1);
              ch1=fgetc(rtf);
         }
  }
  运行结果分析:
  Smpl8_1<回车>
  Usage: Smpl8_1 TXTFILEPATH

  Smpl8_1 NONAMSES.DAT<回车>
  File Open Error,Check File Exist!

  Smpl8_1 Smpl8_1.c<回车>
  此问题的求解思路可通用地扩展到对文本文件进行按字符分析的各种问题。
  其思路总结为:打开读文本文件;读出字符;当字符不是文件结束符时分析该字符,读取下一
字符,关闭文本文件。
5.编写程序实现文件的复制,其中源文件名称和目标文件名称使用命令行参数提供。
【编程解析】
  本例程序输入和输出全部在文件上完成。程序涉及的文件可能是文本文件,也可能是二进制文
件,但程序本身并不分析其数据,应统一考虑使用二进制方式。程序实现有两种办法:按字符模式
和按块模式。
  算法一:字符模式
  反复从源文件中读出字符,直接写入目标文件中,直至源文件结束。采用此方法实现上比较简
单,但因为读写磁盘比较频繁,在文件比较大时,效率不高。
  算法二:块模式
  先在内存中分配一个较大的缓冲区,反复从源文件中读取和缓冲区等长的数据块到缓冲区中,
将缓冲区中的数据写入目标文件,直至读出的长度小于缓冲区长度或文件结束。对于较大的文件,
本算法是效率比较高的。
【结构分析】
  1、 本程序主程序处理命令行参数和文件打开状态,关闭等问题。
  2、 文件的复制过程可设计为函数 datacopy,参数一为打开读的文件类型变量 rbfp,参数二为打
     开写的文件类型变量 wbfp。
【算法流程图】如图 2-15,图 2-16,图 2-17 和图 2-18 所示。
【参考源程序】


                                                 -35-
                                       计算机程序设计基础(C 语言)实验教材



#include <stdlib.h>
    #include <stdio.h>
    #define BUFLEN             30000

    void          datacopy(FILE *rbfp,FILE *wbfp);
    void          main(int argc,char     *argv[])
    {
             FILE       *rbfp,*wbfp;
             if (argc!=3)
             {
                  printf("Usage:SMPL8_3 SourceFile DestFile");
                  return;
             }
             rbfp = fopen(argv[1],"rb");
             if   (rbfp==NULL)
             {
                  printf("Source File can't be Found!");
                  return;
             }
             wbfp = fopen(argv[2],"wb");
             if   (wbfp==NULL)
             {
                  printf("Dest File can't be Create!");
                  return;
             }
             datacopy(rbfp,wbfp);
             fclose(rbfp);
             fclose(wbfp);

    }
/*算法一:以字符方式进行复制
    void          datacopy(FILE *rbfp,FILE *wbfp)
    {
             int ch1;
             ch1 = fgetc(rbfp);
             while (ch1!=EOF)
             {
                  fputc(ch1,wbfp);
                  ch1 = fgetc(rbfp);
             }
    }
        */
/*算法二之方法一:测试文件结束
    void       datacopy(FILE *rbfp,FILE *wbfp)
    {    char *buffer;
         long readbytes;
         buffer = (char *)malloc(BUFLEN);
         while (!feof(rbfp))
         {
              readbytes = fread(buffer,1,BUFLEN,rbfp);
              fwrite(buffer,1,readbytes,wbfp);
         }
         free(buffer);
    }
    */

                                                  -36-
                             计算机程序设计基础(C 语言)实验教材



/*算法二之方法二:通过文件长度控制
  void         datacopy(FILE *rbfp,FILE *wbfp)
  {     char *buffer;
        long readbytes;
        long filelength;
        long copycount;
        long i;
        buffer = (char *)malloc(BUFLEN);
        fseek(rbfp, 0L, SEEK_END);
        filelength = ftell(rbfp);
        rewind(rbfp);
        copycount = ((filelength%BUFLEN==0)?
  (filelength/BUFLEN):(filelength%BUFLEN+1));
        for (i=0;i<copycount;i++)
        {
              readbytes = fread(buffer,1,BUFLEN,rbfp);
              fwrite(buffer,1,readbytes,wbfp);
        }
        free(buffer);
  }




  对文件的操作通常可通过两种方式处理:字节方式和块方式。字节方式通过测试读取的字节是
否为文件结束符号 EOF 控制结束。块方式则通过使用测试文件是否结束的函数 feof 控制结束。另外,
两种方式还可以通过先获取文件长度,计算出次数,通过次数来控制结束。


                                              -37-
                计算机程序设计基础(C 语言)实验教材



6.设计程序(根据教学内容选做)
① 有 5 个学生,每个学生有 3 门课的成绩,从键盘输入以上数据(包括学生号,姓名,三门课成
绩)  ,计算出平均成绩,将原有数据和计算出的平均分数存放在磁盘文件“stud”中。
② 将上题“stud”文件中的学生数据,按平均分进行排序处理,将已排序的学生数据存入一个新文件
“stu_sort”中。
【思考与提高】
1. 文件操作这一部分内容在软件开发中的作用是什么?
2. 掌握常用的几个读写函数,弄清不同函数的用法,知道什么时候用什么函数。


            第三章 课外上机实验内容(提高实验)

3.1 综合实验一

问题描述:一个学生信息包括学号、姓名、年龄、身高 4 项信息。编写程序实现对学生信息的处理。
  (1)输入若干学生的信息,下一次输入之前进行提示选择,输入的选择为字符串“END”则结束,
否则继续。输入的信息以文本文件格式保存,文件名通过命令行参数给出;学生信息各个信息项之
间用制表符隔开,每个学生信息占一行。
             ,生成学生信息文件。编写程序统计学生的人数、平均年龄、平均身高。
  (2)通过运行程序(1)
将所有学生的信息和统计信息送打印机打印。
【编程解析】
  程序(1):本程序输入为键盘,输出为文本文件。通过键盘输入学生信息,学生信息各项之间
输入时以空格分隔,并需要按预定格式写入文件中。
  程序(2):本程序以文本文件为输入,输出到打印机,按预定文本格式读取数据并进行相关计
算,打印机可以作为可写文件使用,参见预备知识 1.5。
【算法分析】
  本程序处理的是学生信息,声明为结构比较适宜。结构名称为 studentinfo。
  程序(1):程序在内存中只需要存储一个学生的信息即可。故声明一个学生信息变量,循环读
取学生信息,将结构变量各个域按格式写入文本文件,并提示是否继续,当输入回答<>END 时,继
续输入,否则结束。
  程序(2):此程序可完全想像为从键盘输入,循环读取学生记录,送打印机文件,同时记载人
数、年龄和、身高和,直至文件结束符。再将统计信息写入打印机设备。
【结构分析】
  程序(1):
  ① 将输入一个学生信息的过程抽象为函数 getonestudent,输入参数为学生信息结构的指针,
  学生信息变量在函数中赋值。
  ② 将输出一个学生信息的过程抽象为函数 putonestudent,输入参数为学生信息结构和打开的
  写入文本文件的类型变量。
  ③ 将输入学生信息并保存为文本文件的过程定义为函数 inputstudentfile,输入参数为打开的
  写入文本文件的类型变量。
  ④ 测试学生信息是否输入结束定义为函数 isendinfo,输入参数为输入的字符串。
  程序(2):
  ① 将读取一个学生信息的过程定义为函数 readonestudent,输入参数为打开读的文本文件变量
  和学生信息结构的指针。
  ② 将一个学生的信息输出到打印机的过程定义为函数 printonestudent,输入参数为学生信息
  结构和打开的打印机文件类型。
  ③ 将读取学生信息,统计并打印学生及统计信息的过程定义为函数 printall 参数为打开的文本

                         -38-
                     计算机程序设计基础(C 语言)实验教材



   文件类型。
【算法流程图】
程序(1)流程见图 2-19、图 2-20、图 2-21、图 2-22 和图 2-23 所示。
程序(2)流程图 2-24、图 2-25、图 2-26 和图 2-27 所示。




                                -39-
                               计算机程序设计基础(C 语言)实验教材




【参考源程序】程序(1)
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>

  struct studentinfo{
       char stid[20];
       char name[30];
       int age;
       float height;
  };

  void       getonestudent(struct studentinfo *stinfoptr);
  void       putonestudent(struct studentinfo stinfo,FILE *wtfp);
  int       isendinfo(char *astr);
  void       inputstudentfile(FILE *wtfp);

  void       main(int argc,char *argv[])
  {
         FILE      *wtfp;
         if (argc!=2)
         {
             printf("Usage:SMPL8_41 TXTFILENAME");
             return;
         }

         wtfp = fopen(argv[1],"wt");

                                               -40-
                                 计算机程序设计基础(C 语言)实验教材



         if (wtfp==NULL)
         {
              printf("file write error,check file name!");
              return;
         }
         inputstudentfile(wtfp);
         fclose(wtfp);
  }

  void       getonestudent(struct studentinfo *stinfoptr)
  {
         struct studentinfo ast;
         printf("Please Input student at one line[stid name age height]:\r\n");
         scanf("%s %s %d %f%c",ast.stid,ast.name,&(ast.age),&(ast.height));
         *stinfoptr = ast;
  }

  void       putonestudent(struct studentinfo stinfo,FILE *wtfp)
  {
         fprintf(wtfp,"%s       %s %d %5.1f\r\n",
         stinfo.stid,stinfo.name,stinfo.age,stinfo.height);
  }

  int        isendinfo(char *astr)
  {
         int code,result;
         code = strcmp(astr,"END");
         result = 0;
         if (code==0) result=1;
               return result;
  }

  void       inputstudentfile(FILE *wtfp)
  {
         struct studentinfo ast;
         char answerstr[100];
         do {
              getonestudent(&ast);
              putonestudent(ast,wtfp);

             printf("continue?[YES/END]:");
             gets(answerstr);
         } while (!isendinfo(answerstr));
  }

【参考源程序】程序(2)
  #include <stdlib.h>
  #include <stdio.h>
  #include <string.h>

  struct studentinfo{
       char stid[20];
       char name[30];
       int age;
       float height;
  };


                                                   -41-
                                 计算机程序设计基础(C 语言)实验教材



void        readonestudent(FILE *rtfp,struct studentinfo *stinfoptr);
void        printonestudent(struct studentinfo stinfo,FILE *prnfp);
void        printall(FILE *rtfp);

void        main(int argc,char *argv[])
{
       FILE       *rtfp;

       if   (argc!=2)
       {
            printf("Usage:SMPL8_42 TXTFILENAME");
            return;
       }

       rtfp = fopen(argv[1],"rt");
       if (rtfp==NULL)
       {
             printf("Error at Opening file,Check file is exists!");
             return;
       }

       printall(rtfp);

       fclose(rtfp);

}

void        readonestudent(FILE *rtfp,struct studentinfo *stinfoptr)
{
       struct studentinfo ast;

       fscanf(rtfp,"%s\t%s\t%d\t%f\n",ast.stid,ast.name,&(ast.age),&(ast.height));

       *stinfoptr = ast;
}

void        printonestudent(struct studentinfo stinfo,FILE *prnfp)
{
     fprintf(prnfp,"%s       %s %d %5.1f\r\n",
stinfo.stid,stinfo.name,stinfo.age,stinfo.height);
}

void        printall(FILE *rtfp)
{
       struct studentinfo ast;
       int       stcount=0,totalages=0;
       float totalheights=0.00;
       float aveage,aveheight;

       FILE      *prnfp;

prnfp = fopen("PRN","wt");
    if (prnfp==NULL)
    {
          printf("Error at Opening Print Device,Check Print Be Connectted!");
          return;
    }


                                                 -42-
                             计算机程序设计基础(C 语言)实验教材



      while    (!feof(rtfp))
      {
          readonestudent(rtfp,&ast);
          stcount++;
          totalages+=ast.age;
          totalheights+=ast.height;

          printonestudent(ast,prnfp);
      }

      aveage = totalages/stcount;
      aveheight = totalheights/stcount;

      fprintf(prnfp,"Total Of Students is:%d\r\n",stcount);
      fprintf(prnfp,"Average Age Of Students is:%5.1f\r\n",aveage);
      fprintf(prnfp,"Average Height Of Students is:%5.1f\r\n",aveheight);
  }

 综合分析:
      该例程序涉及到文件的格式化输入与输出。在 C 语言中任何数据类型都可以格式化写转换
  为字符类型写入文本文件,同时又可以通过格式化读从文本文件中读出并转化为对应的数据类
  型。因此,文本文件可以用做通用数据存储工具。此例即是该思想的一个具体的应用。

3.2 综合实验二

问题描述:一个学生的信息包括学号、姓名、年龄、身高四项信息,现编写程序模拟实现学生信息
数据库的基本操作。
  基本操作包括以下功能:
  (1) 创建数据库:创建学生库文件并写入数据库标识和记录数量。
  (2) 打开数据库:打开存在的数据库文件。
  (3) 关闭数据库:关闭数据库文件。
  (4) 添加学生记录:向数据库的结尾添加录入的学生信息记录。
  (5) 修改学生记录:用录入的学生信息记录替换指定的学生记录。
  (6) 删除学生记录:删除指定的学生记录。
  (7) 学生信息列表:在屏幕上显示指定记录号范围的学生记录。
  (8) 显示所有学生列表:在屏幕上显示所有学生记录。该程序要求采用简单功能列表菜单选择
  方式作为操作界面。
【编程解析】
  在数据库技术普遍使用之前,对于结构化数据的存储和查询主要通过使用外部文件来实现。本
示例程序是实际应用程序的一个简化了的版本。
  对于学生记录,适宜采用一个结构类型描述,每个记录其大小是一致的。文件的内容除了文件
头以外,存放的全部是学生记录,形成学生信息库。学生记录在文件中顺序存放,其存放位置的序
号称为记录号,对学生信息库施加的操作都是基于指定记录号的。由于文本文件需要在数据读写时
做数据类型转换,速度较慢,所以学生信息库不采用文本格式,采用记录直接存储的二进制格式。
  文件头也是一个记录结构,起到标识和记录学生信息库最新操作情况的作用。其记录内容为:
库文件的标志字符串(同其他用途的文件相区别);有效记录数量。文件中对记录的操作涉及到文件
中的位置定位,可能向前,可能向后,不宜按顺序文件方式处理,应使用随机文件处理方法。
【算法分析】
    本程序处理学生信息,声明为结构,结构名称为 studentinfo。
  创建数据库时,先录入数据库文件全路径名,以读写创建一个文件,成功后写入文件头信息,
文件头信息中记录个数设为 0。

                                            -43-
                  计算机程序设计基础(C 语言)实验教材



  打开数据库时,先录入数据库文件全路径名,以读写打开文件。
  添加记录时,先录入添加的记录,定位结尾记录的下一位置(考虑到文件大小是只增加不减少
的,有可能文件结尾并非所有记录的结尾) ,写入新记录,同时将文件头记载的记录总数增一,写入
文件。
  删除记录时,指定删除的记录号,记录号在有效范围时,将该记录所有后续记录转移到该记录
位置进行覆盖,同时文件头的记录总数减一,写入文件。
  修改记录时,指定修改的记录号,记录号在有效范围时,先输入学生记录,定位到指定的记录,
用输入的记录重新写入(因记录总数无变化,无需处理文件头记录) 。
  列表记录时,先显示记录的范围 1-N,选择察看的区间后,指定的记录分行显示在屏幕上。
  菜单使用显示文字并结合数字选取的方法实现。
【结构分析】
 1.基础函数部分
(1) 将输入一个学生信息的过程抽象为函数 getonestudent,输入参数为学生信息结构的指针,学生
 信息变量在函数中赋值。
(2) 将显示一个学生信息的过程抽象为函数 disponestudent,输入参数为学生信息结构。
(3) 将读取文件头信息抽象为函数 readheader,输入参数为文件头信息结构指针和打开的写二进制
 文件的类型变量。
(4) 将在当前文件指针位置读取一个学生信息记录抽象为函数 readonestudent,输入参数为学生信息
 结构指针和打开的写二进制文件的类型变量。
(5) 将在当前文件指针位置写入一个学生信息记录抽象为函数 writeonestudent,输入参数为学生信
 息结构和打开的写二进制文件的类型变量。
(6) 将写入更新的文件头记录抽象为函数 writeheaderrecord,输入参数为文件头信息结构和打开的写
 二进制文件的类型变量。
(7) 将调整文件指针定位到指定号码学生记录起始位置抽象为函数 seektostudent,输入参数为整数的
 学生信息的记录号和打开的二进制文件变量。
(8) 将加入一个学生信息记录抽象为函数 appendonerecord,输入参数为需要增加的学生信息结构的
 记录和打开的二进制文件变量。
(9) 将删除一个学生信息记录抽象为函数 deleteonerecord,输入参数为需要删除的学生信息记录的
 记录号和打开的二进制文件变量。
(10) 将更新一个学生信息记录抽象为函数 replaceonerecord,输入参数为需要替换的学生信息记录
 的记录号、新的学生信息记录和打开的二进制文件变量。
(11) 将显示指定记录号范围的学生记录信息抽象为函数 dispmanyrecord,输入参数为开始显示的
 记录号、结束显示的记录号、打开的二进制文件变量。
(12) 将显示菜单并得到用户选择抽象为函数 menuselect ,无输入参数,输出参数为选取的字符。
(13) 将创建库文件的操作抽象为函数 builddatafile,输入参数为学生数据文件的文件名字符串,成
 功返回打开读写的数据文件变量指针,失败返回 NULL。
(14) 将打开库文件的操作抽象为函数 opendatafile,输入参数为学生数据文件的文件名字符串,成
 功返回打开读写的数据文件变量指针,失败返回 NULL。
 2.功能函数部分
 (1) 将创建数据库过程抽象为函数 dobuilddatafile,成功返回库文件指针,否则返回 NULL。
 (2) 将打开数据库过程抽象为函数 doopendatafile,成功返回库文件指针,否则返回 NULL。
 (3) 将关闭数据库抽象为函数 doclosedatafile,输入参数为库文件指针。
 (4) 将添加学生记录的过程抽象为函数 doappendrecord,输入参数为库文件指针。
 (5) 将修改学生记录的过程抽象为函数 domodifyrecord,输入参数为库文件指针。
 (6) 将删除学生记录的过程抽象为函数 dodeleterecord,输入参数为库文件指针。

                            -44-
                                 计算机程序设计基础(C 语言)实验教材



 (7) 将显示学生信息列表的过程抽象为函数 dodisplayrecord,输入参数为库文件指针。
 (8) 将显示全部学生信息列表的过程抽象为函数 dodisplayallrecord,输入参数为库文件指针。

  每个子程序算法比较简单,在此不再逐一画出。主控调度算法相对比较复杂,参考综合实验一
画出其算法流程图,其余算法请阅读源程序加以理解。
【参考源程序】
  #include <stdio.h>
  #include <stdlib.h>
  #include <conio.h>
  #include <string.h>

  struct studentinfo{
       char stid[20];
       char name[30];
       int age;
       float height;
  };

  struct headerinfo{
       char datafiletag[40];
       long recordcount;
  };

  void      getonestudent(struct studentinfo *stinfoptr);
  void      disponestudent(struct studentinfo stinfo);
  void      readheader(struct headerinfo *headerptr,FILE *wbfp);
  void      readonestudent(struct studentinfo *stinfoptr,FILE *wbfp);
  void      writeonestudent(struct studentinfo stinfo,FILE *wbfp);
  void      writeheaderrecord(struct headerinfo header,FILE *wbfp);
  int       seektostudent(long recno,FILE *wbfp);
  void      appendonerecord(struct studentinfo stinfo,FILE *wbfp);
  void      deleteonerecord(long recno,FILE *wbfp);
  int       replaceonerecord(long recno,struct studentinfo stinfo,FILE *wbfp);
  void      dispmanyrecord(long srecno,long erecno,FILE *wbfp);
  char       menuselect(void);
  FILE        *builddatafile(char *filepath);
  FILE        *opendatafile(char *filepath);

  FILE        *dobuilddatafile(void);
  FILE        *doopendatafile(void);
  void       doclosedatafile(FILE *wbfp);
  void       doappendrecord(FILE *wbfp);
  void       domodifyrecord(FILE *wbfp);
  void       dodeleterecord(FILE *wbfp);
  void       dodisplayrecord(FILE *wbfp);
  void       dodisplayallrecord(FILE *wbfp);

  void       main()
  {
         FILE *datafp;
         char choosech;

         datafp=NULL;
         choosech=menuselect();

         while (choosech!='0')

                                               -45-
                                   计算机程序设计基础(C 语言)实验教材



       {
            switch (choosech)
            {
                 case    '1':
                 case    '2':
                                   if (datafp!=NULL) fclose(datafp);

                                   if (choosech=='1')
                                        datafp=dobuilddatafile();
                                   else
                                         datafp=doopendatafile();

                                   break;
                 case       '3':
                                   doclosedatafile(datafp);
                                   datafp=NULL;
                                   break;
                 case       '4':
                 case       '5':
                 case       '6':
                 case       '7':
                 case       '8':
                                   if   (datafp==NULL)
                                   {
                                        printf("\r\nData File Not Openning!");

                                        printf("\r\nAny Key To Back...");
                                        getch();

                                        break;
                                   }

                                   switch (choosech)
                                   {
                                        case '4': doappendrecord(datafp); break;
                                        case '5': domodifyrecord(datafp); break;
                                        case '6': dodeleterecord(datafp); break;
                                        case '7': dodisplayrecord(datafp); break;
                                        case '8': dodisplayallrecord(datafp); break;
                                   }
                                   break;
                 default:
                                   printf("Press Key is valid,Continue!");
            }

            choosech=menuselect();
       }
       if   (datafp!=NULL) fclose(datafp);
}

void        getonestudent(struct studentinfo *stinfoptr)
{
       struct studentinfo ast;

       printf("Please Input student at one line[stid name age height]:\r\n");
       scanf("%s %s %d %f%c",ast.stid,ast.name,&(ast.age),&(ast.height));
       *stinfoptr = ast;
}

                                                   -46-
                                 计算机程序设计基础(C 语言)实验教材




void       disponestudent(struct studentinfo stinfo)
{
       printf("%s      %s %d %5.1f",stinfo.stid,stinfo.name,stinfo.age,stinfo.height);
}

void       readheader(struct headerinfo *headerptr,FILE *wbfp)
{
       struct headerinfo header;

       fseek(wbfp,0L,SEEK_SET);
       fread(&header,sizeof(struct headerinfo),1,wbfp);

       *headerptr=header;
}

void       readonestudent(struct studentinfo *stinfoptr,FILE *wbfp)
{
       struct studentinfo ast;

       fread(&ast,sizeof(struct studentinfo),1,wbfp);

       *stinfoptr = ast;
}

void       writeonestudent(struct studentinfo stinfo,FILE *wbfp)
{
       fwrite(&stinfo,sizeof(struct studentinfo),1,wbfp);
}

void       writeheaderrecord(struct headerinfo header,FILE *wbfp)
{
       fseek(wbfp,0L,SEEK_SET);
       fwrite(&header,sizeof(struct headerinfo),1,wbfp);
}

int        seektostudent(long     recno,FILE *wbfp)
{
       long     seekpos;

       seekpos = sizeof(struct headerinfo) + sizeof(struct studentinfo)*(recno-1L);

       fseek(wbfp,seekpos,SEEK_SET);
       return 0;
}

void       appendonerecord(struct studentinfo stinfo,FILE *wbfp)
{
       struct headerinfo header;
       long    reccount;

       fseek(wbfp,0L,SEEK_SET);
       fread(&header,sizeof(struct headerinfo),1,wbfp);

       reccount = header.recordcount;
       reccount++;

       seektostudent(reccount,wbfp);

                                               -47-
                                计算机程序设计基础(C 语言)实验教材



       writeonestudent(stinfo,wbfp);

       header.recordcount++;
       writeheaderrecord(header,wbfp);
}

void        deleteonerecord(long recno,FILE *wbfp)
{
       struct headerinfo header;
       struct studentinfo ast;
       long    i,reccount;

       fseek(wbfp,0L,SEEK_SET);
       fread(&header,sizeof(struct headerinfo),1,wbfp);

       if   (recno<header.recordcount)
             for (i=recno+1;i<=header.recordcount;i++)
             {
                   seektostudent(i,wbfp);
                   readonestudent(&ast,wbfp);

                   seektostudent(i-1,wbfp);
                   writeonestudent(ast,wbfp);
              }

       header.recordcount--;
       writeheaderrecord(header,wbfp);
}

int         replaceonerecord(long recno,struct studentinfo stinfo,FILE *wbfp)
{
       seektostudent(recno,wbfp);
       writeonestudent(stinfo,wbfp);

       return 0;
}

void        dispmanyrecord(long       srecno,long      erecno,FILE *wbfp)
{
       long    i;
       struct studentinfo ast;

       printf("\r\n");

       for (i=srecno;i<=erecno;i++)
       {
             printf("%ld----",i);
             seektostudent(i,wbfp);
             readonestudent(&ast,wbfp);
             disponestudent(ast);
             printf("\r\n");
       }
}

char        menuselect()
{
       char        ach;


                                                -48-
                             计算机程序设计基础(C 语言)实验教材



    clrscr();

    printf("\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n");

    printf("    0 ----------- Quit!\r\n");
    printf("    1 ----------- Create data file of student!\r\n");
    printf("    2 ----------- Open data file of student!\r\n");
    printf("    3 ----------- Close data file!\r\n");
    printf("    4 ----------- Append record!\r\n");
    printf("    5 ----------- Modify record!\r\n");
    printf("    6 ----------- Delete record!\r\n");
    printf("    7 ----------- List records!\r\n");
    printf("    8 ----------- List all record!\r\n");
    printf("    Please Select by number[0..8]:");

    ach = (char)getche();
    return ach;
}

FILE     *builddatafile(char *filepath)
{
    FILE     *wbfp;
    struct headerinfo header;

    wbfp=fopen(filepath,"wb+");
    if (wbfp==NULL) return NULL;

    strcpy(header.datafiletag,"STUDENTDATAFILE");
    header.recordcount=0;

    writeheaderrecord(header,wbfp);

    return wbfp;
}

FILE     *opendatafile(char *filepath)
{
    FILE     *wbfp;
    struct headerinfo header;

    wbfp=fopen(filepath,"rb+");
    if (wbfp==NULL) return NULL;

    return wbfp;
}

FILE     *dobuilddatafile()
{
    char    filepath[200];
    FILE     *wbfp;

    printf("\r\ndata file's path of create file:");
    scanf("%s",filepath);

    wbfp = builddatafile(filepath);

    if (wbfp!=NULL)
        printf(" Ok To Create Data File!");

                                               -49-
                                计算机程序设计基础(C 语言)实验教材



       else
           printf("Error To Create Data File!");

       printf("\r\nAny Key To Back...");
       getch();

       return wbfp;
}

FILE     *doopendatafile()
{
    char    filepath[200];
    FILE     *wbfp;

       printf("\r\ndata file's path of open file:");
       scanf("%s",filepath);

       wbfp = opendatafile(filepath);

       if (wbfp!=NULL)
           printf(" Ok To Open Data File!");
       else
           printf("Error To Open Data File!");

       printf("\r\nAny Key To Back...");
       getch();

       return wbfp;
}

void       doclosedatafile(FILE *wbfp)
{
       if (wbfp!=NULL) fclose(wbfp);

       printf("\r\nData File is Closed!");

       printf("\r\nAny Key To Back...");
       getch();
}

void       doappendrecord(FILE *wbfp)
{
       struct studentinfo ast;

       clrscr();
       getonestudent(&ast);
       appendonerecord(ast,wbfp);

       printf("Ok To Append a Student record!");

       printf("\r\nAny Key To Back...");
       getch();
}

void       domodifyrecord(FILE *wbfp)
{
       long    recno;
       struct studentinfo ast;

                                                 -50-
                              计算机程序设计基础(C 语言)实验教材




       clrscr();
       printf("Input the Record No of student:");
       scanf("%ld",&recno);

       seektostudent(recno,wbfp);
       readonestudent(&ast,wbfp);

       printf("Student Info Is:");
       disponestudent(ast);
       printf("\r\n");

       printf("Replace With Below:\r\n");
       getonestudent(&ast);

       replaceonerecord(recno,ast,wbfp);
       printf("Replace Record Ok!");

       printf("\r\nAny Key To Back...");
       getch();
}

void       dodeleterecord(FILE *wbfp)
{
       long    recno;
       struct studentinfo ast;

       clrscr();
       printf("Input the Record No of student:");
       scanf("%ld",&recno);

       seektostudent(recno,wbfp);
       readonestudent(&ast,wbfp);

       printf("Student Info Deleted Is:");
       disponestudent(ast);

       deleteonerecord(recno,wbfp);

       printf("\r\nAny Key To Back...");
       getch();
}

void       dodisplayrecord(FILE *wbfp)
{
       long    srecno,erecno;
       struct studentinfo ast;
       struct headerinfo header;

       clrscr();

       readheader(&header,wbfp);
       printf("Record range is %ld to %ld\r\n",1L,header.recordcount);

       printf("Input the Start Record No of student:");
       scanf("%ld",&srecno);

       printf("Input the End Record No of student:");

                                              -51-
                               计算机程序设计基础(C 语言)实验教材



         scanf("%ld",&erecno);

         printf("Student Record From %ld To %ld:",srecno,erecno);
         dispmanyrecord(srecno,erecno,wbfp);

         printf("\r\nAny Key To Back...");
         getch();
  }

  void       dodisplayallrecord(FILE *wbfp)
  {
         struct studentinfo ast;
         struct headerinfo header;

         clrscr();

         readheader(&header,wbfp);

         printf("Count of Record:%ld\r\n",header.recordcount);
         if (header.recordcount>0)
         {
               printf("Student Record From %ld To %ld:",1L,header.recordcount);
               dispmanyrecord(1L,header.recordcount,wbfp);
         }

         printf("\r\nAny Key To Back...");
         getch();
 }
 C 语言随机文件处理方式为我们构造各种特殊格式的结构化的数据文件提供了强有力的支持,
在开发程序时,应该分析和定义自己的数据结构并在文件中设计数据结构存储格式,从而可以支持
任何复杂的存储使用的要求。




                                              -52-
                     计算机程序设计基础(C 语言)实验教材



         附录一 二级 C 语言程序设计考试大纲(2005 年)

  I. 公共基础知识
  基本要求

   掌握算法的基本概念。
   掌握基本数据结构及其操作。
   掌握基本排序和查找算法。
   掌握逐步求精的结构化程序设计方法。
   掌握软件工程的基本方法,具有初步应用相关技术进行软件开发的能力。
   掌握数据的基本知识,了解关系数据库的设计。
  考试内容
 一、 基本数据结构与算法

   算法的基本概念;算法复杂度的概念和意义(时间复杂度与空间复杂度)。
   数据结构的定义;数据的逻辑结构与存储结构;数据结构的图形表示;线性结构与非线性结
构的概念。
   线性表的定义;线性表的顺序存储结构及其插入与删除运算。
   栈和队列的定义;栈和队列的顺序存储结构及其基本运算。
   线性单链表、双向链表与循环链表的结构及其基本运算。
   树的基本概念;二叉树的定义及其存储结构;二叉树的前序、中序和后序遍历。
   顺序查找与二分法查找算法;基本排序算法(交换类排序,选择类排序,插入类排序)。
 二、 程序设计基础

   程序设计方法与风格。
   结构化程序设计。
   面向对象的程序设计方法,对象,方法,属性及继承与多态性。
 三、 软件工程基础

   软件工程基本概念,软件生命周戎概念,软件工具与软件开发环境。
   结构化分析方法,数据流图,数据字典,软件需求规格说明书。
   结构化设计方法,总体设计与详细设计。
   软件测试的方法,白盒测试与黑盒测试,测试用例设计,软件测试的实施,单元测试、集成
测试和系统测试。
   程序的调试,静态调试与动态调试。
 四、 数据库设计基础

   数据库的基本概念:数据库,数据库管理系统,数据库系统。
   数据模型,实体联系模型及 E-R 图,从 E-R 图导出关系数据模型。
   关系代数运算,包括集合运算及选择、投影、连接运算,数据库规范化理论。
   数据库设计方法和步骤:需求分析、概念设计、逻辑设计和物理设计的相关策略。
 考试方式

  、 公共基础的考试方式为笔试,与 C 语言(VisualBASIC、Visual FoxPro、Java、Access、Visual
C++)的笔试部分合为一张试卷。公共基础部分占全卷的 30 分。
  、 公共基础知识有 10 道选择题和 5 道填空题。

                                -53-
                        计算机程序设计基础(C 语言)实验教材



II.   C 语言程序设计
      基本要求

      熟悉 TURBO C 集成环境。
      熟练掌握结构化程序设计的方法,具有良好的程序设计风格。
      掌握程序设计中简单的数据结构和算法。
              的集成环境下,能够编写简单的 C 程序,并具有基本的纠错和调试程序的能力。
      考试内容
      一、C 语言的结构

      程序的构成,MAIN 函数和其他函数。
      头文件,数据说明,函数的开始和结束标志。
      源程序的书写格式
       语言的风格。
      二、数据类型及其运算

       的数据类型(基本类型,构造类型,指针类型,空类型)及其定义方法。
       运算符的种类、运算优先级和结合性。
      不同类型数据间的转换与运算。
       表达式类型(赋值表达式、算术表达式、关系表达式、逻辑表达式、条件表达式、逗号表达
式)和求值规则。
      三、基本语句

      表达式语句,空语句,复合语句。
      数据的输入和输出,输入输出函数的调用。
      复合语句。
          语句和语句标号的使用。
      四、选择结构程序设计

      用 if 语句实现选择结构。
      用 switch 语句实现多分支选择结构。
      选择结构的嵌套。
      五、循环结构程序设计

        循环结构。
         和 do while 循环结构。
             语句和 break 语句。
      循环的嵌套。
      六、数组的定义和引用

      .一维数组和多维数组的定义、初始化和引用。
      字符串与字符数组。
      七、函数

      库函数的正确调用。
      函数的定义方法。
      函数的类型和返回值。
                                -54-
                         计算机程序设计基础(C 语言)实验教材



  形式参数与实在参数,参数值的传递。
  函数的正确调用,嵌套调用,递归调用。
  局部变量和全局变量。
  变量的存储类别(自动、静态、寄存器、外部),变量的作用域和生存期。
  内部函数与外部函数。
 八、编译预处理

  宏定义:不带参数的宏定义;带参数的宏定义。
  文件包含”处理。
 九、指针

  指针与指针变量的概念,指针与地址运算符。
  变量、数组、字符串、函数、结构体的指针以及指向变量、数组、字符串、函数、结构体的指
针变量。通过指针引用以上各类型数据。
  用指针作函数参数。
  返回指针值的指针函数。
  指针数组,指向指针的指针,MAIN 函数的命令行参数。
 十、结构体(即“结构”)与共用体(即“联合”)

  结构体和共用体类型数据的定义方法和引用方法。
  用指针和结构体构成链表,单向链表的建立、输出、删除与插入。
 十一、位运算

  位运算符的含义及使用。
  简单的位运算。
 十二、文件操作

 只要求缓冲文件系统(即高级磁盘 I/O 系统),对非标准缓冲文件系统(低级磁盘 I/O 系统)不要求。
  文件类型指针(FILE 类型指针)。
  文件的打开与关闭(fopen,fclose)。
  文件的读写(fputc,fgetc,fputs,fgets,fread,frwite,fprintf,fscanf 函数),文件的定位(rewind,fseek 函数)。
 考试方式

  笔试:120 分钟,满分 100 分,其中含公共基础知识部分的 30 分。
  上机:60 分钟,满分 100 分。




                    附录二 Turbo C 编译出错信息解析
                                        -55-
                  计算机程序设计基础(C 语言)实验教材



  说明:Turbo C 的源程序错误分为三种类型:致命错误、一般错误和警告。其中,致命错误通
常是内部编译出错;一般错误指程序的语法错误、磁盘或内存存取错误或命令行错误等;警告则只
是指出一些得怀疑的情况,它并不防止编译的进行。
  下面按字母顺序 A~Z 分别列出致命错误及一般错误信息,英汉对照及处理方法:

1. 致命错误英汉对照及处理方法
Bad call of in-line function (内部函数非法调用)
分析与处理:在使用一个宏定义的内部函数时,没能正确调用。一个内部函数以两个下划线(__)开始
和结束。
Irreducable expression tree (不可约表达式树)
分析与处理:这种错误指的是文件行中的表达式太复杂,使得代码生成程序无法为它生成代码。这
种表达式必须避免使用。
Register allocation failure (存储器分配失败)
分析与处理:这种错误指的是文件行中的表达式太复杂,代码生成程序无法为它生成代码。此时应
简化这种繁杂的表达式或干脆避免使用它。

2. 一般错误信息英汉照及处理方法
#operator not followed by maco argument name(#运算符后没跟宏变元名)
分析与处理:在宏定义中,#用于标识一宏变串。“#”号后必须跟一个宏变元名。
'xxxxxx' not anargument ('xxxxxx'不是函数参数)
分析与处理:在源程序中将该标识符定义为一个函数参数,但此标识符没有在函数中出现。
Ambiguous symbol 'xxxxxx' (二义性符号'xxxxxx')
分析与处理:两个或多个结构的某一域名相同,但具有的偏移、类型不同。在变量或表达式中引用
该域而未带结构名时,会产生二义性,此时需修改某个域名或在引用时加上结构名。
Argument # missing name (参数#名丢失)
分析与处理:参数名已脱离用于定义函数的函数原型。如果函数以原型定义,该函数必须包含所有
的参数名。 Argument list syntax error (参数表出现语法错误)
分析与处理:函数调用的参数间必须以逗号隔开,并以一个右括号结束。若源文件中含有一个其后
不是逗号也不是右括号的参数,则出错。
Array bounds missing (数组的界限符"]"丢失)
分析与处理:在源文件中定义了一个数组,但此数组没有以下右方括号结束。
Array size too large (数组太大)
分析与处理:定义的数组太大,超过了可用内存空间。
Assembler statement too long (汇编语句太长)
分析与处理:内部汇编语句最长不能超过 480 字节。
Bad configuration file (配置文件不正确)
分析与处理:TURBOC.CFG 配置文件中包含的不是合适命令行选择项的非注解文字。配置文件命令
选择项必须以一个短横线开始。
Bad file name format in include directive(包含指令中文件名格式不正确)
分析与处理:包含文件名必须用引号("filename.h")或尖括号(<filename>)括起来,否则将产生本类错
误。如果使用了宏,则产生的扩展文本也不正确,因为无引号没办法识别。
Bad ifdef directive syntax (ifdef 指令语法错误)
分析与处理:#ifdef 必须以单个标识符(只此一个)作为该指令的体。
Bad ifndef directive syntax (ifndef 指令语法错误)
分析与处理:#ifndef 必须以单个标识符(只此一个)作为该指令的体。
Bad undef directive syntax (undef 指令语法错误)
分析与处理:#undef 指令必须以单个标识符(只此一个)作为该指令的体。
Bad file size syntax (位字段长语法错误)
分析与处理:一个位字段长必须是 1—16 位的常量表达式。
Call of non-functin (调用未定义函数)
分析与处理:正被调用的函数无定义,通常是由于不正确的函数声明或函数名拼错而造成。

                            -56-
                           计算机程序设计基础(C 语言)实验教材



Cannot modify a const object (不能修改一个长量对象)
分析与处理:对定义为常量的对象进行不合法操作(如常量赋值)引起本错误。
Case outside of switch (Case 出现在 switch 外)
分析与处理:        编译程序发现 Case 语句出现在 switch 语句之外,           这类故障通常由于括号不匹配造成的。
Case statement missing (Case 语句漏掉)
分析与处理:Case 语必须包含一个以冒号结束的常量表达式,如果漏了冒号或在冒号前多了其它符
号,则会出现此类错误。
Character constant too long (字符常量太长)
分析与处理:字符常量的长度通常只能是一个或两个字符长,超过此长度则会出现这种错误。
Compound statement missing (漏掉复合语句)
分析与处理:编译程序扫描到源文件未时,未发现结束符号 (大括号),此类故障通常是由于大括号
不匹配所致。
Conflicting type modifiers (类型修饰符冲突)
分析与处理:对同一指针,只能指定一种变址修饰符(如 near 或 far);而对于同一函数,也只能给出
一种语言修饰符(如 Cdecl、pascal 或 interrupt)。
Constant expression required (需要常量表达式)
分析与处理:数组的大小必须是常量,本错误通常是由于#define 常量的拼写错误引起。
Could not find file 'xxxxxx.xxx' (找不到'xxxxxx.xx'文件)
分析与处理:编译程序找不到命令行上给出的文件。
Declaration missing (漏掉了说明)
分析与处理:        当源文件中包含了一个 struct 或 union 域声明,          而后面漏掉了分号,    则会出现此类错误。
Declaration needs type or storage class(说明必须给出类型或存储类)
分析与处理:正确的变量说明必须指出变量类型,否则会出现此类错误。
Declaration syntax error (说明出现语法错误)
分析与处理:在源文件中,若某个说明丢失了某些符号或输入多余的符号,则会出现此类错误。
Default outside of switch (Default 语句在 switch 语句外出现)
分析与处理:这类错误通常是由于括号不匹配引起的。
Define directive needs an identifier (Define 指令必须有一个标识符)
分析与处理:#define 后面的第一个非空格符必须是一个标识符,若该位置出现其它字符,则会引起
此类错误。
Division by zero (除数为零)
分析与处理:当源文件的常量表达式出现除数为零的情况,则会造成此类错误。
Do statement must have while (do 语句中必须有 While 关键字)
分析与处理:若源文件中包含了一个无 While 关键字的 do 语句,则出现本错误。
DO while statement missing ( (Do while 语句中漏掉了符号 "(")
              在
分析与处理: do 语句中, while 关键字后无左括号,若                     则出现本错误。 Do while statement missing;
(Do while 语句中掉了分号)
分析与处理:在 DO 语句的条件表达式中,若右括号后面无分号则出现此类错误。
Duplicate Case (Case 情况不唯一)
分析与处理:Switch 语句的每个 case 必须有一个唯一的常量表达式值。否则导致此类错误发生。
Enum syntax error (Enum 语法错误)
分析与处理:若 enum 说明的标识符表格式不对,将会引起此类错误发生。
Enumeration constant syntax error (枚举常量语法错误)
分析与处理:若赋给 enum 类型变量的表达式值不为常量,则会导致此类错误发生。
Error Directive : xxxx (Error 指令:xxxx)
分析与处理:源文件处理#error 指令时,显示该指令指出的信息。
Error Writing output file (写输出文件错误)
分析与处理:这类错误通常是由于磁盘空间已满,无法进行写入操作而造成。
Expression syntax error (表达式语法错误)
分析与处理:本错误通常是由于出现两个连续的操作符,括号不匹配或缺少括号、前一语句漏掉了
分号引起的。

                                         -57-
                    计算机程序设计基础(C 语言)实验教材



Extra parameter in call (调用时出现多余参数)
分析与处理:本错误是由于调用函数时,其实际参数个数多于函数定义中的参数个数所致。
Extra parameter in call to xxxxxx(调用 xxxxxxxx 函数时出现了多余参数)
File name too long (文件名太长)
分析与处理:#include 指令给出的文件名太长,致使编译程序无法处理,则会出现此类错误。通常
DOS 下的文件名长度不能超过 64 个字符。
For statement missing ) (For 语名缺少")")
分析与处理:在 for 语句中,如果控制表达式后缺少右括号,则会出现此类错误。
For statement missing( (For 语句缺少"(")
For statement missing; (For 语句缺少";")
分析与处理:在 for 语句中,当某个表达式后缺少分号,则会出现此类错误。
Function call missing) (函数调用缺少")")
分析与处理:如果函数调用的参数表漏掉了右手括号或括号不匹配,则会出现此类错误。
Function definition out ofplace (函数定义位置错误)
Function doesn't take a variable number of argument(函数不接受可变的参数个数)
Goto statement missing label (Goto 语句缺少标号)
If statement missing( (If 语句缺少"(")
If statement missing) (If 语句缺少")")
lllegal initalization (非法初始化)
lllegal octal digit (非法八进制数)
分析与处理:此类错误通常是由于八进制常数中包含了非八进制数字所致。
lllegal pointer subtraction (非法指针相减)
lllegal structure operation (非法结构操作)
lllegal use of floating point (浮点运算非法)
lllegal use of pointer (指针使用非法)
Improper use of a typedef symbol (typedef 符号使用不当)
Incompatible storage class (不相容的存储类型)
Incompatible type conversion (不相容的类型转换)
Incorrect commadn line argument:xxxxxx (不正确的命令行参数:xxxxxxx)
Incorrect commadn file argument:xxxxxx (不正确的配置文件参数:xxxxxxx)
Incorrect number format (不正确的数据格式)
Incorrect use of default (deflult 不正确使用)
Initializer syntax error (初始化语法错误)
Invaild indrection (无效的间接运算)
Invalid macro argument separator (无效的宏参数分隔符)
Invalid pointer addition (无效的指针相加)
Invalid use of dot (点使用错)
Macro argument syntax error (宏参数语法错误)
Macro expansion too long (宏扩展太长)
Mismatch number of parameters in definition(定义中参数个数不匹配)
Misplaced break (break 位置错误)
Misplaced continue (位置错)
Misplaced decimal point (十进制小数点位置错)
Misplaced else (else 位置错)
Misplaced else driective (clse 指令位置错)
Misplaced endif directive (endif 指令位置错)
Must be addressable (必须是可编址的)
Must take address of memory location (必须是内存一地址)
No file name ending (无文件终止符)
No file names given (未给出文件名)
Non-protable pointer assignment (对不可移植的指针赋值)

                               -58-
                            计算机程序设计基础(C 语言)实验教材



Non-protable pointer comparison (不可移植的指针比较)
Non-protable return type conversion (不可移植的返回类型转换)
Not an allowed type (不允许的类型)
Out of memory (内存不够)
Pointer required on left side of (操作符左边须是一指针)
Redeclaration of 'xxxxxx' ('xxxxxx'重定义)
Size of structure or array not known (结构或数组大小不定)
Statement missing; (语句缺少“;”)
Structure or union syntax error (结构或联合语法错误)
Structure size too large (结构太大)
Subscription missing ] (下标缺少‘]’)
Switch statement missing ( (switch 语句缺少"(")
Switch statement missing ) (switch 语句缺少")")
Too few parameters in call (函数调用参数太少)
Too few parameter in call to'xxxxxx'(调用'xxxxxx'时参数太少)
Too many cases (Cases 太多)
Too many decimal points (十进制小数点太多)
Too many default cases (defaut 太多)
Too many exponents (阶码太多)
Too many initializers (初始化太多)
Too many storage classes in declaration (说明中存储类太多)
Too many types in decleration (说明中类型太多)
Too much auto memory in function (函数中自动存储太多)
Too much global define in file (文件中定义的全局数据太多)
Two consecutive dots (两个连续点)
Type mismatch in parameter # (参数"#"类型不匹配)
Type mismatch in parameter # in call to 'XXXXXXX' (调用'XXXXXXX'时参数#类型不匹配)
Type missmatch in parameter 'XXXXXXX' (参数'XXXXXXX'类型不匹配)
Type mismatch in parameter 'YYYYYYYY' in call to 'YYYYYYYY'( 调 用 'YYYYYYY' 时 参 数
'XXXXXXXX'数型不匹配)
Type mismatch in redeclaration of 'XXX' (重定义类型不匹配)
Unable to creat output file 'XXXXXXXX.XXX' (不能创建输出文件'XXXXXXXX.XXX')
Unable to create turboc.lnk (不能创建 turboc.lnk )
Unable to execute command 'xxxxxxxx'(不能执行'xxxxxxxx'命令)
Unable to open include file 'xxxxxxx.xxx' (不能打开包含文件'xxxxxxxx.xxx')
Unable to open inputfile 'xxxxxxx.xxx' (不能打开输入文件'xxxxxxxx.xxx')
Undefined label 'xxxxxxx' (标号'xxxxxxx'未定义)
Undefined structure 'xxxxxxxxx' (结构'xxxxxxxxxx'未定义)
Undefined symbol 'xxxxxxx' (符号'xxxxxxxx'未定义)
Unexpected end of file in comment started on line #(源文件在某个注释中意外结束)
Unexpected end of file in conditional stated on line # (源文件在#行开始的条件语句中意外结束)
Unknown preprocessor directive 'xxx' (不认识的预处理指令:'xxx')Untermimated character constant (未
终结的字符常量)
Unterminated string (未终结的串)
Unterminated string or character constant(未终结的串或字符常量)
User break (用户中断)             Value required (赋值请求)
While statement missing ( (While 语句漏掉 '(')
While statement missing ) (While 语句漏掉 ')')
Wrong number of arguments in of 'xxxxxxxx' (调用'xxxxxxxx'时参数个数错误)

              附录三 C 语言的学习方法、注意事项与实验要求
                                          -59-
                   计算机程序设计基础(C 语言)实验教材



【学习与考试要领】

  首先要明确学习的目标,没有明确的学习目标就没有学习动力。给自己定一个目标,比如这次
一定通过计算机等级考试,或者这个月学完后做个东西出来等等。其次,确定了目标之后,要认真
去做,多上机操作实践,遇到不懂的要多跟教师和同学们交流,千万不能放弃。当自己编写的一段
小程序运行通过,或攻下一道难题,自己就会获得一种成就感,可能还会很兴奋,渐渐地培养兴趣。
最后,要把所学的知识运用到实际问题当中,这样既可以巩固所学的知识,不至于学完了就忘,还
可以根据实际需要拓展知识面。这样良性循环,兴趣也会越来越浓。
  那么,到底怎样学习 C 语言呢?
  很多人对学习 C 语言感到无从下手,经常会问老师同一个问题:究竟怎样学习 C 语言?作为教
师,虽然现在已经开发了多年的程序,但和很多刚刚起步的人一样,学习的第一门计算机语言就是
C 语言。经过这些年的开发,深深的体会到 C 语言对于一个程序设计人员多么重要,如果不懂 C 语
言,你想写底层程序听起来就很可笑,不懂 C 语言,当你想写出优秀高效的程序,简直就是天方夜
谈。为什么 C 语言如此重要呢?
  首先是 C 语言的语法结构很简洁精妙,写出的程序也很高效,很便于描述算法,大多数的程序
员愿意使用 C 语言去描述算法本身,所以,如果你想在程序设计方面有所建树,就必须去学它。
  其次是 C 语言能够让你深入系统底层,你知道的操作系统,哪一个不是 C 语言写的?所有的
Windows,Unix,Linux,Mac,OS/2,没有一个例外的,如果你不懂 C 语言,怎么可能深入到这些操作系
统当中去呢?更不要说你去写它们的内核程序了。
  第三是很多新型的语言都是衍生自 C 语言,C++,Java,C#,J#,perl...哪个不是呢?掌握了 C 语言,
可以说你就掌握了很多门语言,经过简单学习,就可以用这些新型的语言去开发了,这再一次验证
了 C 语言是程序设计的重要基础。从现实角度看,现在招聘程序员,考试都是考 C 语言,你想加入
IT 行业,那么就一定要掌握好 C 语言。
  建议大家在刚开始学习 C 语言时要借阅谭浩强主编的第二版《C 语言程序设计》(清华大学出
版社),此书很适合初学者入门学习。本书的电子版请到图书馆的“数据库→自建数据库→自建电子
书数据库”里去阅读或下载。但要学好学会 C 语言,通过 C 二级考试,还是选择其它深度稍大和内
容丰富的教材为佳。
                                   ,里边的知识点总结和例
   以外,现在有很多辅助学习软件,推荐一个“集成学习环境(C 语言)”
程讲解都非常好,还有题库测试环境,据说有好几千题,甚至还有一个 Windows 下的 Turbo C,初
学者甚至不用装其它的编译器,就可以练习编程了,非常适合初学者。还有一个“C 语言学习系统”
软件,不过感觉只是一个题库系统,如果你觉得题做的不够,不妨也可以试试。
  学习计算机语言最好的方法是什么?答曰:读程序。
  没错,读程序是学习 C 语言入门最快,也是最好的方法。学习新的 J#,C#等其他语言,一般不
用再抱着书本逐行啃,而是学习它们的例程。但对于没有学过任何计算机语言的初学者,最好还是
先阅读教程,学习完每一章,都要认真体会这一章的所有概念,然后不放过这一章中提到的所有例
程,然后仔细研读程序,直到每一行都理解了,然后找几个编程题目,最好是和例程类似的或一样
的,自己试图写出这段已经读懂的程序,不要以为例程你已经读懂了,你就可以写出和它一样的程
序,绝对不是这样,你就试一试吧,如果写不出来,也不要着急,回过头来再继续研究例程,想想
自己为什么写不出来,然后再去写这段程序,反反复复,直到你手到擒来为止,早日入门。
  写程序的最高境界其实就是掌握各种解决问题的手段(数据结构)和解决问题的方法(算法)。
  是不是写出底层程序就是程序设计高手呢?不一定。写底层程序,无非是掌握了硬件的结构,
况且硬件和硬件还不一样,要给一个芯片写驱动程序,无非就是掌握这块芯片的各种寄存器及其组
合,然后写值读值,仅此而已。这不过是熟悉一些 IO 函数而已。
  那么怎样才算精通程序设计呢?怎样才能精通程序设计呢?举个例子:你面前有 10 个人,找出


                            -60-
                计算机程序设计基础(C 语言)实验教材



一个叫“张三”的人,你该怎么办?第一种方法:直接对这 10 个人问:“谁叫张三”。第 2 种方法:你
挨个去问“你是不是张三?”,直到问到的这个人就是张三。第三种方法:你去挨个问一个人“你认不
认识张三,指给我看”。不要小看这个问题,你说当然会选第一种方法,没错恭喜你答对了,因为这
个方法最快,效率最高,但是在程序设计中找到解决问题的最优方法和你用的手段却是考验一个程
序员程序设计水平的重要标志,而且是不容易达到的。刚才这个问题类似于数据结构和算法中的数
据结构,穷举查找和折半查找。所以掌握好数据结构和一些常用算法,是登峰造极的必然之路。
  考试作为检验学习成果的重要手段,那么怎样复习迎接考试呢?

  下面介绍 C 语言复习迎考的五个要点。
1.了解试卷,胸中有数
  综观近几年全国计算机等级二级基础部分和 C 语言程序设计的题目,笔试中大多数考题是与大
纲要求的基本内容一致的,难度不高,但内容十分广泛,应牢固掌握。所以,全面复习非常重要。
2. 深刻理解,强化概念
  对于计算机的基础知识和体系,应注意理解,切忌死记硬背。例如,可以把计算机硬件系统的
结构图与实物对照着去理解:控制器和运算器常常集成在一起,称为 CPU;存储器分为两种:内存
和外存,只有内存才能与 CPU 直接打交道;所有这些部件又由总线将其联结为一体,这种计算机又
称为总线式计算机;又如,计算机之所以称为电脑,就是因为计算机的硬件结构、处理问题的方式
和人的大脑结构以及处理问题的方式基本一致。采用对照、总结、联想的方法来复习这些内容,比
死记硬背效果要好得多。
3. 归纳整理,适当记忆
  另一部分需要记忆的知识是计算机基础知识、基本概念。这些内容看似不起眼,但如果不适当
加以记忆,考试时因此失分十分可惜。如:1946 年至今,计算机发展已经历了四个时代,这四个时
代是如何划分的?一个计算机系统都由哪几部分组成?各部分关系怎样?我们可以在理解的基础上
归纳整理,适当记忆。需要适当记忆的内容对初学者来说还有许多,如在 C 语言中有几类不同类型
的数据,各类数据在机器内部是如何存储的?C 语言中的运算符都有哪些?运算的优先级别、结合
方向怎样等。
4. 注重实践,融会贯通
  一门理论性、实践性都很强的学科,对二级考试的参加者来说,基础理论方面要求不是特别深
入,卷面中的题目大多数都可以上机实践。因此,注重实践,更显得重要。考生应在对基本知识理
解的同时注意多上机实践,通过实践,将所学知识融会贯通。
5. 多做练习,查漏补缺
  学完考试指定用书后,你可能已雄心勃勃,充满信心。但千万别高兴过早。再找一些题集,认
真地测试一下,一则可以看看你究竟学习得如何,二则可以查漏补缺,将还没有掌握的内容补上,
以备正式考试时万无一失。即使在平时,也应这样。多做练习,多加思考,在解题中下功夫,是学
好计算机的关键。我国著名数学家华罗庚说过:“学数学不做练习,好比入宝山而空返。”学习计算
机也是同样的道理。
【实验课程开设的目的】

  1.理解讲授内容,尤其是一些语法规则,光靠课堂讲授,既枯燥无味又难以记住,但它们都很
重要。通过多次上机,就能自然地、熟练地掌握。通过上机来掌握语法规则是行之有效的方法。
  2.熟练所用的计算机系统的操作方法,了解和熟悉 C 语言程序开发的环境(硬件和软件环境)。
  3.学会上机调试程序,善于发现程序中错误,并能很快地排除这些错误,使程序能正确运行。
【实验要求】


                        -61-
                  计算机程序设计基础(C 语言)实验教材



                   、上机调试运行和实验后的总结三个步骤。
  上机实验一般经历上机前的准备(编程)
  1.上机前的准备
  根据问题,进行分析,选择适当算法并编写程序,初学者可以参考别人的程序,但一定要读懂,
理解,掌握设计思路,变成自己的。上机前一定要仔细检查程序(称为静态检查)直到找不到错误
          。分析可能遇到的问题及解决的对策。准备几组测试程序的数据和预期的正
(包括语法和逻辑错误)
确结果,以便发现程序中可能存在的错误。
                            、源程序和调试步骤等。
  要求写预习报告,包括实验目的、内容、算法设计(流程图)
  上机前没有充分准备,到上机时临时拼凑一个错误百出的程序,宝贵的上机时间就白白浪费了。
或者照抄别人的程序,而自己又不理解,一运行通过,结果正确,就万事大吉,到头来一无所获。
  2.上机输入和编辑程序,并调试运行程序
  首先调用 C 语言集成开发环境,输入并编辑事先准备好的源程序;然后调用编译程序对源程序
进行编译,查错,改正后再编译,直到通过编译。下一步是调用连接程序,产生可执行程序(扩展
      。使用预先准备的测试数据运行程序,观察是否得到预期的正确结果。若有问题,则仔细
名为 EXE)
调试,排除错误,得到正确结果,注意记录。在调试过程中,要充分利用 C 语言集成环境提供的调
试手段和工具,如单步跟踪、设置断点、监视变量值的变化等。整个过程应自己独立完成。不要一
点小问题就找老师,学会独立思考,勤于分析,通过自己实践得到的经验用起来更加得心应手。
  3.整理上机实验结果,写出实验报告
  实验结束要及时整理实验结果并认真分析和总结,在预习报告基础上给出正确源程序,添上实
验调试记录,加上分析与思考形成完整的实验报告。

【注意事项】
  1. 作好预习,无完整的预习报告者不准上机做实验。
  2. 程序调试过程中应仔细记录出现的问题和解决方法,加深程序调试和改错的技能,实验完
      成后,需经指导教师检查签字方有成绩。
  3. 实验后,按时提交实验报告和实验程序源代码,一般在下次上课前提交。

【实验报告的内容基本要求】
                    实验*      ***** ***** *****
         姓名 ****** 班级   ******    学号 *******     科目 *********
一、实验目的
二、实验内容:实验题目与要求。
三、算法说明:NS 图或流程图
四、源程序清单与改错的标记(含出错信息和修改结果)
五、调试记录:原始数据、相应的运行结果和必要的说明
六、分析与思考:调试过程及调试中遇到的问题及解决办法;若最终未完成调试,要分析原因;调
  试程序的心得与体会;其他算法的存在与实践;对课程及实验的建议等。
备注:
                      、         ,实验报告一律使用 B5 大小的
  作业本一律使用 22 开的“单线练习本”“练习本”或“笔记本”
      ,并首先写上“姓名、班级、学号、科目和日期或星期几”
“实验报告纸”                         。




                                 -62-

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:14
posted:5/28/2012
language:
pages:64