概述
第一章:
-
什么是计算机程序:
所谓程序,就是一组计算机能识别的和执行的指令。
-
什么是计算机语言:
指用于人与计算机之间通讯的语言。为了使电子计算机进行各种工作,就需要有一套用以编写计算机程序的数字、字符和语法规划,由这些字符和语法规则组成计算机各种指令(或各种语句)。
-
C语言的发展及其特点:
- 发展:1972年美国贝尔实验室在B语言基础上设计出了C语言,1973年移植到了unix上,1978年移植到中小型设备上,1983年 颁布了C89 , 1999年颁布了C99
- C语言的特点:
- 语言简洁,紧凑,使用方便,灵活
- 运算符丰富
- 数据类型丰富
- 具有结构化控制语句
- 语法限制不太严格,程序设计自由度大
- C语言允许直接访问物理地址,能进行位位操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作。
- 移植性好
- 生成目标代码质量高,程序执行效率高
-
C语言程序的结构:
- 预处理命令
- 程序的源程序由函数构成,每一个函数完成相应的功能
- 每一个源程序中必须有一个主函数,可以放在任何位置,但程序总是 从主函数开始执行
- 函数体:在函数后面用花括号括起来的部分
- 每个语句以分号结束,预处理命令和函数后面不能加分号
- 注释,可以出现在程序的任何地方
- 预处理命令:#开头的命令
-
运行C程序的步骤与方法:
- 编辑源程序
- 对源程序进行编译
- 进行连接
- 运行
-
程序设计的任务:
-
程序设计: 从确定任务到得到结果、写出文档的全过程。
-
程序设计的几个阶段:
- 问题分析
- 设计算法
- 编写程序
- 对源程序进行编辑、编译和连接
- 运行程序分析结果
- 编写程序文档
-
第二章
-
程序=算法+数据结构
- 算法:对操作的描述。要求对计算机要进行操作的步数,也就是算法
- 数据结构:对数据的描述。在程序中要指定用到那些数据,以及这些数据的类型和组织形式。这就是数据结构。
-
什么是算法:解决一个问题的方法和步骤。
-
算法的特性:
- 有穷性
- 确定性
- 有零个或多个输入
- 有一个或多个输出
- 有效性
-
算法的几种表示方法
- 用自然语言表示算法
- 用流程图表示算法
- 用N-S流程图表示算法
- 用伪代码表示算法
-
结构化程序设计方法:
- 自顶向下
- 逐步细化
- 模块化设计
- 结构化编码
-
什么叫结构化的算法?为什么要提倡结构化的算法?
- 使用了三种基本结构的算法叫结构化算法
- 便于编写、阅读、修改和维护,减少程序出错机会,提高程序可靠性,保证程序的质量
第三章
自增(++)、自减(–)运算符
++i,–i (在使用i之前,先使i的值加(减)1)
++i,–i (在使用i之后,先使i的值加(减)1)
字符的输入和输出
putchar 函数:向计算机显示器输出一个字符,一般函数的形式为:putchar©
getchar 函数:向计算机输入一个字符,一般函数形式为:getchar(),一次只能从键盘接收一个字符,剩余的留在缓冲区。
第六章
数组:一组有序数据的集合,每一个元素的数据类型要一致
定义数组:类型符 数组名[常量表达式] (在C语言中数组大小不能作动态定义,即数组大小不依赖程序运行中的值)
初始化一维数组:
- 在定义时对全部数组进行赋予初值。
int a[10]={0,1,2,3,4,5,6,7,8,9};- 只给一部分元素赋值
int a[10]={0,1,2,3,4,5};- int a[10] ={0}; 数组中的元素全部为零
- 不指定数组长度 int a[]={1,2,3,5,6};
定义二位数组: 类型说明符 数组名【常量表达式】 【常量表达式】
二维数组初始化:
- int a[3] [4] ={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
- int a[3] [4]={1,2,3,4,5,6,7,8,9,10,11,12};
- 对某几个数据初始化:int a[3] [4] ={{1,2},{ },{9}};(对a[0] [0], a[0] [1],a[2] [0] 进行赋值)
- int [] [4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 可以省略行数
字符数组初始化:
- char c[10] ={‘I’,’ ‘,‘a’, ‘,’ ,‘m’,’ '};
- char c[]={‘1’,‘2’,‘3’};
字符串的初始化:
- char a[]={“I love you”};
- char a[] =“I love you”;
字符串的结尾符:’ ’
字符串的输入输出:
- ‘%c’ 逐个字符输入输出
- ‘%s’整个字符串一次输入或输出
字符串处理函数
puts 输出字符串的函数:puts(字符数组名),一次只能输出一个字符
gets输入字符串的函数:gets(字符数组名),从终端获得一个字符串,并返回该字符串的首地址。一次只能输入一个字符。
strcat 字符串连接函数:strcat(字符串1.字符串2) 把两个字符串连接起来,把字符串2接到字符串1后面,结果放在字符串1里面,返回字符串1的地址
strcpy字符串复制函数 :strcpy(字符串1,字符串2),将字符串2复制到字符串1中去。
字符串1的长度必须比字符串2长度长。
字符串1必须写字符数组名,字符串2可以是字符数组名,也可以是一个字符常量。
如果在复制前未对str1数组初始化或赋值,则str1各字节中的内容是无法预知的,复制时将str2中字符串和最后的‘ ’一起复制到字符数组1中,取代字符数组1中的前面n个字符,后面的m个字符不一定是‘ ’,而是str1中原来有的东西。
不能用赋值语句将一个字符串常量或者字符数组直接赋值给一个字符数组。
strcmp函数:字符串比较函数:strcmp(字符串1,字符串2)
- str1==str2 返回0
- str1>str2 返回一个正整数
- str1<str2 返回一个负整数
strlen() : 测字符串长度:strlen(字符数组) (不包括‘ ’在内的实际长度)
strlwr() 转小写字符串:strlwr(字符串)
strupr() 转大写字符串:strupr(字符串)
第七章
1. 函数说明
- 由若干个源程序文件组成一个C程序。
- 一个源程序文件由一个或者多个函数以及其他有关内容(指令、数据声明和定义等)组成。在编译时是以源程序为单位进行编译的
- C语言从main函数开始,在main中调用其他函数,在调用后流程返回到main函数。
- 函数间可以相互独立,但是不能嵌套调用,不能调用main函数,他是被系统调用的,
- 从用户角度看,函数有两种:库函数和用户自定义的
- 从函数的形式看,函数分两类:有参函数和无参函数
2. 定义函数
- 定义无参函数
- 类型名 函数名(){ 函数体 }
- 或类型名 函数名(void){ 函数体 }
- 定义有参函数
- 类型名 函数名(形参列表){ 函数体 }
3. 调用函数
- 调用无参函数的一般形式:函数名();
- 调用有参函数的一般形式: 函数名(实参列表);
4. 函数的调用形式
- 函数调用语句:printf();
- 函数做表达式:c=2*sum(a,b);
- 函数作为参数:m=max(a,max(b,c))
5. 函数调用时的数据传递
- 形式参数:就是在定义函数或过程的时候命名的参数。
- 形参是能是变量。
- 形参不占用存储空间
- 实际参数:在调用有参函数时,函数名后面括号中的参数称为“实际参数”
- 实参可以是常量、变量或表达式。
- 实参的本质是一个变量,已经占用内存空间。
- 实参和形参之间的数据传递:
- 形参是变量,但是函数被调用时才被分配内存。当函数执行完毕返回时,形参占用的内存空间又被释放。
- 对应的实参和形参是两个独立实体,它们之间只有单向的值的传递,即实参的值传递给形参。形参的值在函数中不论怎么改变,都不会影响实参。
6. 函数的返回值
- 函数的返回值是通过函数中的return语句获得的
- 返回值类型要和return语句中表达式类型一致。
- 函数类型决定返回值类型。
- 不带返回值的,返回值类型定义为void
7. 函数的声明方式
**函数声明的一般形式有两种,分别为: **
- 函数类型 函数名(参数类型1 参数名1,参数类型2 参数2.。。参数类型n,参数名n)
- int max(int num1,int num2,float score);
- 函数类型 函数名(参数类型1 ,参数类型2 .。。参数类型n)
- int max(int ,int ,float );
8. 数组作为函数的参数
- 把数组值当作函数参数是:实参到形参的,单向传值,是值传递方式。
- 数组名当作函数的参数是:把实参把数组的首地址传递给形参,是地址传递的方式。
9. 局部变量和全局变量
- 局部变量:在函数、循环、判断等语句块里面定义的变量称为局部变量。
- 从定义位置到语句块结束
- 全局变量:定义在函数之外的变量称为外部变量
- 全局变量可以为本文件中其他所有函数所共用
- 有效范围从定义变量的位置到本源文件结束。
- 当局部变量跟全局变量同名时,会屏蔽全局变量,使用局部变量
10. 变量的存储方式
C语言的存储类型分为:auto(自动的)、static(静态的) 、register (寄存器)、extern(外部的)
局部变量的存储类型:
自动变量(auto变量):局部变量不做特殊声明,都是auto存储类别。
在调用时系统给变量分配存储空间,在调用结束时自动释放这些存储空间。(函数体内的变量,形参等)
auto 属于动态存储类型
自动变量是在函数调用时进行的,每调用一次就赋予一次初值
不赋初值,值是一个不确定的值(每次函数调用以后存储单元被释放掉,下次调用到时候,下次调用重新分配存储单元,所有单元中的内容是不确定的)
静态局部变量(static变量):用static修饰的局部变量。
- 函数中的局部变量的值在函数调用结束后不消失而继续保留原有值,即其占用的存储单元不释放,在下一次再调用该函数时,变量里面存储上一次调用以后的值,程序结束以后是否存储单元。
- static属于动态存储类型
- 在编译时赋初值,即只赋值一次
- 不赋初值默认的是0或’ ’
- 静态局部变量不能被其他函数引用。
寄存器变量(register 变量)
- 寄存器变量:将局部变量的值放在CPU中的寄存器中,需要时直接从寄存器取出参加运算。(当一个变量频繁使用时可以使用存储器类型,register int f)
auto变量存储在动态存储区中,static变量存储在静态存储区中,register存储在CPU寄存器中
全局变量存储类型
- extern变量:
- 把外部变量的作用域扩展到此处开始
- 把外部变量的作用域扩展到另一个文件
- static变量:
- static +全局变量 称为静态外部全局变量,只能在本文将中调用,不能在其他文件中调用。
- 全局变量全部放在静态存储区的,默认是static。
11.内部函数和外部函数
- 函数默认的存储类型是extern类型(既可以被本文中的函数调用,又可以被另外的文件中的函数调用)
- 内部函数:加static修饰的函数是外部函数
- static 类项名 函数名(形参表)
- 只能被本文件中的函数调用。
- 外部函数:加extern修饰的函数是外部函数
- extern 类项名 函数名(形参表)
- 可以被其他文件中的函数调用,也可以被本文件中的函数调用
- 函数的默认存储类型就是extern,所以在定义时可以省略
第八章
指针:指向变量单元的地址
指针变量:存放地址值(指针)的变量
定义指针变量: 类项名 *指针变量名
一个指针变量包括:存储单元的地址和数据类型
通过指针引用一维数组:
程序中的数组名不代表整个数组,只代表数组元素的首地址
指针可以进行如下运算:
- 加一个整数
- 减一个整数
- 自加 ++p, p++(指向下一个元素)
- 自减 --p, p-- (指向上一个元素)
- 两指针相加(p2-p1 计算两个指针之间的相对距离)
- *(a+5) = *(p+5) = a[5];
- [] 实际上就是变址运算符,找出此地址上的值
常见情况:
- p++ ; *p, p++ 使p指向下一个元素,然后再得到其值
- *p++, *和++ 同优先级,自右向左,等价于 *(p++),先指向下一位,然后再得到其值。
- ++(*p) = ++a[i] 表示先得到p指向的值,然后再给值加1
- *(p–) 相当于 a[i–] ,先计算p指向的值,然后再使p的值减一
- *(++p) =先使p自加,然后在计算p的值
使用数组作为函数参数
- C语言把数组当作参数时,把数组的首地址传给形参,采用方式是值传递,当形参发生改变时不会对实参产生影响,但是如果修改形参指向的值,实参里面的值也会修改
通过指针引用多维数组
二维数组a的有关指针
表现形式 含义 地址值 a 二维数组名,指向一维数组a[0],0 行的起始位置 2000 a[0], *(a+0), *a 0 行0列的元素地址 2000 a+1,&a[1] 1 行起始地址 2016 a[1], *(a+1) 1行1列的起始地址 2016 a[1]+2,*(a+1)+2,&a[1] [2] 1行2列的起始地址 2024 *(a[1]+2), *( *(a+1) + 2 ),a[1] [2] 1行2列的值。 元素值13 指向多维数组元素的指针变量
指向数组元素的指针变量
#include<sstdio.h> int main() { int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int *p; // p 是 int *指针变量 // p初始指向0行0列,然后让p依次指向下一个元素 for(p=a[0];p<a[0]+12;p++) { if((p-a[o])%4==0) printf("n"); // p 移动四次以后就换行 printf("%4d",*p); //输出p指向元素的值 } printf("n"); return 0; } /* 输出某一个指定数值元素,例如(a[1][2]),则可以计算相对于起始位置的位移量 1(行下标) * 列数(2)+j(列下标); 定义p指向0行0列,当p+1时,他就指向了下一个元素(0行1列),那么我们要输出a[0][3],此时我们只要p+3就可以了,我们要输出1行2列,我们给p+6就可以指向a[1][2],最后我们推出公式:(行下标) * 列数+j(列下标); */
指向m个元素组成的一维数组的指针变量
#include<stdio.h> int main() { int a[3][4]={1,2,3,4,5,6,7,8,9,10}; //定义二维数组a并初始化 int(*p)[4],i,j; //指针变量p是一个指向包含4个整型元素的 p=a; //p指向二维数组的第0行 printf("please center row and cloum"); scnaf("%d,%d",&i,&j); //输入要求输出的元素的行列号 printf("a[%d,%d]=%dn",*(*(p+i)+j)); //输出a[i][j]; return 0; } /* 结论: 1. int (*p)[4]的类型为int(*)[4]型, p被定义为指向一维数组的指针变量,一维数组有4个元素, 因此p的基类型是一维数组,其长度是16个字节。 2. *(p+2)+3括号中的2是以p的基类为长度增加的, p每加1就增加16个字节,p+2得到指向a[2]的地址值, *(p+2)得到a[2],即 &a[2][0], 此时已经转化为指向列的指针。 而括号外面的加3,是以元素的长度为单位,*(p+2)+3指向a[2][3]的地址 *(*(p+2)+3)是a[2][3]的值。 */
#include<stdio.h> int main() { int a[4]={1,2,3,4}; int (*)p[4]; //指向一维数组的指针 p=&a; //使指针指向一维数组 printf("%dn",(*p)[3]); //输出a[3],7 return 0; } /* p=a 是让指针指向一维数组的首元素, 而p=&a 是让p指向一维数组,指向一维数组的行, 而(*p)指向a[0]的首地址。 */
多维数组做函数参数。
多为数组作参数有两种方法:
- 用指向变量的指针变量
- 用指向一维数组的指针变量
#include <stdio.h> #include <stdlib.h> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ #include<stdio.h> #include <stdio.h> /*求总成绩的平均值*/ void average(float*p,int n) { //float *p 指向score 的第o行0列的地址 float *p_end = p+n-1; //指向 score 的最后一个数据 float sum=0; for(;p<=p_end;p++) //让p 指向下一位 { sum+=(*p); // 获取对应地址的值 } //计算平均值 float avg=sum/12.0f; printf("%5.2fn",avg); } /*找出并输出第i个学生的成绩*/ void search(float(*p)[4],int n){ int i; for(i=0;i<4;i++){ printf("%5.2f ",*(*(p+n)+i)); } } int main() { float score[3][4]={{65,67,70,60},{80,87,90,81},{90,99,100,98}}; average(*score,12); // * score 指向 score 的 0 行 0列 的地址值 search(score,2); // score 指向第 0 行的地址值 }
字符串的引用方式
用字符数组存放一个字符串,可以通过数组名和下标引用字符串中一个字符,也可以通过数组名和格式声明%s输出该字符串。
用字符指针变量指向一个字符串常量,通过字符指针变量引用字符串常量
#include<stdio.h> int main() { char *string ="I love Chain!"; //定义字符指针变量string并初始化 printf("%sn",string); //输出字符串 return 0; } /* 1.对指针变量string初始化,是把字符串的第一个字符的地址值赋给 * string,而不是把“赋给了 *string”。 2. %s是输出字符串时所用的格式符,在输入string 指向的第一个字符以后,string自动+1指向下一个元素,直到遇到'