函数
函数定义:理解为封装功能的容器
函数定义的基本格式:
返回值类型 函数名(形参列表)
{
函数体;
}
返回值类型:常用基本数据类型
ps:函数执行完之后,函数会得到一个什么类型的值,如果需要返回一个值出去,那么返回值类型这里,通过return把值返回出去,一般return写在函数的末尾;如果不需要返回一个值出去,那么就在返回值类型这里用void。
void表示空类型
形参列表:形式参考的变量,在调用这个函数的时候,需要用到什么数据,就可以用形参来表示。
实参列表:有实际参考的值
eg:
void Two()
{
}
就可以不用return。
案例:九九乘法表
函数的调用:
把自定义的函数,放到主函数里面,直接写函数名就可以了。
实例:函数的调用和传参
局部变量:作用域在一定的区域内才能被使用的变量,出了自己的作用域会被释放掉。
全局变量:从定义开始往下,所有的地方都可以使用,在程序结束时被释放。
注意:局部变量跟全局变量是可以同名的,使用这个同名变量的时候,使用的是最近的一个(就近原则,从printf前面看离它最近的)
静态变量:在程序执行后定义,生命周期是程序结束后死亡,只会被定义一次,不会被重复定义
eg:
对比非静态变量:
函数的声明:先说明函数
格式:类型说明符 函数名(实参);
没有花括号。
有花括号,函数必须定义了才能调用。
ps:可以在文件头那里先申明函数,然后主函数里调用函数,最后在主函数外面定义函数,这也是可以的。
#include <stdio.h>
void Fun();
int main()
{
Fun();
return 0;
}
void Fun()
{
}
址传递
地址:在定义变量、数组、函数等等,系统会给他们分配内存区域(地址),把这个数据放到这个地址上面。
&:取地址符
eg:&a,得到a的地址编号
* : 定义指针变量的一个标志,并且可以解引用,取内容
指针变量:存储地址的变量
eg:int *d=地址; 代表d是一个指针变量,指针变量可以存地址
址传递实例:
ps:int *d 中 *作用是定义指针变量
printf里面的 *d 是指取d这个地址里面的内容,主函数里d地址赋值为&a,所以取得是a地址的内容,故为10.
eg:
代码解释:先运行主函数里的内容,x赋值为10,然后调用函数fun1,传递了x的地址进去,运行fun1函数,输出的是x地址里存的内容,即10;然后*p1=1000,更改的是x地址里的值为1000,所以主函数里输出x是,值变为了1000.
数组调用:
函数递归
定义:在一个函数中,重复调用自己本身。(自己调用自己)
eg:(不懂)详见25:00 他会先把函数调用执行完,再输出,然后又倒回去输出,终归要把未执行完的语句执行完
eg2:(不懂)
实例:递归逆向输出一个数
输出4321
斐波那契数列:1 1 2 3 5 8 13 21.... 第n个元素的值=第n-1个元素的值+第n-2个元素的值
求第35个位置的元素的值: (35以上就打印不出来了,太大了)
实例:递归输出10到1
预处理
预定义符号
定义:预先定义好的符号,代表某种意思,可以直接使用
ps:必须要大写,不能小写!!
宏定义
宏定义的本质就是替换。
无参宏
ps:#要有
实例:
如果想打印五行五列,就直接改宏就行,#define row 5 define col 5
带参宏
格式:#define 宏名(参数列表)
带参宏类似于一个函数,带参宏的参数是没有类型的,带参宏没有返回值。
实例:
注意:先替换在运算!
输出结果为6.
输出结果为5.
常量的定义
格式:const int a=10;
ps:常量必须要初始化,定义为常量后就不能再更改了。不然会报错。
文件包含
ifndef:如果没有定义
define :定义
endif:与ifndef配套使用
在头文件中申明函数,相当于一个功能。
可以自定义一个头文件在里面写函数,这样在源文件中写上自定义的头文件就可以直接调用这个函数。详见41:00
条件编译
实例:
判断的是运算符
if 1>2,则会输出else下面的语句。
这里判断的是宏
文件操作
操作数据文件:
第一件事,打开文件:通过定义文件指针指向文件
文件指针的定义:FILE*名字 ;
第二件事:用文件指针指向文件,用 fopen(“文件路径\文件名”,“打开方式”);
文件路径:绝对路径 相对路径
这里用的是绝对路径,后面还要加个\1.text
相对路径
ps:如果用w写文件,它有个特点,如果该文件存在,那么它会清空这个文件的内容再进行写入。
第三件事:文件操作,通过函数对文件中的数据进行操作
先判断文件是否打开成功:
往文件中写入一个字符:
换行 \n 也是用 fputc
也可以写数字,因为数字通过ASC码表可以转成对应的字符
往文件中写入一个字符串:
或者用数组写:
读取文件里的单个字符:
它会按照文件里的字符一个一个读取,这里有三个printf,那么就只会读取出文件中的前三个字符。
读取字符串:也是利用数组的方式,把文件里的字符串读取到自定义的数组里
char str[1024]={0}; 解释:
char 是定义的数组类型,str是数组名,【1024】是数组大小,可以存多少,{0}是给它初始化赋值。
fgets(数组名,读取文件里的几个字符,文件名)
为啥只读取了两个字符:
每个字符串后面都有个 \0,会占一个字符
读取整个文件:
while这个函数判断文件指针是否读到了末尾,若读到了末尾就返回一个真值,否则返回一个假。
第四件事:用完记得关闭文件
顺序读写文件
写:
读:
fscanf(file1, "%d\t%s\n", &a, str1 ); //读取
printf("%d\t%s\n", a, str1); //输出
以二进制的形式读写文件
ps:由于是二进制写的,所以在文件中是看不到的
读:
读取图片
fseek函数用于改变文件的读写位置指针
输出结果是:图片的大小(会有个\0占一个字符)
能读能写(覆盖)
原来是12346500,运行结果变成123A6500,解释:
fseek()函数让指针指在4那里,然后又执行fputc()函数,在4那里输入A,那么4就会被A替换掉。(覆盖)
自定义数据类型
结构体
结构体的定义:struct
每一个成员只能存一个变量,一个变量只能存一个数据
实例:
ps:name是用char类型的数组来存的。一 一对应赋值
怎么访问定义的结构体变量里面的成员:用 变量名.成员
不能这样进行初始化,只能按照上面那样
除非用 strcpy(aa.name,"张三"); 就可以,记得导入头文件 #include<string.h>
typedef 给类型取别名
eg:typedef int 整型;
给结构取别名: 给Hero这个结构名取别名为hero
赋值:
(输出全部的)
定义结构体的时候没有写结构名,那么typedef给这个结构体取名
eg:这个结构体就叫STT。
结构体的嵌套
访问成员b:
结构体的内存计算方法
sizeof()求内存大小
自己算的是:4+4+1=9(int占4个字节,char1个字节),结果输出是12
为什么呢?
内存对齐标准:以该结构体中最大的基本数据类型所占的内存进行对齐
这个字节大小为20
注意:
这个是24个字节:double8个字节,然后存b为了对齐也是分配八个字节,其中四个存b,还有四个是空的,那么这时候这四个空字节用去存c,此时c只剩6个字节,那么再分配一个8字节就行,所以一共三个八字节的内存,一共为24.
ps2:
先按照int类型4字节对齐,然后看到更大的double,最后再按照八字节补齐:
所以是4*8=32个字节 详细见39:00
共用体
内存存储:共用体所有的成员共用里面最大的成员空间,在同一个时刻只能存一个成员的值。
只算最大的成员所占的内存,但是要以共用体中最大的基本数据类型所占内存进行对齐。
图上所示为12个字节:最大成员所占内存是10,但是最大数据类型所占字节是4,那么就要以4的方式对齐去分配那10个字节,那么要完全装下就要分配3个四字节的空间,故是12字节。