(1)语言简洁、紧凑,使用方便、灵活
(2)运算符丰富
(3)数据类型丰富
(4)具有结构化的控制语句
(5)语法限制不太严格,程序设计自由度大
(6)C语言允许直接访问物理位置,能进行位(bit)操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作。
(7)C语言编写的程序可移植性好
(8)生成目标代码质量高,程序执行效率高
C语言程序的结构与主函数,程序的书写格式与规范;
C语言是由函数构成的
一个完整的C程序必须有且只能有一个main函数
C语言标识符只能由字母、数字和下划线组成,开头只能是字母或下划线,不能是数字
在C语言中,整型常量可用以下三种形式表示:
(1)十进制整数。
如:123, -456.4。
(2)八进制整数。以0头的数是八进制数。
如:0123表示八进制数123,等于十进制数83,-011表示八进制数-11,即十进制数-9。
3)十六进制整数。以0x开头的数是16进制数。
如:0x123,代表16进制数123,等于十进制数 291。 -0x12等于十进制数-10。
浮点型两种表现形式(小数:0.123、指数:3e-3)
字母e(或E)之前必须有数字,且e后面的指数必须为整数
转义字符:
\n 换行
\t 横向跳格
\r 回车
\ 反斜杠
\ddd ddd表示1到3位八进制数字
\xhh hh表示1到2位十六进制数字
赋值运算符和赋值表达式
逗号运算符和逗号表达式
常量指针和指针常量的区别:
1、本质
指针常量:本质上一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。
常量指针:本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。
2、地址
指针常量:在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化。
常量指针:指针可以指向其他地址
3、内容
指针常量:指向的内容可以修改
常量指针:在常量指针中,指针指向的内容是不可改变的,指针看起来好像指向了一个常量。
格式输入和格式输出函数,
非格式化输入、输出函数;
格式字符 d,i 以带符号的十进制形式输出整数
格式字符 o 以八进制无符号形式输出整数
格式字符 x,X 以十六进制无符号形式输出整数
格式字符 u 以无符号十进制形式输出整数
格式字符 c 以字符形式输出,只输出一个字符
格式字符 s 输出字符串
格式字符 f 以小数形式输出单、双精度,隐含输出6位小数
格式字符 e,E 以指数形式输出实数,用e时指数以“e”表示(如1.2e+02),用E时指数以“E”表示(如1.2E+02)
格式字符 g,G 选用%f或%e格式中输出宽度较短的一种格式,不输出无意义的0。用G时,若以指数形式输出,则实数以大写表示
(1)算术运算符 (+ 、-、 *、 /、 %、 ++、 --)
(2)关系运算符 (> 、<、 ==、 >=、 <=、 !=)
(3)逻辑运算符 (! 、&&、||)
(4)位运算符 (<< 、>>、 ~、 |、∧、&)
(5)赋值运算符 (=及其扩展赋值运算符)
(6)条件运算符 (?:)
(7)逗号运算符 (,)
(8)指针运算符 (*、&)
(9)求字节数运算符 (sizeof)
(10)强制类型转换运算符 ((类型))
(11)成员运算符 (.->)
(12)下标运算符 ([ ])
(13)其他 (如函数调用运算符())
算术运算符是自左至右(左结合性),赋值运算符是自右至左(右结合性)
C语言语句的语法及书写规范;
程序设计的流程图,程序控制结构中的顺序结构,复合语句;
if结构、if结构的多种形式,switch 结构与多分支结构;
当型循环,直到型循环,break语句与continue语句。
算法的特点:
(1)有穷性
(2)确定性
(3)有零个或多个输入
(4)有一个或多个输出
(5)有效性
用流程图表示算法:
起止框
输入输出框
判断框
处理框
流程线
注释框
连接点
注意:
(1)只有一个入口;
(2)只有一个出口;注意:一个菱形判断框有两个出口,而一个选择结构只有一个出口。
(3)结构内的每一部分都有机会被执行到;
(4)结构内不存在“死循环”(无终止的循环)
一维数组,字符数组,二维数组;
定义一维数组 类型说明符 数组名【常量表达式】;
引用一维数组元素 数组名【下标】
定义二维数组 类型说明符 数组名【常量表达式】【常量表达式】
二维数组中元素排列顺序按行存放
引用二维数组元素 数组名【下标】【下标】
下标可以是整型常量或整型表达式。
定义数组第一位长度可以不指定,第二维数组不能省略
存放字符数据
空操作符:’\0’、null、’ ’
字符串结束标志:’\0’
输入字符串函数:gets函数
输出字符串函数:puts函数
字符串连接函数:strcat函数
字符串复制函数:strcpy函数
字符串比较函数:strcmp函数
字符串长度函数:strlen函数
字符串转换小写函数:strlwr函数
字符串转换大写函数:strupr函数
指针:
*
:取值操作符
&
:取址操作符
通过指针引用数组元素:
(1)下标法 a[i]
(2)指针法 (a+i)或(p+i)
有时需要将不同类型的数据组合成一个有机的整体,以便于引用。如:
一个学生有学号/姓名/性别/年龄/地址等属性
int num; char name[20]; char sex;
struct 结构体名
{成员表列};
如:struct student
{
int num;char name[20];char sex;
int age;float score;char addr[30];
}
(1)先声明结构体类型再定义变量名
例如:struct student student1, student2;
(2)在声明类型的同时定义变量
这种形式的定义的一般形式为:
struct 结构体名
{
成员表列
}变量名表列;
(3) 直接定义结构体类型变量
其一般形式为:
struct
{
成员表列
}变量名表列;
即不出现结构体名。
与其他类型的数组一样,对结构体数组可以初始化。例如:
struct student
{int num;char name[20]; char sex;
int age; float score; char addr[30];
};stu[2]={{10101,″LiLin″,′M′,18,87.5,″103 BeijingRoad″},{10102,″Zhang Fun″,′M′,19,99,″130 Shanghai Road″}};
用typedef声明新的类型名
声明枚举类型语句的一般格式和功能为:
格式:enum 标识符{枚举元素列表}变量列表;
功能:
(1)显式或隐式指定所列枚举元素所代表的整数;
(2)如果不省略标识符,则定义一个枚举类型(名):
enum 标识符
枚举元素表是一组用逗号分隔的标识符或整数常量赋值表达式,第一个枚举元素的默认值为0,其它枚举元素的值为前者加1。
typedef语句的格式和功能为:
格式:typedef 数据类型名 别名1,…,别名n;
功能:给指定数据类型增加一组名称。
typedef语句也可在声明结构体、共用体、枚举类型的同时给它增加一组名称。
用指针处理链表
建立链表:create
输出链表:print
插入链表:insert
删除链表:delete
共用体类型:union
枚举类型:enum
使几个不同的变量共占同一段内存的结构称为“共用体”类型的结构.
定义共用体类型变量的一般形式为:
union 共用体名
{
成员表列
}变量
只有先定义了共用体变量才能引用它,而且不能引用共用体变量,而只能引用共用体变量中的成员。
共用体与结构体相似,主要区别有:
(1)定义共用体的保留字为union;
(2)同一共用体各成员的基址相同,访问成员时必须与最后所存数据的类型相同,共用体数据所占内存与其成员中所占内存最大者相同;
(3)不可初始化共用体变量。
读取共用体成员时,应按最后一次所存入成员的数据类型读取。
共用体和结构体的成员可以是已存在的共用体和结构体,但不可嵌套定义。
枚举:将变量的值一一列举出来,变量的值只限于列举
出来的值的范围内。
申明枚举类型用enum
enum weekday{sun,mon,tue,wed,thu,fri,sat};
定义变量:
enum weekday workday,week-day;
enum{sun,mon,tue,wed,thu,fri,sat}workday;
变量值只能是sun到sat之一
#include
main()
{enum color {red,yellow,blue,white,black};
enum color i,j,k,pri; int n,loop;n=0;
for (i=red;i<=black;i++)
for (j=red;j<=black;j++)
if (i!=j)
{ for (k=red;k<=black;k++)
if ((k!=i) && (k!=j))
{n=n+1;
printf("%-4d",n);
for (loop=1;loop<=3;loop++)
{ switch (loop)
{ case 1: pri=i;break;
case 2: pri=j;break;
case 3: pri=k;break;
default:break;
}
switch (pri)
{ case red:printf("%-10s","red"); break;
case yellow: printf("%-10s","yellow"); break;
case blue: printf("%-10s","blue"); break;
case white: printf("%-10s","white"); break;
case black: printf("%-10s","black"); break;
default :break;
}
}
printf("\n");
}
}
printf("\ntotal:%5d\n",n);
}
用typedef声明新的类型名来代替已有的类型名
声明INTEGER为整型
typedef int INTEGER
声明结构类型
Typedef struct{
int month;
int day;
int year;}DATE;
指针的基本概念,指针变量的定义,指针变量的赋值;
地址运算符与指针运算符、间接寻址;
指针变量:
引用指针变量:
*
取值操作符
&
取址操作符
3.指针与数组(简单应用):
指针与一维数组,移动指针及两指针相减运算,指针比较,
指针与字符串,
指针与二维数组;
通过指针引用数组
(1)下标法
(2)指针法
通过指针引用多维数组
指向多维数组元素的指针变量
(1)指向数组元素的指针变量
(2)指向由m个元素组成的一维数组的指针变量
用指向数组的指针作函数参数
指针变量作为函数参数:将一个变量的地址传送到另一个函数中。
用数组名作函数参数
形参可用数组名,也可用指针变量名
实参不能改变指针变量,能改变实参数组的值
实参与形参如果是指针类型,基类型必须一致
指针引用字符串
字符指针作函数参数
形参和实参可以分别用字符数组名或字符指针变量
指向函数的指针
用函数指针变量调用函数
(1)通过函数名调用函数
(2)通过指针变量调用它所指向的函数
用指向函数的指针作函数参数:把函数的入口地址作为参数传递到其他函数
可以对字符指针变量赋值,但不能对数组名赋值。
指针变量的值可以改变,而字符数组名代表一个固定的值(数组首元素的地址),不能改变
返回指针值的函数
指针数组,定义指针数组,指针数组的应用,
指向指针的指针,定义指向指针的指针变量,指向指针的指针变量的应用;
指针数组和多重指针
指向指针数据的指针变量
指针数组作main函数的形参
指向结构变量的指针变量,指向结构数组的指针变量。
函数指针和指针函数的区别:
函数指针:函数类型(指针变量名)(形参列表);
“函数类型”说明函数的返回类型,由于“()”的优先级高于“”,所以指针变量名外的括号必不可少,后面的“形参列表”表示指针变量指向的函数所带的参数列表。
例如:
int (*f) (int x);
double (*ptr) (double x);
定义函数指针时注意:
函数指针和它指向的函数的参数个数和类型都应该是—致的;函数指针的类型和函数的返回值类型也必须是一致的。
函数指针的赋值
函数名和数组名一样代表了函数代码的首地址,因此在赋值时,直接将函数指针指向函数名就行了。
例如:
int func(int x); //声明一个函数
int (*f) (int x); //声明一个函数指针
f=func; //将func函数的首地址赋给指针f
赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。
通过函数指针调用函数
函数指针是通过函数名及有关参数进行调用的。
与其他指针变量相类似,如果指针变量pi是指向某整型变量i的指针,则p等于它所指的变量i;如果pf是指向某浮点型变量f的指针,则pf就等价于它所指的变量f。同样地,*f
是指向函数func(x)
的指针,则*f就代表它所指向的函数func。所以在执行了f=func;
之后,(*f)
和func
代表同一函数。
由于函数指针指向存储区中的某个函数,因此可以通过函数指针调用相应的函数。现在我们就讨论如何用函数指针调用函数,它应执行下面三步:
首先,要说明函数指针变量。
例如:int (*f)(int x);
其次, 要对函数指针变量赋值。
例如:f=func; (func(x)必须先要有定义)
最后, 要用 (*指针变量)(参数表);调用函数。
例如: (*f)(x);
(x必须先赋值)
举例:任意输入n个数,找出其中最大数,并且输出最大数值。
main()
{
int f();
int i,a,b;
int (*p)(); /* 定义函数指针 */
scanf("%d",&a);
p=f; /* 给函数指针p赋值,使它指向函数f */
for(i=1;i<9;i++)
{
scanf("%d",&b);
a=(*p)(a,b); /* 通过指针p调用函数f */
}
printf("The Max Number is:%d",a)
}
f(int x,int y)
{
int z;
z=(x>y)?x:y;
return(z);
}
指针函数
一个函数不仅可以带回一个整型数据的值,字符类型值和实型类型的值,还可以带回指针类型的数据,使其指向某个地址单元。返回指针的函数,一般定义格式为:类型标识符 *函数名(参数表) int *f(x,y); 其中x,y是形式参数,f是函数名,调用后返回一个指向整型数据的地址指针。f(x,y)是函数,其值是指针。
如:char *ch();表示的就是一个返回字符型指针的函数
举例:将字符串1(str1)复制到字符串2(str2),并输出字符串2.
#include
main()
{
char *ch(char *,char *);
char str1[]="I am glad to meet you!";
char str2[]="Welcom to study C!";
printf("%s",ch(str1,str2));
}
char *ch(char *str1,char *str2)
{
int i;
char *p;
p=str2
if(*str2==NULL) exit(-1);
do
{
*str2=*str1;
str1++;
str2++;
}
while(*str1!=NULL);
return(p);
}
总结:函数指针是一个指向函数的指针,而指针函数只是说明他是一个返回值为指针的函数, 函数指针可以用来指向一个函数。
函数 先定义后使用
函数的递归调用
直接或间接的调用该函数本身
函数的返回值是通过函数中的return语句
函数类型决定返回值的类型
函数两种类型:无参函数、有参函数
形式参数和实际参数
实际参数可以是常量、变量以及表达式
实参与形参的参数类型应一致
数组作为函数参数
数组元素作函数实参:把实参的值传给形参“值传递”方式
用数组名做函数实参时,不是把数组元素的值传给形参,而是把实参数组的首元素地址传递给形参数组
函数数据按数值传递,函数数据按地址传递,
利用函数返回值和外部变量进行函数数据传递,结构变量作为函数参数传递;
函数的嵌套调用、函数的递归调用;
局部变量与全局变量的定义、初始化及作用范围;
局部变量和全局变量
局部变量:函数内部定义,只在本函数范围内有效
全局变量:函数外部定义,可以为本文件中其他函数所共用
局部变量与全局变量的生存期,
静态变量与动态变量的定义、初始化、作用范围及生存期;
每一个变量和函数都有两个属性:数据类型和数据的存储类别
存储类别指的是静态存储和动态存储
C语言的存储类别分为四种:自动的(auto)、静态的(static)、寄存器的(register)、外部的(extern)
静态局部变量属于静态存储类别,在静态储存区内分配存储单元。在整个运行期间都不释放。
自动变量(即动态局部变量)属于动态存储类别,分配在动态存储区空间而不在静态存储区空间,函数调用结束后即释放。
如果在定义局部变量时不赋初值的话,对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符‘\0’(对字符变量)。而对自动变量来说,它的值是一个不确定的值。
文件:ASCII文件和二进制文件
fread(buffer,size,count,fp);
buffer:地址
size:要读写的字节数
count:要读写多少个数据项
fp:FILE类型指针
r只读 文本文件
w只写 文本文件
a追加 文本文件
rb只读 二进制文件
wb只写 二进制文件
ab 追加 二进制文件
r+读写 文本文件
w+读写 文本文件
a+读写 文本文件
rb+读写 二进制文件
ab+读写 二进制文件
程序调试步骤:
(1)先进行人工检查,即静态检查。
(2)上机调试。
(3)在改正语法错误和“警告” 后,程序经过连接(link)就得到可执行的目标程序。运行程序,输入程序所需数据,就可得到运行结果。
常见错误:
(1)忘记定义变量。
(2)输入输出的数据的类型与所用格式说明符不一致。
(3)未注意int型数据的数值范围。
(4)在输入语句scanf中忘记使用变量的地址符。
(5)输入数据的形式与要求不符。
(6)误把“=”作为“等于”运算符。
(7)语句后面漏分号。
(8)在不该加分号的地方加了分号。
(9)对应该有花括号的复合语句,忘记加花括号。
(10)括号不配对。
(11)在用标识符时,忘记了大小写字母的区别。
(12) 引用数组元素时误用了圆括号。
(13) 在定义数组时,将定义的“元素个数”误认为是“可使用的最大下标值”。
(14) 对二维或多维数组的定义和引用的方法不对。
(15) 误以为数组名代表数组中全部元素。
(16) 混淆字符数组与字符指针的区别。
(17) 在引用指针变量之前没有对它赋予确定的值。
(18) switch语句的各分支中漏写break语句。
(19) 混淆字符和字符串的表示形式。
(20) 使用自加(++)和自减(–)运算符时出的错误。
(21) 所调用的函数在调用语句之后才定义,而又在调用前未声明。
(22) 对函数声明与函数定义不匹配。
(23) 在需要加头文件时没有用#include命令去包含头文件。
(24) 误认为形参值的改变会影响实参的值。
(25) 函数的实参和形参类型不一致。
(26) 不同类型的指针混用。
(27) 没有注意函数参数的求值顺序。
(28) 混淆数组名与指针变量的区别。
(29) 混淆结构体类型与结构体变量的区别,对一个结构体类型赋值。
程序出错有3种情况:
① 语法错误
② 逻辑错误
③ 运行错误
1.用C表达式或函数计算相对应的数学表达式;
2.连加与连乘的计算,级数的计算;
3.冒泡法排序与选择法排序;
4.矩阵的简单运算与显示;
5.字符串操作;
6.文件编程应用。
按位与 & 如果两个相应的二进制位都为1,则该位的结果值为1;否则为0。
例:0&0=0,0&1=0,1&0=0,1&1=1
3&5=11&01=01=1
84&59=1010100&0111011=0010000=16
按位或 | 两个相应的二进制位中只要有一个为1,该位的结果值为1。
例: 0|0=0,0|1=1,1|0=1,1|1=1
060 | 017= 00110000 | 00001111=00111111
按位异或 ∧ 同号结果为0 异号则结果为1
例: 0∧0=0,0∧1=1,1∧0=1, 1∧1=0
071∧052=000111001∧000101010=000010011=023
按位取反 ~ 对一个二进制数按位取反,即将0变1,将1变0。
例:~025是对八进制数25即二进制数(00010101)按位求反。
左移运算符 <<
左移1位相当于该数乘以2,左移2位相当于该数乘以22=4,15<<2=60,即乘了4。
例:若a=15, 即二进制数00001111,左移2位得00111100,(十进制数60) 高位左移后溢出,舍弃。
右移运算符 >>
右移一位相当于除以2, 右移n位相当于除以2n。
例:a=017时:a的值用二进制形式表示为00001111,舍弃低2位11:a>>2=00000011