zoukankan      html  css  js  c++  java
  • 第一章 C 程序的框架结构

      计算机系统是由硬件系统和软件系统构成,硬件由IBM、HP、DLL、Acer以及联想这样的工厂制造出来,叫裸机。软件由微软、Oracle以及用友等公司的程序员用计算机语言编写出来的,叫程序。程序和编写该程序的文档一起构成了软件系统。裸机安装上了操作系统就构成了第一层虚拟机,计算机软硬件资源由操作系统来管理。在操作系统之上安装应用软件,就构成第二层虚拟机,用户一般与这层计算机打交道的。应用软件提供一个输入数据的界面,用户通过这个界面将要加工的原始数据(文字、数值 、声音、图片、图形、动画、电影等)输入给这个软件,然后它的加工部分对数据进行交换,最后将计算结果输出给用户。

      软件是被记录下来的思维的逻辑推理过程,是计算机硬件的“学历”,是计算机系统的灵魂。没有安装软件的裸机就像是一台接收不到电视信号的电视一样,其“本事”不能被挖掘出来。因此,硬件的价值与安装到其上的软件功能成正比,人们借助软件间接地让硬件“劳动”。

      计算机硬件的制造现在可以实现批量生产了,但软件的开发还需要人来写,目前还不能现让计算机来编写软件。用来写软件的计算机语言多达2000种,C语言能在众多计算机语言中脱颖而出,靠的就是既能写系统软软件又能写应用软件的特长。系统软件一般直接与硬件打交道,编写难度大。应用软件是用来解决特定领域的数据加工问题的。现在通常的做法是用C开发一个系统软件,然后用这个系统软件开发应用软件例如用C开发出的VFP 系统,用户使用VFP 系统开发其领域的应用软件,如考场安排系统,成绩管理系统以及售票系统等。

    1.1 用C 写程序的思想框架

     

        下面给出第一个C程序,命名为c1.c, C源程序的扩名为c。

      main ()   // main函数的功能是调用其他函数,给其传递数据,并接收传来的数据。

      {void drawsomething (char, int);   // 对该函数进行声明

      drawsomething (' ', 2); 

      drawsomething('#', 1); printf (" ");   //括号内参数是实参

      drawsomething(' ', 1); 

      drawspmething('#', 3); printf (" ")  //实参之间用逗号分隔

      drawsomething(' ', 0); 

      drawsomething ('#', 5); printf(" ");   //字符常量用单括撇括起

     }  // 分号是语句的标志,少了它就变成了表达式了。

      /*下面函数的功能是输出n个由参数c 指定的字符*/

      viod drawsomething(char c, int n)  // c 和 n 是形式参数,简称为形参,char 即 character.

      { int i;   // 定义变量i 是integer 型, C规定变量必须先定义,后使用。

      for (i=0; i<n; i++) printf ("c%", c)  //循环n次,每次输出一个字符。

    }  // for 循环中的分号是分隔符。第三章会讲到,同一符号在不同上下文中含义迥然。

      由/*&*/ 括起来的部分是C和C++的多行注释语句,// 是C++的注释语句。本书所有程序都是在Turbo C++3.0 IDE (Integrated Development Evironment)下调试和编译。注释语句也叫内部文档,一般分两种:一种是放在源码的最前面,对该程序进行整体注释,介绍其功能,I/O接口中参数的含义、权限要求、算法的简单描述,调用了哪些函数、编者、创建日期、修改日期以及审核日期;另一种是行间注释,对可能引起歧义的语句进行说明。

      该程序由main和drawingsomething 两个函数构成,每个函数完成一个特定的功能。 一个程序有且只有一个main 函数,mian函数是程序的入口函数,其位置任意。程序总是从main函数开始执行, main 函数执行完了,整个程序也就执行完了。所以,在拿到一个要进行数据变换的问题后,首先要做的就是将要解决的问题分解为若干功能单一的函数,以使每个函数都有“一技之长”。接下来main函数按照输入数据、变换数据、输出数据的顺序调用相应的函数,由其完成具体的任务。当然函数之间可以相互调用,但不能调用main函数。这就是用C解决数据加工问题的思维框架。

      通过上面的示例可以看出,一个函数由函数首部和用花括号括起来的函数体两部分组成。

      函数首部由函数返回值类型、函数名(类型  形参、类型  形参,...)构成。 上面的main函数没有形参,叫无参函数,没有返回值类型,默认为int 型,没有返回值语句,则执行完该函数后系统返回一个随机数。 drawsomething 函数的返回值类型是viod, 说明不能有返回值。 形参是定义函数时的形式参数,必须是变量,实参是调用函数时的实际参数,必须有明确的值。 调用时,按从右到左(TC++是这样的,但Fortran等语言按从左向右的顺序)的顺序将实参的值赋给形参,所以要求实参和形参的类型、个数、顺序要对称,否则是编译不通过,或者是计算结果不正确。现在让我们故意犯个错误,将main函数第3行的,2去掉,编译后给出“too few parameters in call to 'drawsomething' in function main”的提示,将实参2改为2.9 ,运行结果不变,因为形参n是整数,它只要整数的部分。

      函数内要先写局部变量定义,被调函数声明、判断、循环、赋值、 return等语句。函数体也可以是空语句,即只有一个函数首部后跟一对花括号,叫空函数。根据C的思维框架结构,我们在处理一个大的任务时,首先要做的是将大任务分解为小任务,如此分解下去,直到每个小任务只有一个功能,我们暂时就用这个空函数代表这个小任务,待分解合理了,任务之间的关系理顺了,再把空函数为真正的函数,然后上机调试、编译为EXE文件,就可以作为软件使用了。如,求两个正整数的最大公约数和最小公倍数,可以分解为如下三个函数:

      int max(int, int){}  // max 函数负责求最大公约数,返回值类型是int型。

      min (int, int) {}  // min 函数负责最小公倍数,省略了返回值类型。

      void main () {}  //负责接收待求数,调用max和min,接收其返回值,最后输出结果。

      下面细化后的三个函数:

      int  max (int  bcs, int  cs)  // bcs是被除数的拼音字母缩写,cs代表除数。

      { int yushu;   // yushu代表余数,zdgys 代表最大公约数,zxgbs代表最小公倍数。

      while(cs != 0)  // while 循环结构,读作当条件为真时,执行循环体,然后返回到

        {yushu=bcs/cs;  //条件处继续判断,当条件仍为真时,继续执行循环体,如此循环,

        cs=yushu;  //当条件为假时,跳出循环,继续执行后继语句

        bcs=cs;  //当循环体语句多于一条时用{}括起来,构成复合语句;其功能相当于一条语句。

        }  // 下面的return语句是上面循环结构的后继语句

      return (bcs):  // 将加工结果返回调用处, return后面的圆括号可以省略。

    }  //将源代码写成锯齿状的目的是增强程序的可读性,程序的结构层次清淅,一目了然。

      min(int bcs, int   cs)// 形参是局部变量,与生活中的临时工类似。 

      {int zdgys=max(bcs, cs);  // 在定义局部变量的同时调用max函数,其返回值赋之。 

      return  bcs*cs / zdgys;   // 先计算,在返回结果。

    }

      void  main ()  // 无参函数,且不能有返回值,有返回值也不允许使用它。

      {  int  bcs=26,  cs=4;  // 定义局部变量的同时,给其赋值。

        int   zdgys=max (bcs, cs)  // 调用max 函数,并将其返回值给zdgys。

        int  zxgbs=min (bsc, cs)  // 调用min函数,并将其返回值给zxgbs。

        printf (" max=%d, min=%d ", zdgys,zxgbs);   //输出结果

        return 6;   // 6可略,写上此句不算错,读者可编写一个使用此返回值的程序,编译。

    }   // 时会给出“not an allowed typ in function function name”的提示。

      在TC++系统的IDE中输入源码,保存为c2.c, 也可以在类似于NotePad这样的文本文件编缉器中输入源码,然后在TC++系统中打开,编译通过后,生成c2.obj(Object)二进制码文件,再和库函数Link成可独立执行的c2.exe(execute)机器码文件。 可以到XP的命令提示符下运行,输入结果为Max=2, Min=52。 

      为什么要把具有某一功能的一段程序称为函数呢? 仔细剖析Max这段程序可以看出,其功能是将传进来的两个正整数(自变量、其所有可能的值构成定义域)经过一定的变换规则加工为最大公约数(因变量,其所有的值构成的值域), 称这段程序为函数是比较恰当的。 

      若被调用函数处于调用函数之前,或函数的返回值类型是int型,声明语句可以省略。上面的min函数直接调用了max函数就是这个原因。函数的声明,也可以直接写在所有函数之前,程序的开始部分。下面的程序c3,c就是这样。

      long power (int, int);   // 函数的声明放在所有函数之前,可不必声明而直接调用。

      void  main  () 

      {  int a=2,  b=8;  // 16位计算机int型变量占2字节,取值范围-32768~32767

        printf ("result is:%ld ", power (a,b);  // %ld表示此处放一个长整型数,l 即long

    } //d 即decimal, 表示 换行。 

      long power (int x, int n)      // long int 型中的int 可省略,该函数的功能是求X

      {int  i ;  // 定义局部变量,也叫自动变量,用auto修饰,可以省略。

      long  result=1;   // 16 位计算机int型变量占4个字节,取值范围-2147483648~2147483647 。

      for (i=0; i<n; i ++)  // for 循环结构,循环n次。

        result*=x   // 与result = result*x等价,但前者更简洁。

            return result; 

    }

      为何printf函数没有声明,也不见其函数体,用户也没有编写这个函数,却可以拿来直接调用呢?原因是它是库函数。库函数是由C系统开发人员事先写好并编译成二进制代码后保存到库文件中,并随系统一起提供的。库函数一般完成和硬件直接打交道的底层功能,或复杂计算。前结如输出结果的printf函数,将键盘输入的数据送入到内存指定的scanf 函数, 清屏函数clrscr 等, 后者如sqrt、 sin 函数等。由于printf、 scanf 、 clrscr 函数使用频繁, TC++编译系统直接使用它们而不必声明,其他函数在使用前仍需声明,但与用户自定义函数的声明方法略有不同,程序c4.c 说明了这种差异。 

      #include <math.h>  // 包含命令,下面三个库函数首部信息保存在这个头文件中。

      viod ,main()   // 库函数sin ()、 log10 ()   , sqrt () 的返回结果作为printf () 的实参。

      {printf ("sin(3)=%lf,"sin(3))  // 求3的正弦, l 即是long, f 即 float。

      printf ("log10(10)  = %lf," ,log10(10)  )  //求 log10(10) ,    lf 表示双精度数。

      printf ("5's square root is = %lf ", sqrt (5));   // 求5的平方根

    }  // 输出结果为sin(3)= 0.14120, ,log10(10)   =1.000000, 5's square root is:2.236068 。

      # include <math.h> 是编译预处理命令,编译预处理命令(不能叫语句)不是C 语言的组成部分,但却是C编译系统的重要组成部分,使用它主要是为了提高程序的可读性。所有编译预处理命令都以#号开头且后面紧跟define, undef,  pragma 等命令,命令结束处勿写分号。

      在正式编译这段程序前,编译预处理程序找到math.h文件(该文件是一个文本文件,保存在安装文件下include 文件夹中),并将其内容复制一份粘贴到该命令处以取代该命令,然后编译器对经编译预处理后的程序进行编译、连接、生成可执行文件。 *. h (h 即head)文件一般称为头文件,这些文件中包含有库函数的首部信息和系统定义的常量、类型等。程序中用到库函数时,须将相应的头文件写入程序的开始部分,以便在进行编译预处理时,将这些文件的内容包含进来。 

      顺便提一下,<math.h>也可以写作“math.h”。 用双撇时,编译处理程序先去当前文件所在的文件夹下寻找,若找不到,再到系统配置文件所指定的文件夹中查找,查找用户自定义文件一般采用这种方法。用尖括号时,编译预处理程序直接到系统配置文件所指定的文件夹中查找,查找系统自带的文件一般采用这种方法。 

     

     

  • 相关阅读:
    DRUPAL-PSA-CORE-2014-005 && CVE-2014-3704 Drupal 7.31 SQL Injection Vulnerability /includes/database/database.inc Analysis
    WDCP(WDlinux Control Panel) mysql/add_user.php、mysql/add_db.php Authentication Loss
    Penetration Testing、Security Testing、Automation Testing
    Tomcat Server Configuration Automation Reinforcement
    Xcon2014 && Geekpwn2014
    phpMyadmin /scripts/setup.php Remote Code Injection && Execution CVE-2009-1151
    Linux System Log Collection、Log Integration、Log Analysis System Building Learning
    The Linux Process Principle,NameSpace, PID、TID、PGID、PPID、SID、TID、TTY
    Windows Management Instrumentation WMI Security Technology Learning
    IIS FTP Server Anonymous Writeable Reinforcement, WEBDAV Anonymous Writeable Reinforcement(undone)
  • 原文地址:https://www.cnblogs.com/666638zhangqiang/p/8253930.html
Copyright © 2011-2022 走看看