C语言基础课程
学语言:逻辑,基本算法,基本数据结构
学c基础不是目的,就个开端
没有最好的语言,只有最合适的
- 基本结构
- 预处理指令,函数,变量,语句&表达式,注释
- 注释:
- 单行注释://注释内容
- 多行注释:/*注释内容*/
- 注释的用途:1.表明函数或者代码用意 2.版本说名等有用信息
- 打印函数:结果的输出
- 库/包
- #include 面粉
- 提供基础的接口(基础应用)
- 主函数(main函数)
- 注意;每一个C语言工程中有且只能有一个main()函数
- main函数是我们程序的入口
- C语言中有严格的大小写区分
- int数据类型
#include //预处理,帮助你加载已有包/库
#include
int main()
{
// 注释:注释在程序执行是不参加工作 帮你标注你的代码
//第一个c语言程序
/*
多行注释
q
w
e
r
d
f
*/
printf("Hello world!\n");//打印函数。
return 0;
}
序号 | 数据类型 | 描述 |
---|---|---|
1 | 基本数据类型 | 算术数据类型(整数类型和浮点类型) |
2 | 枚举数据类型 | 常用来被定义程序中只能赋予其一定的离散整数型的数值 |
3 | void数据类型 | 缺省型 |
4 | 派生数据类型 | 指针 |
整数类型:
整形(关键字) | 字节数(bytes) | 范围值 |
---|---|---|
short | 2字节 | -3万~3万 |
long | 4字节 | -215次方-215 |
int | 2字节(32位操作系统)/4字(64位操作系统) | 。。 |
char(带符号) | 1字节 | -128~127/ 0~255 |
unsigned char(无符号类型) | 1 | 0-255 |
unsigned int(无符号类型) | 2字节/4字节 | |
unsigned long(无符号类型) | 4字节 | |
unsigned short(无符号类型) | 2字节 | 0~4294967295 |
浮点型
类型 | 存储大小 | 精度 | 整数位个数 | 小数位个数 |
---|---|---|---|---|
float(单精度浮点) | 4字节 | 小数据点后6位 | 8位 | 23位 |
double(双精度浮点) | 8字节 | 小数点后15位 | 11位 | 52位 |
long double | 16字节 | 小数点后19位 |
#include //预处理 加入库/包
#include
int main()
{
//主函数,程序运行的入口,花括号中的内容为函数体
//声明变量——变量的声明/定义要放在函数体的最顶端
float i;
printf("float max size = %d\n",sizeof(float));//输出float类型的最大字节数
printf("float max value = %E\n",FLT_MAX);//%E 以指数形式输出单,双精度实数。
printf("float min value = %E\n",FLT_MIN);
printf("float 精度:%d\n",FLT_DIG);
//输出float数据类型 %f
printf("float %f",i);
}
注意:
- float:
- 数据类型当小数点后第七位有数据值时符合四舍五入的原则讲数据整合到第六位进行输出。
- 如果float后只是一个整数时,输出结果会讲其精度进行补全
缺省型void
概念:void是指没有确定的或者可指向的值
一般有以下三种情况
1. | 函数返回为空。C语言中各个函数都拥有返回值,如果说不具有返回回值时,函数名使用void进行修饰。 |
---|---|
2. | 函数的参数为空,c语言当中各函数接收任何参数,你就可以在函数的参数列表中写入void |
3. | 指针指向void:执行的类型为void* 表达的时对象的地址,而不是类型。***内存管理 |
二进制数据:
概念:
最基本的机器语言是二进制码。—》机器是不是由一堆电路和电子元器件。
二进制码机器是如何识别的?机器对于输入输出(信号):电信号(逻辑电平)—》有电/没电 0 1
二进制对比十进制:(短除法)
二进制 | 十进制 |
---|---|
0 | 0 |
1 | 1 |
10 | 2 |
100 | 4 |
1000 | 8 |
1100 | 12 |
1 0010 | 18 |
二进制到十进制:
二进制数 | 十进制数 |
---|---|
10000 | 16 |
11100 1x4+1x23+1x22+0x21+0x2^0 | 28 |
计算机都是按位运算存储的。
//引入头文件/包
#include
int main() //主函数
{
//1.变量的声明 数据类型(空格)变量名;(最后以分号结尾)
int i;//整数数据类类型 i;
short a;//
char b;//整数类型中的字符型数据 b;
float c;//单精度浮点型数据
int d;//做一个定义
int j;//j只做声明不做定义直接将其输出
//我们的 i ,a ,b ,c其实在计算眼中就是在给内存起名字,方便于直观进行内存的数据存放和管理
//变量在声明时就可给它一个初始值,将其定义
/*
多行注释
注意大家在编码时要以分号结尾
*/
//2.变量的定义,实际实在给变量进行赋值
i = 10;
a = 233;
b = 'L';//字符的写法都是由char 类型定义 字符的表示方法就是英文状态下单引号中写。切记char 只是单字符
c = 80.233;
//变量在使用前必须声明。可以不进行定义但是必须进行声明
d = 100;
printf("i = %d\n",i);//%d针对整型数据输出的
printf("a = %d\n",a);//
printf("b = %c\n",b);//%c是单个字符输出使用使用的
printf("c = %f\n",c);//%f是输出浮点数时使用
printf("j = %d\n",j);//j直接输出没有经过定义
}
i = 10;//正确的读法为:将10赋给变量i
//注意在赋值操作中一般分为左值和右值。切记左值不能为 常量
212 //十进制数
215U //U代表无法号整数-unsigned
21L //代表的长整数
0x001// 16进制数
020// 8进制数
10.2 //浮点数产量
字符常量
转义字符 \ | 含义 |
---|---|
’ | ’ |
" | " |
\t | 制表符:多个空格 |
\n | 换行符 |
\r | 回车 |
\v | 垂直制表符 |
字符串
#define 常量名 常量值
//常量举例
#include
//常量的定义方法
#define value 20 //注意没有分号 value 现在是一个常量
//赋值时常量不能为左值
int main()
{
int a;
a = value;
printf("a = %d \n",a);
}
a = 10 ,b = 2
运算符 | 描述 | 实例 |
---|---|---|
+ | 加法 | a+b 12 |
- | 减法 | a-b 8 |
* | 乘法 | a*b 20 |
/ | 取整除法 | a/b 5 |
% | 取余/取模除法 | a%b 0 |
++ | 自增 | ++b 前加 b++后加 |
– | 自减 | –b 前减b-- 后减 |
a+=2 运行过程为a = a+2;
//放到将条件语句的时候给大家讲
运算符 | 描述 | 实例 |
---|---|---|
== | 是否相等:判断左值与右值的数值是否相同 | |
> | 是否大于 | |
< | 是否小于 | |
>= | 是否大于等于 | |
<= | 是否小于等于 | |
!= | 是否不等于 |
运算符 | 描述 | 实例 |
---|---|---|
&& | 逻辑与:A条件&&B条件,当两个都为真是结果为真,有一个条件为假时即为假AB都为真,A&&B 结果为1 ,否则A&&B,有一个假的或者都是假的结果为0 | A&&B |
|| | 逻辑或:A || B,只有一个为真即为真,都为假才为假 | A||B |
!(英文状态下的!) | 逻辑非:!(A&&B(假)) 就变成真的了,非真条件为假,非假条件为真 | !A |
#include
#define value 100
int main()
{
//主函数
int i;
int j;
i = 10;
if(i==value && i < value)//逻辑与都为真才为真
//if的条件判断就两种真或者假, 布尔值(bool)0 / 1
{
//执行内容
printf("条件满足\n");
}
j = (i==value && i<value);
printf("逻辑与结果为:%d\n",j);
}
////////////////////////////////////////////////////////////////////////
#include
#define value 100
int main()
{
int i = 10;
if(i>value||i<value)//这个条件中有一个为真
{
printf("条件满足\n");
}
printf("程序结束\n");
}
运算符 | 描述 | 例子 |
---|---|---|
& | 与 | |
| | 或 | |
^ | 异或 | |
>> | 右移 | |
<< | 左移 |
概念:判断结构要求程序指定一个或者多个测试条件,以及通过条件之后要执行的内容(内容是必须要有的,不可为空)
if(条件)中的条件结果为0 和非0。结果为0时代表条件为假,否则条件为真
if(条件)
{
满足条件的执行内容
}
#include //基础头文件的引入
#define Value 18 //这是的作用是什吗? ----》常量的定义
int main()
{
//主函数
int i;//变量的声明
i = 18;//变量的定义,赋值操作
if(i == Value)// i是否和value相等
{
//条件通过之后执行的内容
printf("1. i和value值相等\n");
}
//判断体之外的语句。不受判断体的影响c
printf("2. 程序结束\n");
}
规则:如果条件满足时的执行语句只有一行代码时,可以不需要加大括号将执行内容包裹起来。如果执行内容时多行时,必须使用花括号将其包裹起来
#include
#define value 100
int main()
{
int i;
i = 10;
//代码格式
if(i == value)
printf("1.i和value 相等\n");
if(i >= value)
printf("2.i大于等于value\n");
printf("这是插入的语句\n");
if(i<=value)
printf("3.i小于等于value\n");
if(i != value)
printf("4.i不等于value\n");
printf("2.程序结束\n");
}
语句 | 描述 |
---|---|
if 语句 | if(条件) |
if … else语句 | if(条件1)else(除了条件1不满足其他的都满足) |
if的嵌套式语句 | if(条件1) else if(条件2) |
switch语句 | switch(条件) case…break…default…break |
A?B:C | 三元运算符,B,C都是执行语句。A是条件语句,A满住时执行B,不满足执行C |
#include
int main()
{
int age;
age = 40;
if(age<18)//if 。。else 条件只有两个
{
printf("1.年纪为%d岁不可以谈恋爱,要多学习\n",age);
}
else if(age>=18 && age<=25)//如何实现 10
{
printf("2.年纪为%d岁,正是大好年华\n",age);
}
else if(age>25 && age<35)
{
printf("3.年纪为%d岁,爱情事业双丰收\n",age);
}
}
#include
int main()
{
int money;
money = 30;
printf("我有%d块钱,能吃:\n",money);
switch(money)//money是结果 //条件
{
case 10://case value 注意只有条件和value 相等时才会执行
printf("吃一碗面条\n");
//切记需要在每一个case的执行内容中加入一个break;
break;//帮助你跳出执行体 打破
case 30:
printf("面条加啤酒\n");
break;
case 40:
printf("面条加啤酒加一盘小菜\n");
break;
case 50:
printf("面条加啤酒加一盘小菜加两鸡蛋\n");
break;
default: //以上条件都不满足时。执行 else
printf("以上都不满足\n");
break;
}
printf("程序结束\n");
}
三元运算符
#include
int main()
{
int number;
number = 11;
number%2==0?printf("偶数"):printf("奇数");
}
课堂小练习:
eg:用三元运算符和if…else 。写出两个数值比较大小,
概念:比如我们要执行一个语句多次,一般情况下都会使用循环来实现。
循环类型 | 描述 |
---|---|
for | 给定的条件为真的时候就执行循环语句,他在循环前先判断条件是否符合 |
while | 多次执行语句代码。简化循环变量 |
do while | 循环语句至少会执行一次,然后根据while()括号中的条件来判断是否继续执行循环语句 |
循环嵌套 | 循环套循环,列子见day03_07 |
for(a;b;c)
a代表的结果值,
b代表的条件
c代表的步进值。
注意:在for循环中a,c可以不写在for语句中,b必须在
#include
int main()
{
int i;
i = 0;
for(;条件;)//for循环中失去了结束条件,这个for循环会一直执行下去,形成死循环
{
i+=2;
printf("进入循环1\n");
printf("进入循环2\n");
}
printf("i = %d\n",i);
}
while():
括号中为循环条件,满足条件进行循环
在括号中写入非0的常量是构成死循环。
#include
int main()
{
int i;
i = 0;
while(i==0)//括号中就是循环条件,条件为真进入循环,假跳出循环
{
printf("进入循环-----1\n");
printf("进入循环--2\n");
i = 1;
}
}
do…while…
#include
int main()
{
int i;
i = 3;
do{
printf("执行\n");//至少会执行一次
i--;//
}while(i>1);//括号中就是循环条件
printf("结束\n");
}
循环的控制语句
控制语句 | 描述 |
---|---|
break 语句 | 终止循环。直接结束循环 |
continue 语句 | 结束本次循环,进行下一次循环 |
goto 语句 | 将控制转移到被标记的语句, |
#include
int main()
{
int i;
for(i=0;i<10;i++)
{
if(i%2==0)//i为偶数时
{
continue;
}
printf("i = %d\n",i);
}
}
#include
int main()
{
int i;
for(i=0;i<10;i++)
{
printf("i = %d\n",i);
//
break;
}
}
#include
int main ()
{
int i;
for(i = 0;i<10;i++)
{
if(i == 5)
{
goto end;//跳转点
}
printf("i=%d\n",i);
}
end://标记点
printf("end i = %d\n",i);
}
#include
int main ()
{
int i,j;
end:
printf("结束\n");
for(i = 0;i<3;i++)
{
for(j = 0;j<10;j++)
{
if(j == 5)
{
goto end;
}
printf("j = %d ",j);//%d只是表示输出一个整型数据。\n换行
}
printf("\n");
}
}
#include
int main()
{
int i,j,k;//变量的声明
i = 0;
j = 0;//变量的定义
k = 0;
for(i=1;i<10;i++)
{
for(k=0;k<(10-i);k++)
{
printf(" ");
}
for(j=1;j<=i;j++)
{
printf("* ");
}
printf("\n");
}
}
概念:函数是一组一起执行一个任务的语句。每一个c语言至少要有一个函数,也就是主函数。所有的简单代码都可以拥有额外的函数内容
函数的特性:高聚合,低耦合
示例
#include
//定义函数
/*
1. int 指的函数运行结束时返回值的数据类型
2. Add指函数名称
3. ()括号中的内容称为参数列表
4. int a,int b 称为形式参数也就是形参
5.花括号包含的内容为函数主体,也就是说函数的执行内容
*/
/*
规则:一般会使用注释的方式对函数功能,返回值,以及参数进行说明
例如:
function:加法函数
a:整数
b:整数
返回指为 整数类型
*/
int Add(int a,int b)//
{
int c;//实参
c = a+b;
return c;//返回值类型是由函数返回类型决定的
}
int main()
{
//必须要要有的主函数
//函数的调用——》如果说函数想要执行,就需要主函输进行调用
int i,j,k;
i = 10;
j = 20;
k = Add(i,j);
printf("k = %d\n",k);
}
注意:在同一个c文件中,函数如果定义在被调用之前,则不需要写函数声明,否则,也就是函数写在被调用之后必须书写函数声明,且在c文件的头部进行声明
C语言时编译型语言,也就是代码从main函数开始,自上而下执行,如果执行时发现未定义内容则报错
#include
//声明-注册
int MaxUnmber(int ,int);//声明时参数名称不是必要的,而参数类型是必要的
int main()
{
int c;
c = MaxUnmber(100,80);
printf("max = %d\n",c);
}
/*
输出两个数中的最大值
a 为整数
b 为整数
返回值为a,b中的最大值
*/
//定义
int MaxUnmber(int a,int b)
{
if(a>b)
return a;
else
return b;
}
概念:数组是一种数据结构,它可以存储固定大小的相同类型的数据的顺序集合。
int array[10]:(一维数组)声明————type name [size]
访问方式:
通过 ***数组名[下标]***的方式进行访问。下标的目标值的在数组中顺序位置***从0计数开始***的位置。
以循环的方式将数组中所有的值进行输出
通过对***数组名[下标] = 数值***的方式对其中的元素进行更改
#include
#include
//需求:写10个数,从10-19
int main()
{
int a,b,c,d,e,f,g,h,i,j;
//array 整数的数组
int array[10] = {10,11,12,13,14,15,16,17,18,19};//数组的初始化
//数组进行访问
//利用数组中元素的下标也就是位置,位置的计数是从0开始的
//列子访问 13拿出来
array[3] = 99;
for(i=0;i<10;i++)
{
printf("array[%d] = %d\n",i,array[i]);
}
}
#include
int main()
{
char a[4];//数组的声明,数组中没有数值。
int i;
a[0] = 'A';
a[1] = 'W';
a[2] = 'S';
a[3] = 'L';
for (i = 0;i<4;i++)
{
printf("%c",a[i]);
}
printf("\n");
}
多维数组
二维数组:多维中最简单的一种,本质上就是在一位数组的基础上加了列的概念,也就是说有x,y两个维度
练习—自己写一个三维和四维数组,然后利用循环将其输出
#include
int main()
{
//主函数
int array0[3] = {1,2,3};//一维数组
int array1[2][3] = {1,2,3,6,7,8};//二维数组1
int array2[2][3] = {//2*3 = 6个元素
{3,4,5},
{7,8,9}
}//另一种写法:有两个1行3列数组
int array3[2][2][3] = {2,3,4,5,6,7,8,9,10,11,12,13};//元素个数就是数量的乘积2*2*3 = 12个元素
/*
2层拥有2个3列的数组
*/
int array4[2][2][3] = {
{
{1,2,3},
{4,5,6}
},
{
{7,8,9},
{10,11,12}
}
}
}
概念:C语言中一种基本的数据类型,它可以让数据变得更加的简单,易读
语法格式为:
enum 枚举名 {元素1,元素2,};
#include
int main()
{
enum Day {
MON,
TUE,
WED,
THU,
FRI,
SAT,
SUN,
};//枚举的声明
enum Day day;//定义
day = SUN;
printf("%d\n",day);
}
#include
int main()
{
enum color {red=1,green,blue};//枚举的声明
enum color fav_color;//枚举的定义
while(1)
{
printf("输出你喜欢的颜色(1.red 2.green 3.blue):");
scanf("%d",&fav_color);//输出函数---****作用就是从控制台获取你得收入值
switch(fav_color)
{
case red://1
printf("你喜欢的是红色\n");
break;
case green://2
printf("你喜欢的是绿色\n");
break;
case blue://3
printf("你喜欢的是蓝色\n");
break;
default:
break;
}
}
}
注意:enum 中默认是从0开始的,可以通过赋值方式对其进行更改
概念:指针作为C当中的灵魂,如果进行内存和地址的访问,就需要使用指针,注意,指针不是一种变量,指针是指向地址的类型。
查看变量的地址
#include
int main()
{
int a;//整型a;
char b;//字符b;
float c;//浮点c
//查看a , b ,c的存储地址,
//存储地址就是指:a,b,c定义时计算机给分配的内存地址
//查看是利用指针指向他们所在的地址
//声明指针
/*
指向类型 * 指针变量名;
*/
int *p0;//指针p0指向一个整型数据的地址
char *p1;
float *p2;
p0 = &a;// &--->在位操作中是与操作,放在变量之前为取地址符
p1 = &b;
p2 = &c;
//%d->整数的打印占位 %f->浮点数 %c->字符 %p->地址的打印
//地址输出为16进制数
printf("a的地址为%p\n",p0);
printf("b的地址为%p\n",p1);
printf("c的地址为%p\n",p2);
}
指针:数据类型 * 指针变量 ————》指向某种数据类型的地址的指针变量
不论这个数据类型是什吗样子的,不论是这个整型,浮点型,字符型,等等,对于指针来说其类型都是一样的,都是代表着一个16进制数的内存地址
因为和这个数据类型没有关系所以指针在内存存放时的大小始终是4/8(长度和编译环境有关系)个字节长度
#include
int main()
{
printf(" int占%d|char占%d|float%d|\n",sizeof(int),sizeof(char),sizeof(float));
printf(" int指针占%d|char指针占%d|float指针%d|\n",sizeof(int*),sizeof(char*),sizeof(float*));
}
使用指针是会有有以下操作:定义指针,把变量地址赋值给指针,访问指针变量种可用地址的指。这些都是通过元运算符*号来返回位于操作数所指定原来的地址的变量的值。
以下为案例
#include
int main()
{
int a;
int*p;//定义一个指向整型的指针
a = 666;
p = &a;//通过取地址符&将变量a的地址赋予指针p;
//然后就可以通过指针p访问到地址a中的数值
printf("a = %d\n",a);
printf("p指向的地址中的数值是多少%d\n",*p);//*p读作 对p取值
printf("变量A的地址是%p\n",&a);
printf("变量p的地址是%p\n",&p);
printf("变量p指向的地址是%p\n",p);
//可以通过指针修改指针指向内存中的数据
*p = 30;//通过指针p改边了a变量内存中的数据
printf("a = %d\n",a);
}
指针访问数组
数组在内存中存储形式:***连续的存储的***每一个元素之前的地址间隔取决于元素的数据类型
数组的数组名代表了数组的存储地址的首地址,存放的是第一个数组元素
#include
int main()
{
int buffer[4] = {1,2,3,4};//4个int类型的数据
char buffer1[4] = {'c','b','d','!'};
int i;
for(i=0;i<4;i++)
{
//利用循环将数组中每个元素的地址进行输出
printf("buffer[%d]的地址为:0x%p\n",i,&buffer[i]);
}
printf("buffer的首地址是0x%p\n",buffer);//数组名就代表了这个首地址
printf("--------------------------------------------\n");
for(i=0;i<4;i++)
{
//利用循环将数组中每个元素的地址进行输出
printf("buffer1[%d]的地址为:0x%p\n",i,&buffer1[i]);
}
printf("buffer1的首地址是0x%p\n",buffer1);//数组名就代表了这个首地址
}
通过指针进行数组的访问
注意:指针指向类型要与数组中的元素类型相同,否则在偏移时就会和数组中每个元素存放的地址不相同,无法正确访问。
#include
int main()
{
int buffer[4] = {1,2,3,4};//4个int类型的数据
char buffer1[4] = {'c','b','d','!'};
int i;
//定义一个指针
int *p;//地址
for(i=0;i<4;i++)
{
//利用循环将数组中每个元素的地址进行输出
printf("buffer[%d]的地址为:0x%p\n",i,&buffer[i]);
}
printf("buffer的首地址是0x%p\n",buffer);//数组名就代表了这个首地址
printf("--------------------------------------------\n");
for(i=0;i<4;i++)
{
//利用循环将数组中每个元素的地址进行输出
printf("buffer1[%d]的地址为:0x%p\n",i,&buffer1[i]);
}
printf("buffer1的首地址是0x%p\n",buffer1);//数组名就代表了这个首地址
printf("------------------------------------------------\n");
//地址是可以通过指针进行访问的
p = buffer;//buffer代表首地址,也是数组第一个元素的地址
//p现在指向了数组第一个元素的地址,也就是数组的首地址
//通过指针p获取数组中的第一个元素,对地址进行取值操作
printf("数组buffer的第一个值为%d\n",*p);//p本就代表地址通过*号对地址进行取值
//地址+1,地址+1的步进值取决于p指向的数据类型
//p+1实际在内存中p向后/前移动了4个字节,刚到就到达了buffer[2]的地址
for(i=0;i<4;i++)
{
//利用循环,进行地址偏移
printf("p指向的地址为:%p,地址中存放的数值为:%d\n",p,*p);
p += 1;
}
}
注意:
指针是指向地址的一种数据类型
指针通过别人的地址来进行访问其数据
数组的数组名代表了数组的首地址也就是第一个元素的地址
指针偏移的步进值取决于指针指向的数据类型
指向类型和数组类型不同时,注意步进值
#include
int main()
{
int buffer[5] = {7,8,9,10,99};
char* p;//指向字符类型的的地址的指针.
int i;
for(i = 0;i<5;i++)
{
printf("buffer[%d] = %d \t buffer[%d]的地址为:%p\n",i,buffer[i],i,buffer+i);
}
//p接收数组buffer
p = buffer;//数组的首地址——>数组元素的第一个值得地址
//p每一次偏移1个字节,buffer的每一个元素的地址间隔是4个字节
//通过指针p输出uffer中的所有数据
printf("打印第一个元素:%d 地址:%p\n",*p,p);//
printf("打印第二个元素:%d 地址:%p\n",*(p+4),p+4);//
}
多维数组:所有的元素在内存中都是顺序存储的
#include
int main()
{
int a[2][2] = {
4,5,
6,7
};
int b[2][2] = {
{14,5},//b[0]
{77,88}//b[1]
};
int c[2][3][2] = {
{ //c[0]
{11,111},//c[0][0]-->这一个维度的首地址
{22,222},
{33,333}
},
{//c[1]
{44,444},//c[1][0]--->这个维度的首地址
{55,555},
{66,666}
}
}
int *p;
int i,j;
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
printf("a[%d][%d] = %d,地址为:%p \t",i,j,a[i][j],&a[i][j]);
printf("b[%d][%d] = %d,地址为:%p \n",i,j,b[i][j],&b[i][j]);
}
}
p = a;//获取数组a的首地址
for(i=0;i<4;i++)
{
printf("p-a = %d\n",*(p+i));
}
p = b;//获取数组b的首地址
for(i=0;i<4;i++)
{
printf("p-b = %d\n",*(p+i));
}
printf("______________________________\n");
p = a[1];//--->数组a的第二行的首地址--也就是说a[1]代表了第二行的数组的首地址
printf("p获取的数据%d\n",*p);
}
#include
//声明
int Sub(void);
int main()
{
int result;
int main_array[3] = {0};
//result = Sub();//
//printf("result = %d\n",result);
////////////////////////////////////////
printf("请输入3个数值:");
scanf("%d,%d,%d",&main_array[0],&main_array[1],&main_array[2]);
result = Sub2(main_array);
printf("result = %d\n",result);
}
int Sub(void)//函数的定义
{
int array[3] = {0};
int i;
printf("请输入3个数值:");
scanf("%d,%d,%d",&array[0],&array[1],&array[2]);
i = array[0]+array[1]+array[2];
return i;
}
int Sub2(int *array)
{
int i;
i = array[0]+array[1]+array[2];
return i;
}
1.指针的实质意义是访问到内存中的数据,可以对内存中的数据直接操作
#include
#include
//函数声明
void my(int a,int b);
void her(int *a,int *b);
int main()
{
int a;
int b;
a = 10;
b = 20;
my(a,b);
printf("main a %d \n",a);//10
printf("main b %d \n",b);//20
printf("--------------------------\n");
her(&a,&b);//
printf("main a %d \n",a);//11
printf("main b %d \n",b);//21
return 0;
}
void my(int a,int b)//变量有屏蔽作用
{
a = a+1;
b = b+1;
printf("my a : %d\n",a);//11
printf("my b : %d\n",b);//21
}
void her(int *a,int *b)
{
*a = *a + 1;
*b = *b +1;
printf("her a : %d\n",*a);//11
printf("her b : %d\n",*b);//21
}
概念:
函数指针指向函数的指针变量
通常指针变量指向一个整型,字符型或数组等变量,而函数指针是指向函数的
函数指针可以像一般函数一样,用于调用和传递参数
示例:
type (*指针名称/函数名称)(参数1,参数2,…);
#include
//函数声明
//int max(int,int)
int max(int a,int b);
int main()
{
//定义一个函数指针
int (*p)(int,int) = &max;//&取地址符可以省略,max也就代表了函数地址
int a,b,c,d;
while(1)
{
printf("请输入两个数值:");
scanf("%d,%d",&a,&b);
d = p(a,b);//等价于 d=max(a,b);
printf("较大的值为%d\n",d);
}
}
/*
求最大值函数
int指函数的返回指为整型
max是函数名
a,b是形式参数,用来进行值的传递
*/
//int max...函数的定义
int max(int a,int b)
{
//a>b?a:b b
/*
if(a>b)
return a;
else
return b;*/
return a>b?a:b;
}
概念:
函数指针作为某个函数的参数来使用,简单来说就是由别人的函数执行时调用你得函数
/*在函数MyArray中定义了三个参数。其中第三个参数是一个
函数指针,在函数MyRound函数中返回一个随机值,将来要传入MyArray
MyArray调用8次回调函数,并将其返回值复制给数组
*/
#include
#include
//函数声明
void MyArray(int *array,int Size,int (*p)(void));
int MyRound(void);
int main()
{
int array[20] = {0};
int i;
MyArray(array,20,MyRound);
for(i = 0;i<20;i++)
{
printf("array[%d] = %d\n",i,array[i]);
}
}
/*
array:指向整型数据的指针
Size:整数
p:指向返回值为int类型且参数为void的函数的指针
功能就是将p指向的函数的返回值,放到数组里
*/
void MyArray(int *array,int Size,int (*p)(void))
{
int i;
for(i=0;i<Size;i++)//循环次数
{
array[i] = p();
}
}
//产生随机值
int MyRound(void)
{
return rand(); //随机值
}
我们有时候希望自己的函数的参数的个数是个动态的,而不是一开始就指定好参数的类型和个数的
#include
//函数声明
int sub(int number,...);
int main()
{
sub(2,2,3);
sub(3,2,3,4);
}
//求和函数
int sub(int number,...)
{
}
注意:
例子
#include
#include
//函数声明
void my(int num,...);
int main()
{
my(5,12,13,14,15,20);
}
//函数的定义
void my(int num,...)
{
va_list valist;//定义参数列表
int sum = 0;
int i;
/*为num个参数进行初始化*/
va_start(valist,num);//
//访问赋值给valist中的所有参数
for(i=0;i<num;i++)
{
sum = va_arg(valist,int);//读取一次数据,返回为整数
printf("你传入的数据数值为:%d\n",sum);
}
//清理这个valist,准备下次使用时没有留存的垃圾值c
va_end(valist);
}
概念:字符串实际上是由null字符也就是***‘\0’结束一堆***字符数组,也就是说字符串是包含了以‘\0’结尾的多个字符的集合,集合也就是数组,这个数组被叫做字符串
#include
#include
int main()
{
char start[5] = {'H','E','L','L','O'};
char start1[] = {"HELLO"};//字符数组+'\0'
int i;
printf("start=");
for(i=0;i<5;i++)
{
printf("%c",start[i]);
}
printf("\n");
printf("start1=%s\n",start1);
printf("start size %d\n",sizeof(start));
printf("start1 size %d\n",sizeof(start1));
}
字符串的定义:
1.字符串是一个由字符构成的数组,所以在定义字符串时完全符合数组的方法
#include
#include
int main()
{
//定义字符串
//在定义字符串是不需要指定数组长度,计算会根据你写的内容计算长度存放起来
char buffer[] = {"Hello world!"};//12字符+‘\0’ 13
int i;
//1。字符串长度是多少?————解:13个
printf("buffer的长度为:%d\n",sizeof(buffer));
//2。如何将字符串中的字符挨个取出
for(i=0;i<sizeof(buffer);i++)
{
printf("buffer[%d] = %c\n",i,*(buffer+i));
}
printf("--------------------------------------\n");
for(i=0;i<sizeof(buffer);i++)
{
printf("buffer[%d] = %c\n",i,buffer[i]);
}
//3。如何整体输出这个字符串
printf("buffer = %s\n",buffer);
return 0;
}
字符串操作函数(API:接口函数)
使用前需要引入头文件 #include
函数 | 描述 |
---|---|
strcpy(s1,s2) | 复制把字符串S2复制到字符串S1 |
strcat(s1,s2) | 连接字符串,将S2字符串拼接到S1的末尾 |
strlen(s1) | 计算字符串的长度 |
strcmp(s1,s2) | 比较s1和s2的内容是否相同,如果相同返回0,如果不相同 s1>s2 返回值大于0 s1 |
strchr(s1,ch) | ch代表一个字符,s1是一个字符串。ch第一次在s1中出现的位置,返回的是一个指针 如果匹配不到返回指针 NULL |
strstr(s1,s2) | s2字符串第一次出现在字符串s1种的位置,返回值是一个指针类型,如果匹配不到返回指针 NULL |
ascall码:计算机存储数据都是二进制值,于是就是把对应的字符转换成具体的数值进行存储
#include
#include
#include
int main()
{
char s2[] = "xuao";
char s1[20] = {0};//定义空字符串
char s3[] = "tong";
char s4[] = "8个月,比他大";//内存中占12个
char s5[] = "MLXG";
char s6[] = "MLXG";
char s7[] = "8个月";
char ch = 'L';
char *p;
int result;
printf("s1被填充之前%s\n",s1);
//复制操作,将S2的字符串内容复制到S1
/*
注意点,
s1的长度要大于等于s2否则无法拷贝完整
*/
strcpy(s1,s2);
printf("s1复制了S2之后的内容为%s\n",s1);
//
//s1 = "xuao"
//字符串拼接操作
/*
注意:s1的长度原来为5,
拼接后sizeof还是计数原始长度
*/
printf("s2拼接前的内容:%s\n",s2);//xuao
printf("s2的原始长度%d\n",sizeof(s2));//5
strcat(s2,s3);//xuao tong ->xuaotong
printf("s2拼接后的内容:%s\n",s2);
printf("s2的拼接后长度%d\n",sizeof(s2));
//计算字符串长度
/*
注意1.sizeof计算出的是占用的内存的字节数
strlen计算出的是字符串的字符长度
*/
printf("sizeof计算出的长度%d\n",sizeof(s4));
printf("strlen计算出的长度%d\n",strlen(s4));
printf("-------------------------------------\n");
//字符串的比较
result = strcmp(s5,s2);
if(result == 0)
{
printf("两个字符串完全相同\n");
}else if( result > 0 )
{
printf("%s > %s\n",s5,s2);
}else{
printf("%s < %s\n",s5,s2);
}
//单个字符在字符串中第一次出现的位置
printf("---------------------\n");
p = strchr(s5,'X');//MLXG L
printf("%s \n",p);
//一个字符串是否存在于另一个字符串当中
printf("---------------------\n");
p = strstr(s4,s7);
printf("结果为:%s\n",p);
}
它是一个关键字,你可以利用它给一个类型起一个新的名字,公式:typedef 数据类型 new_name;
#include
int main()
{
int a;//定义一个整型变量a
typedef int iinntt; //将int 取别名为iinntt
iinntt b;//定义一个整型变量b
a = 10;
b = 20;
printf("a = %d b = %d\n",a,b);
}
概念:
输出
#include
/*
所有的C都包含主函数main
printf()函数就是将内容格式化输出到屏幕上
stdio.h中声明了printf()函数
#include 预处理命令,引入头文集过程
%d:整型用来匹配整型变量并将其输出到大屏幕
%f:浮点型(小数)用来匹配浮点型变量然后将其输出到屏幕
%c:字符型,用来匹配单个字符的变量然后输出到屏幕
%s:字符串的输出
%p:指针地址的输出
*/
int main()
{
int a;
float b;
char ch;
char str[] = "打雷了,要下雨";
int *c;
a = 10;
b = 100.1;
ch = 'L';
c = &ch;
printf("Hello world!\n");
printf("a = %d\n",a);
printf("b = %0.2f\n",b);//0.2代表精确到小数点后两位
printf("ch = %c\n",ch);
printf("str = %s\n",str);
printf("c指向的地址为:0x%p\n",c);
}
getchar()和putchar() api
int getchar(void)函数从屏幕读取***一个字符***,并把它返回成一个整数(这个字符对应的ascall码值)。这个函数在同一时间只会读取一个字符,也就是说每次只能从屏幕上获取输入内容中的一个字符
int putchar(int c)函数能把一个字符输出到屏幕上,并且返回一个相同的字符对应的ascall码值。每次执行只能输出一个字符,可以利用循环来让他输出多个字符
#include
int main()
{
int c;
printf("please enter a value:");
c = getchar();
printf("get value ascall :%d\n",c);
printf("putchar output value is:");
putchar(c);
printf("\n");
printf("________________________________\n");
putchar(98);//b-->ascall
}
gets()和puts() 函数
char* gets(char* s)函数从屏幕上读取一行字符到s所指向的内存中,直到一个终止符
int puts(const char* s)将字符串输出到屏幕上去,
#include
int main ()
{
char str[100];
char str1[] = "啥阵型";
printf("你瞅啥?\n");
gets(str);//获取你在屏幕上输入的内容
puts(str1);
gets(str);//获取你在屏幕上输入的内容
printf("别整了\n");
}
scanf()和printf()函数
int scanf(const char *format,…)
int printf(const char *format,…)
#include
#include
#define SIZE 100
int main()
{
int a;
char str[SIZE];
char res1[] = "要";
while(1)
{
printf("许傲:彤彤啊你多大了?\n");
scanf("%d",&a);//&a也是指针
printf("彤彤:我今年%d岁了\n",a);
if(a > 20)
{
printf("彤彤:老许老婆要不要?\n");
scanf("%s",str);//str是数组指针
printf("许傲:%s\n");
if(strcmp(str,res1) == 0)
{
printf("彤彤:就是我,死鬼\n");
}else{
printf("彤彤:哦\n");
}
}else if(a < 20)
{
printf("许傲:吃鸡不?");
scanf("%s",str);
printf("彤彤:%s\n",str);
}
}
}
概念
就是将变量从一种数据类型转换成另一种数据类型
#include
int main()
{
int a;
float b;
int c;
a = 100;
b = 100.99;
c = (int) b;
printf("c = %d\n",c);
printf("a = %f\n",(float)a);
}
数据的转换
#include
int main ()
{
char a = 'a';
int b;
int c;
b = 3;
c = b + (int)a;
printf("c = %d\n",c);
}
类型转换层级关系
概念:
结构体的定义、
#include
int main()
{
//定义结构体
struct Student{
char name[10];//名称
int age;//年龄
int grade;//成绩
};
}
struct 关键字
Student 结构体标签
char name 标准的变量定义
定义公式:
struct 结构体标签名 {
member-1;//成员1,数据类型由程序猿自己指定
member-2;
member-3;
//成员个数也是由程序猿自己指定
};
结构体的使用
#include
#include
int main()
{
//定义结构体
struct Student{
char name[10];//名称
int age;//年龄
int grade;//成绩
};
//定义只能告诉你结构体中包含了那些内容或者说属性
//如果想要使用结构体,需要进行结构的初始化
//结构体的初始化
//方法1
struct Student WangKai;//结构体变量WangKai
//方法2
struct Student ZhaoDIngDing = {"赵丁丁",20,100};
//使用变量加.的方式访问结构体中内容
strcpy(WangKai.name,&"王凯");//name -> 指针 字符串 strcpy()
WangKai.age = 20;
WangKai.grade = 90;
printf("wangkai的info\nname %s\nage %d\ngrade %d\n", WangKai.name,WangKai.age,WangKai.grade);
printf("ZhaoDIngDing的info\nname %s\nage %d\ngrade %d\n", ZhaoDIngDing.name,ZhaoDIngDing.age,ZhaoDIngDing.grade);
}
1.结构体的定义
2.结构体的初始化方法
结构体指针
指向结构体的指针。可通过指针访问结构体或者初始化结构体,
#include
#include
//全局变量
struct BOOK{
char name[20];
char Author_name[10];
int price;
};
//函数声明
void BookInfo(struct BOOK book);
int main()
{
int i;
struct BOOK book1 = {"厉害吧","许傲",5};
struct BOOK book2 = {"在摸鱼","王怀彤",10};
struct BOOK book3 = {"可不得了","李冲",15};
struct BOOK book4 = {"班长在游戏","陈钊",200};
while(1)
{
printf("--------------------------------------------\n");
printf("| 1.厉害吧,2.在摸鱼,3.可不得了,4.班长在游戏 |\n");
printf("--------------------------------------------\n");
printf("请输入你要查看的书的id:");
scanf("%d",&i);
printf("您查询的信息为:\n");
switch(i)
{
case 1:
BookInfo(book1);
break;
case 2:
BookInfo(book2);
break;
case 3:
BookInfo(book3);
break;
case 4:
BookInfo(book4);
break;
default:
break;
}
}
}
//打印书的基本信息
void BookInfo(struct BOOK book)
{
//定义一个结构体指针
struct BOOK *p;//结构体指针
p = &book;//将book的地址赋值给结构体指针p
//打印信息
printf("书名为:%s\n",p->name);
printf("作者为:%s\n",p->Author_name);
printf("售价为:%d元\n",p->price);
}
概念
在函数的定义自己调用自己
语法格式如下
void mode1()
{
line1;
line2;
....
model();//自己调用自己
}
int main()
{
model();
}
例子
#include
//阶乘 5! = 5*4*3*2*1
/*
3 -- > 3*model(2)---> 3*2*model(1) == >6
*/
double model(unsigned int i)
{
if(i<=1)
return 1;
return i*model(i-1);
}
int main()
{
unsigned int i;
double result;
while(1)
{
printf("输入一个整数:");
scanf("%d",&i);
result = model(i);
printf("%d 的阶乘结果为:%0.0f\n",i,result);
}
}
斐波那契数列
//斐波那契数列
#include
// 0 1 1
// 0 1 1 2
//
int fibonaci(int i)
{
if(i == 0)
{
return 0;
}
if(i == 1)
{
return 1;
}
return fibonaci(i-1)+fibonaci(i-2);
}
int main()
{
int i;
for(i=0;i<30;i++)
{
printf("%d-->",fibonaci(i));
}
}
动态内存管理,可以对内存进行申请,释放,扩充操作
序号 | 函数 | 描述信息 |
---|---|---|
1 | void*calloc(int num,int size) | 在内存中动态的分配num个长度为size的连续空间,并且将内存中的原始内容会被清除为0. |
2 | void free(void* address) | 释放(将内存归还给系统进行管理)address所指向的内存空间 |
3 | void* malloc(int num) | 在堆区指定分配一块指定大小的内存空间,这块内存只会被分配不会被初始化(不会清除其中原有的数据) |
4 | void realloc(void * address,int newsize) | 重新分配address执行的内存空间的大小为newsize |
注意使用前引入头文件