C语言入门:
第六章:
1. C语言调用函数,永远只能传值。每个函数拥有自己的变量空间,参数也位于这个独立的空间中,和其他函数没有关系;
2. 形参和实参(旧称呼),参数和值(和前面对应);
3. 生存期、作用域
4. 本地变量的规则:6-3-3
5. 一般来说,对于main函数,return 0代表运行正常,return非0的数表示错误。
6. 函数原型=函数声明=引用声明
7. 二维数组列数不可省略,如:int a[][3]={{0,0,0,{0,0,0},{0,0,0};
第七章:
1. 结构体,搜索-第三个视频,二分查找,时间复杂度log2^n
2. 选择排序,选择最大的放到最前或者最后。
第八章:
1. sizeof(),给出在内存中占据的字节数;
2. &,运算符,获得变量的地址,地址的大小是否与int相同取决于编译器;
3. 指针,在定义时,int *p 和 int* p 相同,此时,*p在一起;在使用时,int *p=&i或者p=&i;
4. 注意:作为参数的指针的形式。例如:定义函数void sum(int *p);调用函数sum(&i);
5. *是一个单目运算符,用来访问指针的值所表示的那个地址上的变量;
6. 数组变量是一个const的指针,不能被赋值
7. 8-2-1视频,scanf()中带空格和不带空格,情况是不同的;
8-2-2视频,逃逸字符,用来表达无法印出来的控制字符或者特殊字符,用\开头后面跟字符表示
8. 字符串常量和字符串变量;
C语言的字符串是以字符数组的形态存在的。
9. 字符串:
Char *s = "Hello,world" 指针形式;字符串不知道存在哪里,只读模式,一般用于处理参数、动态分配空间;
char s[] = "Hello, world" 数组形式;字符串就在这里,可以作为本地变量,可以更改;
因此,总体来说,如果用于构造一个字符串,用数组;
如果用于处理一个字符串,用指针。
10. scanf("%s"),读的是单词,到空格、tab、回车为止。
C语言进阶:
第一章:
1. 指针常见错误:定义了指针变量,还没有指向任何变量就开始使用指针;
2. 传入函数的数组,函数参数表中的数组实际上是指针,指向该数组的首地址,但是可以用[]进行运算;
3. ”const 指针“,如:int *const p,表示该指针一旦得到了某个变量的地址,不能再指向其他地址;
"所指是const",如:const int *p,表示不能通过这个指针去修改那个变量;视频1-1-3
4. *p++,取出p所指的数据,并将p移到下一个位置;
5. 0地址,0地址通常不能随便碰。NULL表示0地址;
6. 指针的类型转换,例如:int *p=&i; void *q=(void*)p; 并没有改变p所指变量的类型,而是用不同的眼光通过p看其所指的变量;
7. 动态内存分配:
头文件#include<stdlib.h>,例如:int *a=(int*)malloc(n*sizeof(int));malloc返回类型是void*,等式右边int*是类型转换;malloc申请的空间大小以字节为单位;申请后,用完要free()释放掉;
如果分配失败,则返回NULL,即0;
8. int putchar(int c);
int getchar(void);
9. 字符串函数的实现:
size_t strlen(const char *s);const说明对s不会改变;
int strcmp(const char *s1,const char *s2);
...还有几个函数
第二章:结构类型
1. 枚举,是一种用户定义的数据类型,关键字enum; enum 枚举类型名字 {名字0,...},值从0开始自动递增;也可以指定值;
2. 声明结构类型,和本地变量一样,可以在函数内部和外部声明结构,效果也一样;
形式1: struct point{int x; int y; };//声明结构类型 struct point p1,p2;//定义结构变量 p1和p2都是point,里面有x和y;
形式2: struct {int x; int y; }p1,p2; p1和p2都是无名结构,里面有x和y;
形式3: struct point{int x; int y;} p1,p2; 和形式1一样,同时做了两件事,声明结构体和定义结构体类型p1,p2;
3. 结构的初始化
形式1: struct point p1={0,1};
形式2: struct point p1={.x=0,.y=1};
4. 结构指针
和数组不同,结构变量的名字并不是结构变量的地址,因此要获取结构变量的地址需要用到&运算符,例如:struct point *pDate = &today;
5. 结构作为参数
(1). 结构体作为参数,如果不用指针,传的是值,将值传给了一个类型一样的克隆体;
(2). 结构指针作为参数;
6. 指向结构体的指针,如:struct date{int month; int day;} mayday;//声明结构体, struct date *p = &myday; //声明结构体指针
两种取值方式:(1)(*p).month. (2) p->month. 视频3-2-2
7. 结构体数组
8. 结构中的结构
9. 自定义数据类型,C语言提供了一个叫做typedef的功能来声明一个已有数据类型的新名字;如:typedef int Length,length就是int的别名。
typedef struct ADate{ //struct ADate是原来的名字
...
}Date; //Date是新名字
10. 联合,Union
存储:(1)所有的成员共享一个空间;(2)同一时间只有一个成员是有效的;(3)union的大小是其最大成员的大小
第四章(*):链表
1. 可变数组,视频4-1-1
例子:typedef struct {int *array; int size;} Array;
声明了一个结构体,结构体中有一个指向int的指针和一个表示大小的int,后之后对array进行malloc(Array a; a.array = (int*) malloc(sizeof(int)*a.size) ,表示array指向的那块地址保存size大小的int数
2. 根据视频和PPT-可变数组,理清楚技术要点和思路!
free(p)是释放p指向的这段内存空间,释放后p值不变仍然指向这段内存,但是这段内存已经无效,不能被使用;free() 只能释放动态分配的内存空间,并不能释放任意的内存。
3. 链表(linked list),可变数组具有每次增长都需”拷贝数据“和内存持续申请则连续内存不够的缺陷,因此,引申出链表;
第五章: 程序结构
1. 全局变量 定义在函数外面的变量是全局变量:
(1)没有做初始化的-全局变量会得到0值、指针会得到NULL值;
(2) 只能用编译时刻已知的值来初始化全局变量;
(3)如果函数内部存在与全局变量同名的变量,则全局变量会被隐藏;
(4)全局变量具有全局生存期和全局作用域。
2. 静态本地变量 在本地变量(函数内)定义时加上static修饰符,就成为了静态本地全局变量:
(1)当函数离开时,静态本地变量会继续存在并保持其值;
(2)静态本地变量的初始化只会在第一次进入这个函数时做,以后进入函数会保持上次离开时的值;
(3)静态本地变量实质上是特殊的全局变量,静态本地变量和全局变量在相同的内存区域;(4)静态本地变量具有全局的生存期,但是由于它位于函数内,所以其作用域是局部的。
3. *返回指针的函数 (1)返回本地变量的地址是很危险的,因为函数执行完毕后,本地变量地址会被回收分配给别的变量使用,这时候返回的地址变得不可控了;
(2)返回全局变量或静态本地变量的地址是安全的;
(3)返回在函数内malloc的内存是安全的,但是容易造成问题(思考);
(4)最好的做法是返回传入的指针(思考)!
注意:(1)不要使用全局变量在函数间传递参数和结果;(2)使用全局变量和静态本地变量是线程不安全的;
4. 编译预处理和宏
(1)#开头的是编译预处理指令;
(2)宏定义 (2-1)有值的宏 例如:#define PI 3.14 (没有;) 需要宏定义多行语句时,需要在每个语句后加\; 例如:#define PRAT printf("\n");\ printf("%d",a)
(2-2)没有值的宏 例如:#define _DEBUG 这类宏用于条件编译,后面有其他的编译预处理指令来检查这个宏是否已经被定义过了;
(3)预定义宏
5. 带参数的宏
6. 大程序结构 构建项目
(1)一个.c文件叫做一个编译单元,编译器每次编译只处理一个编译单元;
(2)#include是一个预编译处理指令,与宏一样,在编译前处理,它把那个文件的所有文本原封不动的插入到它所在的位置;#include ""在当前目录寻找,<>在指定目录,标准库去寻找;
(3)int i;是变量的定义 extern int i;是变量的声明;
(4)标准头文件结构;
第六章 交互图形设计
本章重点掌握函数指针及其应用 视频6-2-1,6-2-2
例如:void f() { ... }; //定一个函数
void (*pf)() = f; //定义一个指向void类型的f函数的指针(*pf) // if else/switch 也能做
(*pf)(); //调用f函数
第七章 文件
1. 文件根据文件的存储形式可以分为:二进制文件和文本文件(ASCII码文件或Unicode文件);
ASCII码文件由一个个字符组成,每个字符由一个ASCII代码表示;二进制文件是以数据在内存中的存储形式原样输出存储在磁盘上的文件;
2. 文件操作函数
(1)格式化输入与输出:printf的使用格式,scanf的使用格式;printf和scanf有返回值,分别是输入个数和输出个数;
(2)文件的打开和关闭
(2.1)文件打开函数fopen():
打开文件的标准代码:
FILE *fp; //FILE实际上是一个结构体类型,文件的信息保存在该结构体中,fp是一个指向内存中文件缓冲区的指针,通过该指针实现对文件的操作
fp = fopen("file路径","r");
if(fp) { //如果打开失败,fp = NULL,所以可以判断
fscanf(fp,...);
flose(fp);
}
else {
...
}
fopen("文件路径","r(方式)"),函数中"方式"-参数意义:
r 打开只读(文本文件)
r+ 打开读写,从文件头开始(文本文件)
w 打开只写。如果不存在,则新建一个;如果存在,则清空文件
w+ 打开读写。如果不存在,则新建一个;如果存在,则清空文件
a 打开追加,如果不存在,则新建一个;如果存在,则从文件尾开始
rb
rb+ //加上了"b",文件是二进制文件,其余不变
wb
wb+
..x 只新建,如果文件已存在,则无法打开
每一个与主机相连的输入输出设备都可以看作是一个文件,stdin;标准输入,一般指键盘;stdout:标准输出,一般指屏幕/打印机;stderr:标准出错输出,一般指屏幕/打印机
(2.2) 文件关闭函数fclose():
fclose(fp);
(3) 文件的操作
(3.1) 字符读写函数:
fgetc(); 原型:int fgetc( FILE *fp )
例如:char ch; ch = fgetc(fp); //从fp指向的文件中读取一个字符并传回字符变量c中。该函数以无符号 char 强制转换为 int 的形式返回读取的字符。思考:fgetc()返回类型为int,为什么ch为定义为char型呢?char 可以用int 表示。
fgetc()可以不向字符变量赋值,但是读出的结果不能保存;读完之后自动后移一位,当读写至文件末尾或者执行出错,返回EOF(-1);
fputc(); 原型:int fputc(char ch, FILE *fp)
例如:fputc(ch,fp); 将字符变量ch的值写入fp指向的文件中并返回写入成功的那个字符的值,若写入失败返回EOF;
(3.2) 字符串读写函数:
fgets(); 原型:char *fgets(char *buff,int n,FILE *fp )
例如:char str[]; fgets(str,n,fp); //从fp所指的文件中读出n-1个字符送入字符数组str中
在读出n-1个字符之前,如遇到了换行符或EOF,则读出结束。fgets()函数的返回值是字符数组的首地址,若文件结束或出错,返回NULL
fputs(); 原型:int fputs( char *str, FILE *fp ); //把字符数组str的内容写入fp所指的文件中
例如:fputs(str,fp); 执行成功返回0,失败返回EOF(-1)
(3.3) 读写数据块的函数:
fread(): 原型:int fread( char *buffer, int size, int count, FILE *fp) //buffer:存放读/写数据的起始地址;size:数据块的字节数;
fwrite(): 原型:int fwrite( char *buffer, int size, int count, FILE *fp) //count: 读/写数据块的块数;fp: 文件指针;
//函数调用成功,返回count的值
实例:fread(fa, 4, 5, fp); //从fp所指的文件中,每次读4个字节(一个实数)送入fa所指的空间中,连续读5次,即读5个实数到fa所指空间中
fwrite(fa, 4, 5, fp); //从fa所指的空间中,每次输出4个字节(一个实数)的内容到fp所指的文件中,连续写5次,即写5个实数到fp所指文件中
(3.4) 格式化读写函数: 格式化读写函数是按照格式字符串规定格式来读文件和写文件,它们的功能类似于scanf和printf。前两者操作对象是文件,后两者操作对象是键盘和屏幕
fscanf(): 原型:fscanf(文件指针,格式字符串,输入地址表列) //一般用法是将文件中的内容读出来,若读取成功,则返回匹配成功的个数;读到文件末尾返回EOF
fprintf(): 原型:fprintf(文件指针,格式字符串,输出表列) //一般用法是将内容往文件里面写
(3.5) freopen()可以重定向输入输出流,可以从指定文件读,并把读取的数据输出到指定文件中;
freopen(): 原型:FILE *freopen(const char *filename, const char *mode, FILE *stream) //例如:FILE *fp = freopen(fp,"w",stdin);
stream,指向FILE对象的指针,该 FILE 对象标识了要被重新打开的流,包括stdin/stdout;
(3)二进制文件
二进制文件读写,fread()、fwrite()
二进制文件不可跨平台,文本文件(即,ASCII码文件)可以跨平台;
3. 位运算(与逻辑运算区分开)
逻辑运算,它只看到两个值0和1;
按位运算,把所有非零值全变为1;
(1) 按位(bit)与: &, 都为1,才为1;
按位或: |,有一个1,就为1;
按位取反: ~,把0变1,把1变0;
按位异或: ^, 两位相等则为0,不等则为1;
按位左移: <<,例如:i << j,i中所有的位向左移动j个位置,右边填入0;
按位右移: >>,和符号有关
...