内部函数和外部函数 我们之前了解到,变量有着作用域,有局部变量和外部变量之分。那么相对于函数而言,也有着内部函数与外部函数的区别。在程序中,有的函数可以被本文件中的其他函数调用,也可以被其他文件中的函数调用但是有的函数却只能被本文件中的其他函数调用,不能被其他文件中的函数调用。我们定义一个函数的目的就是为了让它被另外的函数调用,那么在不加声明的情况下,这个函数就是全局的,也就是说该函数既可以被本文件中的函数调用,也可以被其他文件中的函数调用。这里我们就需要考虑一些情况,
变量的声明与定义的关系 对于外部变量的声明,就是声明该变量是一个已在其他地方定义的外部变量,只是为了扩展其作用域。关于声明和定义,我们一般是认为他们是一样的,这就出现了混淆,我们这里来分析一下。声明部分的作用就是对有关的标识符(变量,函数,结构体,共用体等)的属性进行声明。在函数中对变量的声明只要没有用extern来声明,那么他就是定义。但是他的声明却可以有很多次,既可以在函数内,也可以在函数外。int a,这是一个定义性声明,对函数的类型也进行了定义。而在函数中对其他函数的声明就不是定义,比如被调用函数。
变量的存储方式与生存期 因为程序运行时,调用函数后他的值并不会消失,也就不需要再一次赋初值。这个程序就可以用来求阶乘,它的这个被调用函数里面就是根据n的值来确定被调用的次数,而f是一个静态局部变量,这样,就可以从1累成到n,也就实现了阶乘的运算。我们在程序的整体来看,A,B,C是在函数的外部定义的外部变量,常规来说,他的作用域就是从定义处开始到程序结束,也就是说上面的主函数是不可以用这三个变量的。我们可以看出,每一次循环结束,b的值都会消失,在调用时,重新赋值为0,而c的值不会随着调用结束而消失,这就是static的作用。
数组作为函数参数 X调用有参函数时,需要提供实参,实参可以是常量、变量或表达式。数组元素的作用与变量相当,一般来说,凡是变量可以出现的地方,都可以用数组元素代替。因此,数组元素也可以用作函数实参,其用法与变量相同,像形参传递数组元素的值。此外,数组名也可以用作形参和实参,传递的是数组第一个元素的地址。
函数的递归调用 因为int类型的存储单元有限,更大的结果就不准确,上面的20!这里是再调用函数f时,其内部有一次调用了f函数,这五个就是直接调用本函数。在调用一个函数的过程中又出现直接或间接的调用该函数本身,这张图里的第一个就是直接调用,第二个是间接调用。为了出现有限次的调用,我们使用if语句来控制。考虑了所有的情况,首先是n的正负,附属不要。有5个学生坐在一起,问第五个学生的年龄。这两种递归调用都是无终止的自身调用。在这个程序里面,主要是函数部分的定义。第三个学生比第二个学生大两岁,第二个学生比第一个学生大两岁,
程序:求四个实数中最大的数(嵌套调用) 这个就是嵌套调用,看程序还是很好理解的。主调函数先调用max4,将abcd的值给了形参,在一个函数中不能再定义另一个函数,既不能嵌套定义。我们之前说了,函数之间是平行关系。之后max4调用max2,但可以进行嵌套调用。
定义函数 1.定义无参函数这个函数的一般形式为:类型名 函数名()函数体或类型名 函数名(void)函数体函数名后面括号内的void表示空,即函数没有参数。2.定义有参函数我们来看一个max函数:int z;z = x>y?x : y;return(z);这个就是一个有参函数,求的是x和y中的最大值。我们在调用这个函数时,主调函数将x和y值传递给此被调用函数,x和y是形式参数。
调用函数的注意事项 (1).库函数,系统提供的,可直接使用,不同的C语言编译系统的库函数某些是不同的。1.C程序的执行是从main函数开始的,如果在main函数中调用其他函数,在调用后流程返回到main函数,在main函数中结束整个程序的运行。2.所有函数都是平行的,即在定义函数时是分别进行的,是互相独立的。一般情况下,执行被调用函数时会得到一个函数值,供主调函数使用。无参函数可以带回或不带回函数值,但一般不带回的居多。一个函数并不从属于另一个函数,即函数不能嵌套定义。在调用无参函数时,主调函数不向被调用函数传递数据。
程序:简单的函数调用 这个是为了对用户定义的函数(print_star函数和print_message函数)进行声明,指定其类型为void。在主函数中,只要我们声明了其他函数,并且对其他函数进行了定义,就可以对函数进行调用。分别为主函数,print_star函数和print_message函数。void是空的意思,所以这种声明的意思就是函数无类型,即无函数值。在程序中定义的函数的命名并无固定形式,但要做到容易记和理解。这里面我们将主函数看成是一个母体,另外两个函数看成是零件。我们需要注意,对函数的声明需要在main函数后面。
程序:找出三个字符串的“最大者” 这里面的strcmp和strcpy函数都是之前讲过的,分别是字符串比较函数和字符串复制函数。先拿第一行和第二行进行比较,把大的复制给string,然后把第三行和string进行比较。在这里,我们可以设定一个二维数组,大小为3*20,即有3行20列,每行存放一个字符串。这里是设定了一个三行的字符数组,我们其实可以设定三个字符数组。这个程序从总体上看是非常简单的,就是对三串字符进行了比较。这个程序的最后还有一个else的情况,上面没有写入。这个程序利用了之前的字符串的大小比较。把最大的复制给string。
程序:求一行字符中有几个单词 第一个检测的是I,这个不是空格,但是word值是0,那么就有else if后的运算,之后word变为1,第二个元素是空格,word再次变为0,集训进行else if的运算,word再次变为1,之后知道下一个空格,word才变为0,num再次加1,这样可以计算出值为4。这个不同之处在于开头是一个空格,但这个并不影响,开头是空格,word值为0,num+1,遇到I,word变1,之后在遇到空格,word变0,num+1.如是进行,结果还是4.word无非就两个值,0和1,这很好的界定了num的增长。
字符数组 用来存放字符数据的数组是字符数组。在字符数组中的一个元素内存放一个字符。如:char c[5];cc[0]=‘e’;c[1]=‘a’;c[2]=‘b’;c[3]=‘c’;c[4]=‘d’;上面定义的就是字符数组c,其内元素为eabcd。字符是按照整数存放的,因此也可以用int定义字符数组,如:int a[10]
程序:求矩阵中最大的数 打擂台,固定参赛人数,先选一个人上擂台,之后逐个进行比武,输者淘汰。最后留下的就是最强的。有一个3*4的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号。一直比较到最后一个元素,稀释就能求出max的值,而对应的行和列已经被记录。每次循环都拿a[i][j]来与max进行比较,大的数变为max,i对应的是行,有三行,i就循环三次,这个是外循环。同时拿第一行第一列的元素作为max,最大值。这个我们用打擂台算法,也可以理解成淘汰法。这个程序还有前面比大小的影子,内循环是j,有四列,循环四次。
程序:将二维数组行和列的元素互换 内部的for循环中的j对应数组a的列数,之后的语句就是把数组a的(i+1)行(j+1)列元素赋值给数组b的(j+1)行(i+1)列元素。这个是定义数组b和后面要用到的可以用来表示行和列的i和j。第一个for循环,i取0和1,循环两次,对应数组a的行数。我们只需要把a[i][j]换成a[j][i]即可。数组a和b的行和列的数值是相反的。这个是输出替换后的数组b。这个程序还是很简单的,这个是对数组a进行赋值。
二维数组的定义和引用 4.如果对全部元素都赋初值(即提供全部初始数据),则定义数组时对第1维的长度可以不指定,但第二维的长度不能省去。虽然我们可以在直观上看到用矩阵表示的二维数组,但在内存的存放中,二维数组的数据是连续存放的,呈线性排列。我们在向二维数组中输入元素时,就像上面两行三列中的数字顺序一样进行输入的,这个表示的就是数组b的第一行第二列元素等于数组a的第二行第三列元素/2。在引用数组元素时,下标值应在已定义的数组大小的我范围内,内部的每一个{}表示一行,内部的{}内的是该行的元素。
程序:对十个数据进行从小到大的排序(冒泡排序法) 第2次拿调换过的第二个数与第三个数比较,大的数向后调,即在比较结束后,大的数在第三个位置。第1次拿第一个数和第二个数进行比较,大的数向后调,即在比较结束后,大的数在第二个位置。这个最终调换我们通过例子来理解,就是上面说的将最大的数放在最后一位这个整体的过程。下面的式子就是大数与小数的调换过程,之前在比较两个数的大小就是这种方法。将第二大的数放在倒数第二位,需要进行8次比较,以此类推,来进行调换。将最大的数放在最后,香醋要进行9次比较,i从0开始,进行9次比较。这里的for循环就是用来输出数组元素的。
程序:用一维数组编写斐波那契数列 这个时使用新的方法来进行斐波那契数列的求解。这个程序中用到的计算方法跟之前的是一样的。他用了两次循环,第一次时关于数值的,我们给出的数组只限定了20个元素,第二次循环是针对每行元素数目的。内部的计算方法还是很简单的,所以输出的也是20个。