指数形式
12.34e3 = 12.34x10^3 0.145E-25 = 0.145x10^-25 输出时用%e表示
13**3 = 2197 (13的3次方)
转义字符
\a 警告,通过扬声器发出一次警报声
\b 退格,光标向前移动一位,后继输出会覆盖后面的数据
\r 回车,把光标当前位置移动到本行的开头,后继输出会覆盖
\t 水平制表符,光标移动到下一个tab位置,后续覆盖
符号常量
也叫宏定义,注意最后没有分号。
#define PI 3.1415926
常变量
不能改变的变量,初始化时需要给其赋值,书上推荐使用常变量不用符号常量。
const int a = 3;
标识符
标识符为变量,函数,数组,类型等的统称,其定义时只能由数字,字母,下划线组成,而且首位必须由字母或下划线组成。
数据类型
下列是几种常见的数据类型关键字及其位数。c标准要求long不短于int类型,short类型不长于int类型。float数据类型能得到6位有效数字。在c语言中进行浮点运算时,会自动把float转换位double类型在计数。计算机在编译时会自动把带小数点的常量按照双精度浮点数处理,分配8个字节,当我们定义float类型时给了5位小数,编译器会警报,意思为把一个双精度的数赋值给单精度的变量会损失精度,但是我们可以在常量的后面加上f,此时表示此常量就是单精度的,赋值时不会报错,同理可以在单精度常量后面加上L,那么编译器会把单精度的常量作为long double类型处理。
int //整形根据计算机决定位数,一般为32位
short int //短整形16位
long int //长整型32位
long long int //双长整型64位
unsigned //无符号类型,一般搭配整型和浮点型使用
char //字符型8位
float //浮点型32位,小数点后4位 -3.4x10^-38 ~ 3.4x10^-38
double //双精度浮点型64位 小数点后8位 -1.7x10^-308 ~ 1.7x10^-308
enum //枚举类型
struct //结构体类型
union //共同体类型
float pi = 3.1415925f; //编译器会把其作为点精度处理,不会报错
long double a = 1.23L; //上述同理
volatile //禁止优化,一般用于地址操作
运算符
%的两侧都需要为整型才能运算。
循环
结束循环用break,中断本次循环用continue。
输入输出
输入双精度时需使用%lf的格式声明。在输出浮点型时可以在%后面紧跟一个浮点类型的常量,例如:%7.2f,表示为指定数据占7位,其中小数占两位,也可已不指定数据直接编写成%.2f,代表保留两位小数。在%后还可以加一个负号,表示位输出的数据向左对齐,例如:%-7.2f。输出格式附加字符:m代表一个正整数,数据最小宽度。n代表一个正整数,对实数表示输出n位小数,对字符串表示截取的字符个数。“-”输出的数字或字符在域内向左靠。如果要输出 '\n' 而不是要输出换行符时,需要用 '\\n' 来代替,编译器会自动处理成 '\n'。
//输出高位显0
printf("%d",1); //输出为 1
printf("%02d",1); //输出为 01
printf("%03d",1); //输出为 001
常见头文件
一些常见用到头文件,以及它们常用的函数。
#inclued <stdio.h>
gets(a); //输入字符串给a
#inclued <math.h>
b = aqrt(a) //把a开根号后赋值给b
b = abs(a) //把a的绝对值赋值给b,其类型为整型
b = fabs(a) //把a的绝对值赋值给b,其类型为双精度浮点型
字符串
在字符串类型的最末尾处有一个结束符'\0',使用%s输入时在输入完成后,最末尾处自动添加结束符,在输出时使用%s会把'\0'前面的内容输出。在使用字符串输入时用scanf函数不能有效的输入第一次空格后面的字符,scanf会把遇到的第一个空格检测为结束符,如需要输入带空格的字符串可以使用gets()函数。输入单个字符可以用getchar()函数,他没有输入,返回值就是输入的字符。另外还有getch()与getchar()的使用方法相同,但是没有输入显示,可以用来设计密码,上述的两种输入在输入一个字符串后自动运行后面的代码,与scanf不同需要输入enter的等待。
//字符串处理函数,需要加头文件string.h
pust(a); //输出字符串,a里面的内容以'\0'为结束位,只能输出一个字符串
gets(a); //输入字符串,a里面的内容以'\0'为结束位,只能输出一个字符串
c = strcat(a,b); //字符串拼接函数,把a和b的内容给c,需要保证c的长度足够
strcpy(a,b); //把b中的内容赋值到a中,a必须大于b
strcpy(a,"abd"); //b必须为字符串,b可以是字符常量
strncpy(a,b,n); //把b中前n个字符复制到a中去
strcmp(a,b); //字符串比较函数,将两个字符串按照从左到右按照ASCII的值进行比较,直到'\0'
strlen(a); //字符串长度测量,以'\0'为结束位,并不计算在内
strlwe(a); //将字符串中大写的字母转化为小写的字母,其他不改变
strupr(a); //将字符串中小写的字母转化为大写的字母,其他不改变
递归
函数调用自己本身,利用返回值结束调用,形成类似累加或循环程序。
函数参数传递时有形参和实参,他们的含义为分别为 实参:实际的数或者变量 形参:地址
变量影响范围
局部变量与全局变量,全局变量同一文件内生效,若函数内有同名的局部变量那优先选择局部变量进行运算。若想全局变量在同一工程不同文件内生效,则要编写外部变量声明。
int a; //不同文件中定义的全局变量
extern int a; //在外部变量声明后,就可以使用
extern a; //可以省略变量类型
//若想让变量只在本文件内生效即可如下定义
static int a; //静态外部变量
extern a; //此时程序会出错,a不能被外部变量声明
//函数定义也和变量相同,若在定义时加上 static 则定义的是静态函数,外部不可调用
void a() //定义外部函数
{
return;
}
extern void a(); //不同文件下声明后即可使用
static void a() //定义内部函数
{
return;
}
extern void a(); //此时程序会出错,a不能被外部函数声明
变量持续时间
自动变量与静态变量,所以默认定义的变量都为自动变量,持续时间为所定义的函数运行的时间,全局变量的持续时间为从工程开始到结束,静态变量的持续时间为从代码运行到定义处开始,持续到工程结束。
static int a; //静态变量定义格式
指针
*p++ 由于++与*的优先级是一样的,所以按照从右到左的顺序计算,所以等价与*(p++)。
指针数组的一些操作
//一维数组
int a[3];
int *b = a;
//a[1] 等价 b[1];
//*b++ 等价 *(b++)
//二维数组
int c[3][3];
int *d = c;
//c[1][1] 等价 d[1][1] 等价 *(*(d+1)+1) 等价 *(d[1] + 1);
//指向一维数组的指针与指针数组
int p;
/*数组指针可以理解为一个二维数组,其x轴的大小为3,y轴的大小由指针控制,分配好内存或起始地址后可以在有限的空间内自增*/
int (*p1)[3] //数组指针,指向一维数组的指针,一维数组的个数为3个
char *p2[3] = {"aaa","bbb","ccc"}; //指针数组
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
p1 = a;
p = *(p1+1); //*p = 4;
p = *p1+1; //*p = 2;
在while或for循环中可以写赋值运算表达式
//这是一个字符串复制函数,以字符串的结束符'\0'为循环结束判断
void copy_sting(char *from,char *to)
{
while((*to++ = *from++) != '\0');
}
//与上述while等价
for(;*to++ = *from;);
//由于'/0'在ASCLL中的数值等于0,上述的代码还能简化
while(*to++ = *from++);
for(;*to++ = *from++;);
指针函数
//用指针调用函数
int max(int x,int y); //获取最大值的函数声明
int (*p)(int int); //定义函数指针
int a,b,c;
c = (*p)(a,b); //*p两边的括号不可缺少
指向指针的指针
char *a[] = {"aaa","bbb","ccc"};
char **p;
p = a;
printf("%s",*p); //输出为:aaa
动态内存分配
//开辟动态存储区,返回值都为开辟内存的首地址,需要用到stdlib.h库
//size为需要开辟的字节数,一般用sizeof()计数数值
void *malloc(unsigned int size);
//在动态存储区中分配 n 个长度为 size 的连续空间
void *calloc(unsigned n,unsigned size);
//重新分配动态存储区函数,p 为内存首地址,大小改为 size ,如果分配不成功返回值为NULL
void *realloc(void *p,unsigned int size);
//释放开辟的内存,p为需要释放内存的首地址
void free(void *p);
结构体
//结构体编写格式,注意最后的分号不能缺少
struct 结构体名称
{成员列表};
//也可以不写结构体名称直接在后面写结构体变量
struct
{成员列表}test1;
//定义结构体变量
struct 结构体名称 test2;
结构体指针
struct temp
{
int a;
char b;
};
struct temp test;
struct temp *p;
p = &test;
//结构体与结构体指针的引用方式
temp.a = (*p).a = p->a;
链表
链表是一种常见的数据结构,可以根据需要,开辟内存单元。利用头指针定位地址,所以需要定义一个头指针,然后与结构体变量结合形成链表。
struct temp
{
int a;
struct temp *next;
};
//建立静态链表
struct temp a,b,c;
struct temp *head,*p;
head = p = &a;
a.next = %b;
b.next = %c;
c.next = NULL;
//利用指针的操作对链表的成员进行操作
p = p->next;
//建立动态链表
struct temp *head,*p;
head = p = malloc(sizeof(struct temp)); //建立链表的头
p->next = malloc(sizeof(struct temp)); //根据需求利用循环,建立需要的链表长度
p = p->next;
p->next = malloc(sizeof(struct temp));
p = p->next;
.
.
.
p->next = NULL; //链表最后的指针要指向空
共同体
定义一个新的变量,它可以储存几种不同的数据类型,其占用空间为最大BIT的数据类型,它与结构体不用,它只能存储一个数据(非数组字符串格式下)
//共同体定义格式,与结构体基本相同
union 共同体名称
{
成员列表
}变量列表;
union temp
{
int i;
char c;
};
//用共同体时要引用成员,要不然编译器不知道你所使用的那种变量类型
union temp a;
a.i = 97;
printf("%d %c",a.i,a.c); //输出的值为 97 a 因为在ASCLL中97号为小写字母a
//使用共同体赋值时也需要引用成员,同一种共同体可以直接赋值
union temp a,c;
int = b;
a = 1; //错误
b = a; //错误
a = c; //正确
枚举类型
枚举类型的作用是固定变量的取值,把变量可取的值都一一列出来,变量只能取列出的值。枚举元素列表默认为int类型,从0开始每个元素加1,同时也可以自己定义元素值,从自己定义的元素开始后面的元素默认加1。这个数值可进行基本的运算。
//定义枚举变量格式
enum 变量名称 {枚举元素列表};
//sun = 7,mon = 1,tie = 2,wed = 3,thu = 4,fri = 5,sat = 6
enum weekday {sun = 7,mon =1,tie,wed,thu,fri,sat};
weekday = sun; //枚举类型只能取枚举列表内的值
weekday = 7; //也可以用数字代替
weekday = 8; //非法,不用取未枚举的值
typedef 变量类型声明关键字
//重定义基本数据类型,注意最后有一个分号
typedef 基本类型 自定义名称; //基本类型是c语言中的变量类型
typedef unsigned int u_int;
typedef unsigned char u_cahr;
//还可以用typedef重定义结构体
typedef struct
{
结构体成员;
}变量名称;
typedef temp //这样就可以直接用test定义结构体变量,这样好像定义不了链表结构
{
int a;
char n;
}test;
test i;
文件操作
//文件类型指针,文件操作系统相关函数需要用到stdlib.h库
FILE *fp;
//打开数据文件
fopen(文件名称,使用文件格式); //返回值为文件格式指针,若失败则返回NULL,可以用exit(0)结束
fp = fopen("test.txt","r"); //注意要加双引号,文件使用方式在下列表格中查找
//关闭数据文件
fclose(文件指针); //关闭成功返回值为0,否则返回值为EOF(-1)
fclose(fp);
//单个字符读写文件函数
fgetc(文件指针); //读取文件内的单个字符,读取成功返回读取到的值,否则返回EOF
fputc(字符,文件指针); //把字符写入到文件指针所指的文件
//检测文件末尾标志是否被读取过
feof(文件指针) //若被读取过返回1,否则返回0
//字符串写入文件函数
fgets(str,n,fp); //从fp指向的文件读入一个长度为(n-1)的字符,存放到字符串数组str中
fputs(str,fp); //把str所指向的字符串写到文件指针fp所指向的文件中
//用格式化的方式读写文件
fprintf(文件指针,格式字符串,输出列表); fprintf(fp,"%d %f",a,b);
fscanf(文件指针,格式字符串,输入列表); fscanf(fp,"%d %f",&a,&b);
//用上述读写方式时由于输入输出需要平凡的转换为ASCLL,所在内存与磁盘频繁交换时使用fread与fwrite
//使用二进制向文件读写一组数据
fread(buffer,size,fp); //buffer用于存放文件读取的内容,size要读多少个字节
fwrite(buffer,size,fp); //buffer用于存放文件写入的内容,size要写多少个字节
在C语言中换行是用'\n',但是在windows系统中换行用'\r'和'\n',我们在编译的时候用非二进制打开文件时,编译器会自动转换,进行输入时也会自动转换,这就是使用文件格式带不带b的数据上的差异。
文件使用方式 | 含义 | 如果指定的文件不存在 |
r(只读) | 为了输入数据,打开一个已存在的文本文件 | 出错 |
w(只写) | 为了输出数据,打开一个文本文件 | 建立新文件 |
a(追加) | 向文本文件尾添加数据 | 出错 |
rb(只读) | 为了输入数据,打开一个 | 出错 |
wb(只写) | 为了输出数据,打开一个 | 建立新文件 |
ab(追加) | 向二进制文件尾添加数据 | 出错 |
“r十”(读写) | 为了读和写,打开一个文本文件 | 出错 |
“w+”(读写) | 为了读和写,建立一个新的文本文件 | 建立新文件 |
“a十”(读写) | 为了读和写,打开一个文本文件 | 出错 |
“rb+”(读写) | 为了读和写,打开一个二进制文件 | 出错 |
“wb+”(读写) | 为了读和写,建立一个新的二进制文件 | 建立新文件 |
“ab+”(读写) | 为读写打开一个二进制文件 | 出 |
文件位置标记
文件内容在被读写时,每读写一个字符或一个字符串后文件位置标记会自动向后移动,类似windows的光标,我们可以使用函数控制光标的位置。
//文件位置标记指向文件开头
rewind(fp); //没有返回值
//任意改变文件位置标记
//起始点为0表示为文件开始位置,1为文件当前位置,2为文件末尾位置
fseek(fp,位置量,起始点);
fseek(fp,100L,0); //从文件开头向后移动100个字节,L为long型,位置量可以为负数
//检测当前位置函数
ftell(fp); //返回值为当前位置,若调用失败返回 -1L
文件写入出错检测
//若返回值为0表示未出错,返回非0数表示出错
//对同一个文件每使用一次输入输出函数都会返回一个新的ferror函数值
ferror(fp);
//清除错误标志,使ferror的值为0,还可以对文件再次进行读写操作也可以进行清零操作
clererr(fp);