C语言整理
——谭大爷的书[精简版]
l 程序设计和C语言
1. main表示主函数,int表示类型,stdio是一个文件名,.h是头文件,#include指令把信息调用
2. 函数的组成:函数首部和函数体(声明部分与执行部分)
3. 编辑-编译-链接-执行
l 顺序结构
1. 指数的表示:12.34e3(12.34乘10的3次方),-346.87e-25,注意e或E前必须有数字,后面必须是整数
2. 符号常量:指定一个符号代表一个常量,#define PI 3.1416
3. 转义字符:由\与字符值两部分组成
转义字符 |
意义 |
ASCII码值(十进制) |
\a |
警告(alert),产生声音或视觉信息 |
007 |
\b |
退格(BS) ,跳到前一列 |
008 |
\f |
换页(FF),跳到下页开头(会影响打印机执行) |
012 |
\n |
回车换行(LF) ,跳到下一行开头 |
010 |
\r |
回车(CR) ,跳到本行开头 |
013 |
\t |
水平制表(HT) ,跳到下一个TAB位置 |
009 |
\v |
垂直制表(VT),跳到下一个垂直制表对齐点(会影响打印机执行) |
011 |
\\ |
输出一个反斜线 |
092 |
\' |
输出一个单引号 |
039 |
\" |
输出一个双引号 |
034 |
\? |
输出一个问号 |
063 |
\0 |
空字符 |
000 |
\ooo |
三个位置组成的八进制数,来表示任意字符 |
三位八进制 |
\xhh |
x后面的字符是十六进制数,来表示任意字符 |
二位十六进制 |
4. 数据类型:
基本数据类型 short(2字节)、int(4)、long(4)、char(1)、float(4)、double(8)
空类型(void)
指针类型(只能存地址)
构造类型 数组、结构体、共用体(union)、枚举(enum)
5. 运算符:%取余,++i使用前先加一,i++使用后再加一
6. 不同类型数据间的混合运算:
先转换成同一类型,再进行运算。
可强制转换,例如:a=(int)(x+y) 强制转换为整型等。
7. 格式控制符:
%d,按整型数据的实际长度输出。
%md,m为指定的输出字段的宽度。
%ld,输出长整形数据。
%o,以八进制整形式输出整数。
%x,以十六进制数形式输出整数。
%u,用来输出unsigned无符号整型,输入范围为正数,以十进制形式输出。
%c,用来输出一个字符。
%s,用来输出一个字符串。
%f,用来输出实数(包括单双精度),以小数形式输出。
%e,以指数形式输出实数。
%g,用来输出实数,它根据数值的大小,自动选f格式或e格式(选择输出是占宽度较
小的一种),且不输出无意义的零。
%p,用于变量地址的输出。
scanf(“%[^\n]”,str); //遇到回车结束。
%%,输出一个“%”。
**,表示幂次,比如a的三次方可表示为:a**3 。
printf("c=%#x\n",c);(ox)十六进制 printf("c=%#d\n",c);十进制 printf("c=%#o\n",c);
(o)八进制
注意:%-m.nd等的含义与使用方式。
8. C语言运算符:
(1)逻辑运算符: !(非)、&&(且)、||(或)
(2)位运算符: <<(左移,例:a<<1 左移一位,结果为a*2 )、>>(右移,右移的位
数舍弃,左补空位)、~(按位求反)、|(按位或)、^(按位异或)、&(按位
与)
(3)条件运算符: ?:(例如:max = (a>b) ? a : b ) 相较于if else要简单的多;具有
结右性。
(4)逗号运算符:从左向右运算,值为最后一位。例如:a=(x+3,y++,x++) 这里a的值
为x++
(5)指针运算符:“&”是取操作对象的地址,“*”是取指针指向的对象的内容,两
者互为逆运算。&(*p) = p 表示指针,*(&x)= x 表示变量x
例:int x , *p ;
p = &x ;
(6)求字节数运算符:sizeof 例:int len = sizeof(a)
(7)成员运算符:. 和 -> (指针)
9. C语句:
控制语句If( )...else... \for( )...\while( )...\do...while( );\continue结束本次循环\break强制
结束\switch\return\goto很少用。
函数调用语句;表达式语句:i=3;空语句;复合语句{ };
10. 有关数据的输入输出:
输入 输出
字符 getchar putchar 可以:putchar(getchar(a));
格式 scanf printf
字符串 gets() puts()
l 选择结构
1. 算数运算符(+ - * /) (高)
关系运算符(>=、<=、==等)
赋值运算符(=) (低)
2. switch多分支选择语句:
Switch(表达式) //表达式的类型:整数类型(包括字符型)
{
case 常量:语句;break;//可以有多个case,表达式和常量相同时执行
. . .
default: 语句;//只能有一个default
}
3. 逻辑变量的使用:提高可读性、减少出错。
#include
bool leap;
leap=ture;或者leap=false;
l 循环结构
1. 用break语句提前终止循环(只能用于以下两种情况):
结束switch语句;跳出循环体,进入循环体下面的语句;
2. 用continue语句提前结束本次循环:接着执行下一次循环。
l 数组
1. 一维数组:类型符 数组名 [常量表达式]
注意:常量表达式要为一个定量;不合法:static int a[a*n];
易出错的地方:循环赋值;初始化;
2. 排序问题:
(1)折半法(2)起(冒)泡法(3)选择法
3. 二维数组:类型符 数组名 [常量表达式][常量表达式]
初始化:可部分初始化,例如:int a[3][4]={{1},{5},{9}};这里的第一竖列为159,其他为0
4. 字符数组:char c[10]或char c[5][5],必须要初始化哟!
l 函数
1. 处理字符串的函数:
(1)字符串连接函数 strcat: strcat(字符数组名1,字符数组名2)
功能:把字符数组2中的字符串连接到字符数组1 中字符串的后面,并删去字符
串1后的串标志“\0”。本函数返回值是字符数组1的首地址。
注意:字符数组1应定义足够的长度
(2)字符串拷贝函数strcpy: strcpy(字符数组名1,字符数组名2)
功能:把字符数组2中的字符串拷贝到字符数组1中。串结束标志“\0”也一同
拷贝。
(3)字符串比较函数strcmp: strcmp(字符数组名1,字符数组名2)
功能:按照ASCII码顺序比较两个数组中的字符串,并由函数返回值返回比较结
果。
字符串1=字符串2,返回值=0;
字符串1〉字符串2,返回值〉0;
字符串1〈字符串2,返回值〈0。
(4)测字符串长度函数strlen:
功能:测字符串的实际长度(不含字符串结束标志‘\0’)
(5)大写字母换为小写strlwr( )
(6)小写换大写strupr( )
熟悉常用数学函数!!
2. 若定义函数在main函数后面:应当在main函数前或main函数开头部分,对函数进行
声明,之后才能调用。
3. 所有函数都是平行的,不能嵌套定义。
4. 按函数的形式看,分为两类:
(1)无参函数:例如,
Int main( )
{
Void printf_star( );
Printf_star( );
}
Void printf_star( )
{
Printf(“*********\n”);
}
(2)有参函数:例如,
Int max(int x,int y)
{
Int z;
z=x>y?x:y;
Return(z);
}
最后max的值为z
5. 实参与形参的类型应相同或赋值兼容(书上有解释P177)
6. 函数声明格式:
(1)函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2,......);
(2)函数类型 函数名(参数类型1,参数类型2,.......);//显得更加精炼
7. 嵌套调用函数:例如,可以在第一个子函数里声明、调用一个新的函数,然后在第一个
子函数后面定义这个新的函数,从而实现嵌套调用。
8. 函数的递归调用:类似于一个算式的逆过程(只明确的知道其中的一项值),并且要用
到if...else...来帮助结束递归,得到最终值。
9. 数组作为函数参数:
(1)数组元素作为函数实参
(2)数组名作为函数实参:向形参(数组名或指针变量)传递的是数组首元素的地址。
例如,
int main()
{
int aver(int array[10]);//声明函数,形参数组可以不定义大小,int array[]
int a[10],i,average;
for(i=0;i<10;i++);
scanf(“%d”,&a[i]);
average=aver(a);
printf(“%d\n”,average);
return 0;
}
int aver(int array[10])//可写作int aver(int array[])
{
int i,sum=array[0];
for(i=1;i<10;i++)
sum+=array[i];
aver=sum/10;
return(aver);
}
(3)多维数组名作函数参数:定义形参时可以指定每一维的大小,也可以省略第一维
的大小。
10. 变量的存储方式:
(1)静态存储:外部变量(全局变量)、静态外部变量、静态局部变量
(2)动态存储:函数的形参、定义的没有用关键字static(静态)声明的变量,即自动
变量、函数调用时的现场保护和返回地址等。
11. 局部变量的存储类别:
(1) 自动(auto)变量:函数中的形参和在函数中定义的局部变量(包括在复合语
中定义的局部变量)例如,auto int b;//auto可省略不写,属于动态存储方式。
(2) 静态局部变量(static局部变量):函数中的局部变量的值在函数调用结束后不消
失而继续保持原值(占用的存储单元不释放),在下次调用函数时,该变量已有
值了。P206的例子很不错~
注:定义局部变量时,若不赋初值,静态局部变量编译时会自动赋初值为0或’\0’;
自动变量的值则是不确定的,因为每次函数调用结束后存储单元会释放,然后下
次重新分配。
(3) 寄存器(register)变量:一些变量需要频繁使用,为提高执行效率,允许将局部
变量的值放在CPU的寄存器中,需要时直接从寄存器取出参加运算。
注:一般变量的使用是这样的,当然比较慢:由控制器发出指令将内存中该变量的值
送到运算器中。运算完了,如果需要存数,再从运算器将数据送到存储器中存放。
(4) 外部extern:用于扩展全局变量的作用域,比如如果函数想引用一个外部变量,
但该外部变量在该函数后定义,那么这个函数需要使用 extern 来声明变量,这
样才能使用在该函数后面定义的全局变量。此外,extern 还可以在多文件的程序
中声明外部变量。可写作extern int A;或者extern A;
l 指针
1. 指针的认识:房号象征“地址”,房客象征“内存单元里存放的数据”。地址指向变量单元,而“地 址”也被形象化的称为“指针”。指针是一个地址,指针变量是存放地址的变量。
2. 直接访问:用A钥匙开A抽屉。
间接访问:用B钥匙打开B抽屉,取出B中的A钥匙,用A钥匙打开A抽屉。
3. 指针变量的值是地址,例如,i_pointer(是指针变量)=&i ; i=3 ; 所以 *i_pointer=3 ;
// “*”表示指向
4. 定义指针变量:类型名 *指针变量名
int *a,指针变量a读作“a是指向整型数据的指针变量”,int *读作“指向int的指针”
5. 指针变量作为函数参数:
例如,int main()
{
int swap(int *p1,int *p2);
swap(p1,p2);//注意这里是将指针变量(内存放的地址)作为实参来传递的;
}
void swap(int *p1,int *p2)
{
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;//通过指针从而实现了指针指向的值的交换,因为函数结束后会释放
};
注意:若是在子函数里,通过交换p1、p2指针变量存的地址,是不能交换指向的值的。
6. int *fun(); 是返回一个指针的函数、int (*fun)( ); 是指向函数的指针、int *array[n]; 是数 组、int (*array)[n]; 是指向一维数组的指针。
7. 数组元素的指针:就是数组元素的地址。
int *p ; p=&a[0] ; 或 p=a ; 数组名不代表整个数组,只代表数组首元素的地址。
8. p+1,直接增加一个位置。
9. 指向函数的指针:int (*p)(int int); p=max; c=(*p)(a,b); 外面一个子函数int max(int x,int y){ }
10. 返回指针值的函数: float *search(float (* pointer)[4],int n)
{
float *pt;
return(pt);
}
11. 指针数组:一个数组里的元素全为指针。int *p[4];
区别:int(*p)[4] ; 指针p指向一个含有4个元素的数组;
l 动态内存分配与指向它的指针变量
#include
1. 使用malloc函数。格式: void *malloc(unsigned int size);
Malloc(100); //开辟一个100字节的临时分配域,函数值为第一个字节的地址。如果执
行失败则返回NULL。 例如:p=(int *)malloc(5*sizeof(int));开5个空间的整型指针。
2. 动态数组: void *calloc(unsigned n,unsigned size); 分配n个size大小的空间,以保持一个 数组。 例如:P=calloc(50,4);
3. free函数,释放空间;
4. 改变malloc或calloc已获得的空间大小:realloc函数,void *realloc(void *p,unsigned int size); 例,使用 时,realloc(p,50);
l 建立数据类型
一、结构体
1. 结构体:struct Student
{
Int num; int age; char name[20]; char sex;
}; < - - 千万注意这个分号。
2. 定义结构体,有3种方法:
(1) struct Student student1,student2;
(结构体类型名) (结构体变量名)
(2) 同时定义: struct Student
{
}student1,student2;
(3) 不常用,不指定类型名:struct
{
}student1,student2;
注意:结构体变量使用前要初始化。要引用的话,加个“.”就行了。
3. 结构体数组:struct Student { }stu[4]; 即定义了4个学生;
4. 结构体指针:
( 1 ) struct Student{ };
struct Student stu1;
struct Student *p; //注意这一步
p=&stu1;
这样后面的stu1.num 可以用 (*p).num 或者p->num替换。
( 2 ) 如果是指针数组呢?
还是定义 struct Student *p; 后面就可以用到for循环了:
for(p=stu ; p)
二、链表
1. 建立静态链表:
struct Student
{
struct Student *next;
};
int main()
{
struct Student a,b,c,*head;
head=&a;
a. next=&b;
b. next=&c;
c. next=NULL;
}
2. 建立动态链表:
//抄了书上一个程序,自己体会。
#include
#include
#define LEN sizeof(struct Student)
struct Student
{
long num;
float score;
struct Student *next;
};
int n;
strucr Student *creat() //建立链表的函数
{
struct Student *head;
struct Student *p1,*p2;
n=0;
p1=p2=(struct Student *)malloc(LEN);
scanf(“%ld,%f” , &p1->num,&p1->score);
head=NULL;
while(p1->num!=0)
{
n=n+1;
if(n==1)head=p1;
elae p2->next =p1;
p2=p1;
p1=(struct Student *)malloc(LEN);
scanf(“%ld,%f” , &p1->num,&p1->score);
}
p2->next=NULL;
return(head);
}
void print(struct Student head)
{
struct Student *p;
printf(“\nNow,These %d record are:\n”,n);
p=head;
if(head!=NULL)
do
{
printf(“%ld,%5.1f\n”,p->num,p->score);
p=p->next;
}while(p!=NULL);
}
void main()
{
struct Student *head;
head=creat();
printf(head);
}
三、共用体
1. 用同一段内存单元存放不同类型的变量。
union data //data是共用体名
{
int i;
char ch;
float f;
};
定义方式和结构体相似,但是共用体变量只能存放一个值,存在覆盖现象。
四、枚举类型
1. 声明:enum Weekday{ sum,mon,tue,......};
也可作 enum { }Weekday;
2. 定义:enum Weekday workday,weekend;
类型名 变量名
Weekday=num;
五、typedef声明新类型名
1. 用新的代替原有的:typedef int Integer;
2. 偷懒1号。typedef struct
{
}Student;
Student stu1,stu2;
偷懒2号。typedef int array[100];
array a; //a为整型数组名,有100个元素。
反正其他情况都可以用。
l 文件的输入输出
wei wan dai xu ... ...