您的位置:首页 > 编程语言 > C语言/C++

C语言--汇总

2015-12-21 13:05 489 查看
一、四个月的课程体系
1、语言基础
1、c语言10day
2、oc语言(真正开发语言)6day
3、foudation(库)
2、iOS 核心编程
1、视图层(如何做QQ的样子,手势、动画)
3、iOS 高级编程
1、系统服务
2、网络编程
4、游戏开发
1、学习C ++(主要用来开发游戏)可以跨平台
2、cocos2d-x
3、swift语言以及iOS8开发
二、什么是ios开发
1.移动便携式开发:android 和 iOS
2.iOS开发(iOS程序员、iOS软件工程师)
3.android 和 iOS区别
a.     iOS基于unix,安全稳定。android基于linux的虚拟机,安全性低
b.    iOS强大的sdk、开发工具,不开源,apple公司,App             Store(08年上线),高端用户使用
android开源,google公司,googleplay应用商店,各种用户人群,
三、ios开发环境
1.mac操作系统
1)操作系统os:管理硬件资源和软件资源
2)macos:apple公司,自我封闭
3)iOS:设备:iPhone(2007年1月9日),iPod,touch,iPad,      apple tv
2. 布局:菜单栏、桌面、dock(快捷键)
3.格式化u盘:磁盘工具——ms-dos(fat)
4.软件安装
1、*.dmg(setup.exe虚拟光驱)
2、*.app(绿色软件)直接安装
3、直接从app store
5.pwd、cd、is命令
1、操作计算机的两种方式
a.图形化操作方式(操作直观)
b.命令行的操作方式(操作便捷,节约资源)
2、操作命令(终端快捷操作)
a.ls命令(查看当前文件夹下的文件或者子目录)
b.pwd(查看当前操作目录)
c.cd+空格+子目录名称(切换子目录)
d.cd+空格+..(退回上一级目录)
e.clear清除屏幕信息
f.mkdir+空格+文件夹(创建一个目录)
g.rm+空格-f空格  删除
3.相对路径和绝对路径(路径两种表达方式)
1./代表硬盘根目录(/uses/tarena/doc)
2.相对路径:相当于当前操作状态下的文件(或目录)的位置
3.绝对路径:根据硬盘根目录开始,文件(或目录)的位置
4.文件夹的创建与查看

12.31
c语言(1973年贝尔实验室)
1.四大部分:中央处理器(控制器、运算器)、存储器、输入设          备、输出设备    (1946年,冯诺依曼)
2.计算机语言分类
机器语言、汇编语言、高级语言
3.编程:自己有个想法,通过计算机语言使计算机理解,并帮我  们实现。
一、c语言执行步骤:
一.编辑程序
1.编写c语言的代码,保存在扩展名.c的文件中,源文件。
2.编写代码有三种方式:
a.vi命令方式系统自带
b.ultraedit网络下载
c.xcode网络下载
二.编译(gcc  文件名.c)
将c语言转换成计算机识别的代码
三.运行(./a.out)
经过编辑、连接之后,源程序文件就可以生成可执行文件
* vi的使用-补充(c语言快捷键):shift+“:”进入编辑功能
wq退出
“i”insert进入编辑模式
四.xcode简单的使用
1.创建项目
2.创建一个osx—command line Tool
3.main.c进行编程
4. 菜单栏product编译-run执行
5.改字体(苹果-第二个prefer..偏好设置-第五个改字体)
五.#include指令
1.在编译之前做的事情
2.相当于复制操作
3.加载系统提供的标准函数库
*“”是加载系统自定义功能
《》是加载系统功能
六.变量
1.数据类型:字符型char、整数型int、浮点型float/double、指  针、结构、联合等类型。
2.语法格式:变量类型  变量名=初始化值
3.保存运算中临时的值,number1=10赋值,可以多次赋值,但只会保留最后一次的值(右—左)
4.变量命名:a.必须以字母或下划线开头
b.包含字母、下划线或数字(不要出现空格)
c.不能与关键字冲突
d.大小写敏感的
e.长度一般不会限制,但会被编辑器截断

*变量放在等号左边就是存值操作,变量放在等式右边就是取值操作 i=10(存),j=i(取).把右面的赋值给左边的,从右向左

1.4
数据类型和变量赋值
1.整数类型
(char、int)小数类型(float、double)
a.有符号类型(整数、负数、0)范围   ( -128~127)
*所占存储空间的第一位为符号位。
*二进制符号位,最左边0+,1代表负数
b.无符号整型(整数、0)(0~255)256
c.有符号的整型(int,4个字节 )(-2^31~2^31-1)
*Byte、KB、MB、GB、TB、PB(1024)
如:1KB=1024B
超出最大值从最小值开始运算
超出最小值从最大值开始运算
d.有符号的短整型(short int,2字节)
e.有符号的长整型(long int,8字节)
f.有符号的长长整型(long long int)
g.无符号的整型(unsigned int,4字节)
h.无符号短整型(unsigned  short int,2字节)
i.无符号长整型(unsigned  long int,8字节)
j.无符号长长整型(unsigned  long long  int,8字节)
2.进制
a.十进制%d(0-9)逢十进一
b.八进制%o(0-7)逢八进一
c.十六进制%x(0-9ABCDEF)逢十六进一
d.二进制(0、1)逢二进一
int i=11 //十进制
int i=011 //八进制
int i=0x11 //十六进制
*c语言不能使用二进制
1.十进制转换二进制(除二取余,将余数从下向上读出)
举例:
32/2=17……0
17/2=8……1
8/2=4……0
4/2=2……0
2/2=1……0
1/2=0……1
将余数从下向上读出:100010

2.二进制数转化成十进制数(按权相加)
0       1     0    1    1    1  0   1位(从右向左)93
128   64   32  16   8    4  2   1权
举例:
1001110
0*2^0=0
1*2^1=2
1*2^2=4
1*2^3=8
0*2^4=0
0*2^5=0
1*2^6=64
得出的值相加=0+2+4+8+0+0+64=78
3.十进制数转换成八进制数、十六进制数
方法:辗转相除,从下向上取余
34/8=16……6
16/8=2……0
2/8=0……2
从下向上对应的八进制数:206
4.八进制数、十六进制数转换成十进制数
方法:按权相加法
6*8^0=6
0*8^1=0
2*8^2=128
按权相加:=134
5.二进制数转换成八进制数
方法:从最后一位开始,每三位二进制数,相当于一个八进制数。前面不足3为补0
举例:100  010=42
6.二进制转换成十六进制数
方法:每四位,不足补0
举例:0010  0010->22
3.字符(%c)
1.通过数值直接赋值  2.通过字符直接赋值
*.2f保留两位有效数字
4.变量:临时保存数据,数据的容器
常量:不可改变的值(具体的数值)
字面值:不可改变的值,就是数值(字符、数值)
*变量=字面值(常量)数据

练习题:
C语言中整数-8在内存中存储形式是:     原码->反码->补码(只有负数存的是补码)(2个字节=16位)
A)1111,1111,1111,1000             B)1000,0000,0000,1000
C)0000,0000,0000,1000             D)1111,1111,1111,0111

一、知识点
一.scanf(“%d”,&i);&取地址

例题:
1.输入两个数,并输出两个数
#include <stdio.h>

int main(int argc, const char * argv[])
{
int i=0,j=0;

printf("pelease input a number:");
scanf("%d",&i);
printf("pelease input nest number:");
scanf("%d",&j);
printf("i=%d\nj=%d",i,j);
return 0;

}

2.输入两个数,求其面积、周长、和
int main(int argc, const char * argv[])
{
int i=0,j=0,sum=0,mj=0,zc=0;
printf("pelease input a number:");
scanf("%d",&i);
printf("pelease input nest number:");
scanf("%d",&j);
mj=i*j;
zc=(i+j)*2;
sum=i+j;
printf("面积=%d\n周长=%d\n和=%d\n",mj,zc,sum);
return 0;
}

3.输入两个数求和、差、积、商
int i = 0 , j = 0;
//输入函数 要依赖于变量 要临时保存在键盘上输入的数据
//程序会发生阻塞状态
//友好性差 配合输出语句结合使用
printf("please input first Number:\n");
scanf("%d",&i);//&得到变量在内存中的地址,将键盘上输入的数据保存在变量中
printf("please input second Number:\n");
scanf("%d",&j);
//输出函数
printf("i:%d\n",i);
printf("j:%d\n",j);

int sum = 0;//求和
int sub = 0;//求差
int mul = 0;//求积
int div = 0;//求商
sum = i+j;
sub = i-j;
mul = i*j;
div = i/j;//整数相除取整数部分
printf("sum:%d\n",sum);
printf("sub:%d\n",sub);
printf("mul:%d\n",mul);
printf("div:%d\n",div);
return 0;
结果:
please input first Number:
45
please input second Number:
2
i:45
j:2
sum:47
sub:43
mul:90
div:22

4.数据类型省略写法
int main(int argc, const char * argv[])
{
signed int i=0;//有符号整型 可以省略signed
unsigned int i2=0;//无符号整型
short i3=0;//有符号短整型 可以省略 int 关键字
unsigned short i4=0;//
long i5=0;//有符号长整型 可以省略int
unsigned long i6=0;
long long i7=0;//长长整型 可以省略signed 和int 关键字
unsigned long long i8=0;//

return 0;
}
知识点
二、进制转换

5.输入一个数,分别以十进制、八进制、十六进制输出变量
int main(int argc, const char * argv[])
{
int i,j,k;
printf("输入:");
scanf("%d%d%d",&i,&j,&k);
printf("i=%d j=%o k=%x\n",i,j,k);//分别以十进制%d、八进制%o、十六进制%x输出变量
return 0;
}
6.十进制、八进制、十六进制之间的转换
int i=11,j=011,k=0x11;
printf("i=%d j=%o k=%x\n",i,i,i);//分别以十进制、八进制、十六进制输出变量
printf("i=%d j=%o k=%x\n",j,j,j);
printf("i=%d j=%o k=%x\n",k,k,k);
return 0;
结果:i=11 j=13 k=b
i=9 j=11 k=9
i=17 j=21 k=11

7.制表符(\t)  空3个字符,一个汉字
printf("1234567890123456\n");
printf("helloword!\n");
printf("hello\tword!\n");

return 0;
结果
1234567890123456
helloword!
hello   word!

8.整型数据溢出
//数据溢出
int i = 2147483647;//999 + 1
int j = i + 1;//超出最大值从最小值开始运算
int k = -2147483648;
int l = k - 1;//超出最小值从最大值开始运算
printf("j:%d\n",j);
printf("l:%d\n",l);
return 0;
结果:
j:-2147483648
l:2147483647

9.浮点型(float:%f  double: %lf)
float f = 3.1415926;//100
double d = 3.1415926;//200
float f2 = d;//100 = 200
//%.2f保留两位有效数字
printf("float:%.2f\n",f);
printf("double:%lf\n",d);
return 0;
结果:
float:3.14
double:3.141593

知识点
三、sizeof:计算存储空间的大小,单位:字节
sizeof()对应的数据类型是 long unsigned int ->%ld

10.sizeof所占空间大小
int i = 10;
long l = 20l;
long long ll = 30ll;
char c = 10;

float f = 10.1f;
double d = 10.1;
long double ld = 10.1l;
//求出某种类型或变量或字面值(常量)或表达式所占内存空间大小
//一定注意 变量的空间一定要大于字面值的空间,否则“可能”出现数据问题。
unsigned long int length = sizeof(d=20.1); //sizeof()不负责计算表达式的值
printf("d:%lf\n",d);
printf("length:%lu\n",length);
结果:
d:10.100000
length:8
知识点
四、运算符

11.优先级与结合性
int i = 3+4*5;
printf("i:%d\n",i);
int i2 = 3/2;//整数相除 结果还是整数
double d = 3.0/2;//如果相除时,有小数,则结果为小数
printf("i2:%d\n",i2);
printf("d:%lf\n",d);

//取余运算符%
int i3 = -5%2;
printf("i3:%d\n",i3);

//向0取整
int i4 = -5/2;
printf("i4:%d\n",i4);

//符号问题
int i5 = -5/-2;//与数学中的符号相同
printf("i5:%d\n",i5);
int i6 = 5%-2;//与前面的数字的符号相同
printf("i6:%d\n",i6);
结果:
i:23
i2:1
d:1.500000
i3:-1
i4:-2
i5:2
i6:1

12.例题:输入一个秒数 求时分秒
int inputSecond = 0;
printf("请输入一个秒数:\n");
scanf("%d",&inputSecond);

int hour=0,minute=0,second=0;

//hour = inputSecond/3600;
//minute = (inputSecond-hour*3600)/60;
//second = inputSecond -hour*3600 - minute*60;

hour = inputSecond/3600;
minute = inputSecond%3600/60;
second = inputSecond%60;

printf("input的秒数=%d时%d分%d秒\n",hour,minute,second);

结果:
请输入一个秒数:
3666
input的秒数=1时1分6秒

13.自增自减运算符
int i = 10;
//i++;//自增1 i = i + 1;
i--;//自减1 i = i - 1;
printf("i:%d\n",i);

int j = 10;
//int k = ++j;//前缀表达式 先自增 再运算(赋值)
int k = j++;//后缀表达式 先运算 后自增
printf("k:%d\n",k);

i = 10;
k=++i+(++i)+i++;
printf("k:%d\n",k);
return 0;
结果:
i:9
k:10
k:35
14.关系运算符
int i = 10;
int j = 20;
//>、<、>=、<=、==、!= 关系
printf("i>j:%d\n",i>j);//0 不成立
printf("i<j:%d\n",i<j);//1 成立
printf("i==j:%d\n",i==j);//0
printf("10>20:%d\n",10>20);
printf("10.1>20.1:%d\n",10.1>20.1);
printf("10.1>20:%d\n",10.1>20);
printf("'A'>'B':%d\n",'A'>'B');//ASC码
printf("'A'<'B':%d\n",'A'<'B');
结果:
i>j:0
i<j:1
i==j:0
10>20:0
10.1>20.1:0
10.1>20:0
'A'>'B':0
'A'<'B':1
15.练习题:
用户从控制台输入一个年龄,由程序判断该年龄是否大于18岁,结果输出1为真,0为否
int age = 0;
printf("请输入一个年龄:\n");
scanf("%d",&age);
printf("age>18:%d\n",age>18);
结果:
请输入一个年龄:
45
age>18:1
16. 布尔类型(bool)
C99 版本新添加的数据类型 逻辑值类型bool类型
#include <stdbool.h> 头文件
bool flag = false;//true 1 false 0
printf("flag:%d\n",flag);
结果:0
知识点
五、if语句条件分支语句    if…else    if…else if

//条件 关系表达式
//逻辑值 真 (1 true 或 非0) 假(0 false)
1.if 语句书写有三种形式
//普通语句(大括号可以省略)只会执行一条语句
if(true) printf("congratulation!");
区别
1. //普通语句(大括号可以省略)没有括号,只会执行一条语句
if(true)
printf("congratulation!");

printf("congratulation!");

2.//复合语句  要么多执行 要么都不执行 把多条语句变成一个整体
if(true){
printf("congratulation!");

printf("congratulation!");
}

3.//空语句
if(age>18);

2.if…else
int age = 18;

if (age>=18) {
printf("你已经成年了!\n");
}else{
printf("你还未成年!\n");
}
结果:你已经成年了!

3. if…else if…else
if(表达式1)语句1;
else if(表达式2) 语句2;
else if(表达式3) 语句3;
……
else 语句5;
执行方式从头开始判断真假

17.练习 输入小写字母 得到相应的大写字母
char ch;
printf("shuru");
scanf("%c",&ch);
if(ch>=97){
ch=ch-32;得到大写字母
printf("=%c",ch);

}else{
ch=ch+32;得到小写字母
printf("=%c",ch);
}
return 0;
18.输入一个分数,判断这个分数是否及格?
int score = 0;
printf("请输入一个分数:\n");
scanf("%d",&score);

if (score>=90) {
printf("您的分数是优秀\n");
}
else if(score>=60){
printf("您的分数是及格\n");
}
else{
printf("您的分数是不及格\n");
}
结果:
请输入一个分数:
95
您的分数是优秀
19.输入一个分数,得到相应的级别
int score=0;
printf("input:");
scanf("%d",&score);
if(score>100) printf("GO OUT !!!");
else if(score>=90) printf("A");
else if(score>=80) printf("B");
else if(score>=60) printf("C");
else printf("D");
return 0;
20.else if和if 比较
else if 相当于过一个十字路口:一次判断,多种选择
但是if 相当于过多个十字路口:多次判断
1.一次判断 多种选择 只会选择其一执行(满足条件)
int score = 0;
printf("请输入一个分数:\n");
scanf("%d",&score);
if (score>=60) {
printf("60\n");
}else if (score>=70){
printf("70\n");
}else{
printf("else\n");
}
结果:
请输入一个分数:
90
60
2.多次判断 多次执行(满足条件)
int score = 0;
printf("请输入一个分数:\n");
scanf("%d",&score);
if (score>=60) {
printf("if 60\n");
}
if (score>=70) {
printf("if 70\n");
}
结果:
请输入一个分数:
80
if 60
if 70
3.if在大括号里如果满足条件依次执行
int score = 0;
printf("请输入一个分数:\n");
scanf("%d",&score);
if (score>=60) {
printf("if 60\n");
printf("if 70\n");}

结果:
请输入一个分数:
80
if 60
if 70
21.逻辑运算符(&&、||)
int i=0,j=10;//逻辑与短路(短路与)
if((1!=1)&&(i=10))//若第一个表达式的值为假,后面的表达式不再计算
printf("i=%d",i);
//短路或  若第一个表达式值为真,后面的表达式不再计算
if((1==1)||(j=20))
{
printf("j=%d",j);
}
return 0;
结果:
i:0
j:1
22.取地址&与寻址运算符*
int i = 30;

int* p = &i;//得到变量在内存中位置
printf("p:%p\n",p);

//通过寻址运算符 根据地址直接操作内存
//取
printf("内存中的数据:%d\n",*p);
//存
*p = 40;
printf("i:%d\n",i);

结果:
p:0x7fff5fbff70c
内存中的数据:30
i:40

作业

1.输入一个年份,求该年一共有多少天。
int year;
printf("请输入年份:\n");
scanf("%d",&year);
if(year%400==0||((year%4==0)&&(year%100!=0)))
{printf("366天\n");}
else{printf("365天\n");}
结果:
请输入年份:
2005
365天
老师的程序: int days=365+(year%400==0||((year%4==0)&&(year%100!=0)))

2.输入一个年份,输入一个月份,求该月有多少天?
//1.输入年份
int year = 0;
printf("请输入年份:\n");
scanf("%d",&year);
//2.输入月份
int month = 0;
printf("请输入月份:\n");
scanf("%d",&month);
//3.判断不同的月份 天数是不一样的
//1 3 5 7 8 10 12 31天
//4 6 9 11 30天
//2 闰年 29天 平年28天
int days = 0;//用来保存所求天数
if (month==4||month==6||month==9||month==11) {
days = 30;
}else if (month==2){
days = 28 + ((year%400==0)||(year%4==0 && year%100!=0));
}else{
days = 31;
}
//4.输出天数
printf("year:%d month:%d days:%d\n",year,month,days);
结果:
请输入年份:
2005
请输入月份:
12
year:2005 month:12 days:31
3.准备回家过年了,交通工具,通过输入工资,
小于1300(最低工资),程序要报错,工资大于10000
坐飞机回家,如果大于5000,就坐火车回家,如果大于
3000,就坐汽车回家。大于1500,就骑自行车回家,都
不满足,步行。
int i=0;
printf("请输入工资:");
scanf("%d",&i);
if(i>=10000)
printf("飞机\n");
else if(i>=5000)
printf("火车\n");
else if(i>=3000)
printf("汽车\n");
else if(i>=1500)
printf("自行车\n");
else if(i<1300)
printf("程序报错\n");
else
printf("步行\n");

4.通过键盘输入4个值,求4个值中的最大值,最小值,和。
//1.输入4个值
int num1=0,num2=0,num3=0,num4=0;
int sum = 0;
printf("请输入第一个数:\n");
scanf("%d",&num1);
sum+=num1;
printf("请输入第二个数:\n");
scanf("%d",&num2);
sum+=num2;
printf("请输入第三个数:\n");
scanf("%d",&num3);
sum = sum + num3;
printf("请输入第四个数:\n");
scanf("%d",&num4);
sum = sum + num4;
//2.求最大值 算法(逻辑)
int max = num1;//标尺
if (num2>max) {max = num2;}
if (num3>max) {max = num3;}
if (num4>max) {max = num4;}
printf("max:%d\n",max);
//求最小值
int min = num1;//标尺
if (num2<min) {min = num2;}
if (num3<min) {min = num3;}
if (num4<min) {min = num4;}
printf("min:%d\n",min);

//3.求最小值
//4.求和
//sum = sum + num3; 累加
//sum += num3;累加 但效率更高 (编译原理)
//sum = num1+num2+num3+num4;
printf("sum:%d\n",sum);
结果:
请输入第一个数:
8
请输入第二个数:
6
请输入第三个数:
5
请输入第四个数:
9
max:9
min:5
sum:28

知识点
六、运算符

23.赋值运算符
int i = 20;
int j = 10;
int k = 15;
int l = 0;
l = (i = (j = (k = 5)));//从右向左运算的 右结合
printf("i:%d j:%d k:%d l:%d\n",i,j,k,l);
结果:i:5 j:5 k:5 l:5

1.按位异或操作
printf("5&3:%d\n",5&3);   //0000 0101
int i = 5;            //0000 0011
printf("~5:%d\n",~i);
int j = 3;
printf("5^3:%d\n",i^j);//按位异或操作
结果:
5&3:1
~5:-6
5^3:6

2.调换两个值(^)
int l = 5;
int r = 4;
printf("调换前: l:%d r:%d\n",l,r);
l^=r;//l=l^r;
r^=l;//r=r^l;
l^=r;//l=l^r;
/*
int temp = 0;//中间临时变量 桌
temp = l;
l = r;
r = temp;
*/
printf("调换后: l:%d r:%d\n",l,r);

结果:
调换前: l:5 r:4
调换后: l:4 r:5

3.按位左移 按位右移 标识一些有规律的数据
int i2 = 1;
//数据(二进制数)<<(左移)移动位数
//0000 0001 <<1 0000 0010
printf("i2<<1:%d\n",i2<<1);
//0000 0001 <<2 0000 0100
printf("i2<<2:%d\n",i2<<2);
结果:
i2<<1:2
i2<<2:4

4.多目运算符
int i = 10;
int j = 20;
char c ;
c = i<j?'a':'b';
printf("c:%c\n",c);
结果:c:a

24.重构利用多目运算符,输入字符 如果大写 转换小写 如果小写 转换大写
char ch;
char ch2;
printf("请输入一个字符:\n");
scanf("%c",&ch);
//2.判断 大->小 小->大
//ch2 = (ch>='A' && ch<='Z')?ch+('a'-'A'):ch-('a'-'A');
//多目运算符的嵌套
/*
条件表达式?表达式1:表达式2;
条件表达式?(条件表达式?表达式1:表达式2):表达式2;
*/
ch2 = (ch>='A' && ch<='Z')?ch+('a'-'A'):(ch>='a'&&ch<='z')?ch- ('a'-'A'):'?';
printf("ch:%c->ch2:%c\n",ch,ch2);
结果:
请输入一个字符:ch:a->ch2:A

知识点
七、swich语句
25.输入一个小写的数字 输出相应的大写数字 1->一
//1.输入一个小写数字
int number = 0;
printf("请输入一个小写的数字:\n");
scanf("%d",&number);
//2.根据不同的值进行不同的处理(条件分支)

switch (number) {
case 1:
printf("一\n");
break;//终止switch语句继续执行
//case 'a':printf("A\n");
case 2:
printf("二\n");
break;
case 3:
printf("三\n");
break;
default:printf("您输入的数据有误!\n");
break;
}
结果:
请输入一个小写的数字:
2
二

26.重构成绩等级制输入分数求级别
int score = 0;
printf("请输入一个分数:\n");
scanf("%d",&score);
//2.求相应的级别
//100/10 10 95/10 9 90/10 9
switch (score/10) {
case 10:
case 9:printf("A\n");break;
case 8:
case 7:printf("B\n");break;
case 6:printf("C\n");break;
default:printf("D\n");
break;
结果:
请输入一个分数:
90
A
27.重构等级制度输入一个分数级别
//二、输入一个分数级别
//求分数的范围 A "您的分数范围是90~100"
//1.输入一个级别
char level;
printf("请输入一个分数的级别:\n");
scanf("%c",&level);
//2.根据级别求分数范围
/* if分支语句
if (level=='A'||level=='a') {
printf("分数的范围是90~100\n");
}else if (level=='B'||level=='b'){
printf("分数的范围是70~90\n");
}else if (level=='C'||level=='c'){
printf("分数的范围是60~70\n");
}else{//E
printf("分数的范围是0~60\n");
}*/

//switch语句
switch (level) {
default:
printf("0~60\n");
break;
case 'B':
case 'b':printf("70~90\n");break;
case 'C':
case 'c':printf("60~70\n");break;
case 'A':
case 'a':printf("90~100\n");break;
结果:
请输入一个分数的级别:
a
90~100
28.switch练习
//1.输入数字
int number = 0;
printf("==================\n");
printf("1.显示全部记录\n");
printf("2.查询登录记录\n");
printf("3.退出\n");
printf("==================\n");
printf("请输入你需要的功能:\n");
scanf("%d",&number);
//2.根据不同数字 进行不同处理
switch (number) {
case 1:
printf("执行显示全部记录\n");
break;
case 2:
printf("执行查询登录记录\n");
break;
case 3:
printf("退出系统\n");break;
default:
printf("您输入的数据有请误!\n");
break;
}
结果:
==================
1.显示全部记录
2.查询登录记录
3.退出
==================
请输入你需要的功能:
2
执行查询登录记录

知识点
八、for   循环

1.for循环
//0 1 2 3 4 5 6 7 8 9
//循环语句 重复的执行一段代码
for (int i = 0; i<10; i++) {
//循环体
printf("跑了第%d圈\n",i);
}

//可以省略表达式1 可以放到其它位置 可能会出现问题
//可以省略表达式2 默认值是1 不可以放到其它位置
//可以省略表达式3 可以放到其它位置 但必须放在循环体的最后一条件语句
//三个表达式都可以省略
/*
for (int i=0;i<10;i++) {
printf("Hello\n");
}
*/
结果:
跑了第0圈
跑了第1圈
跑了第2圈
跑了第3圈
跑了第4圈
跑了第5圈
跑了第6圈
跑了第7圈
跑了第8圈
跑了第9圈

29.循环作业

1.重构字母转换(if语句)(逻辑运算符)
大写—>小写,小写—>大写,不是字母—>您输入的数据有误

2.求1-100的和1+2+3+5.....=5050
//求(输出)1到100的和。
//1.拿1~100数
//表达式1 循环标识
//表达式2 循环条件
//表达式3

int sum = 0;
for (int i = 1; i<=100; i++) {
//printf("i:%d\n",i);//循环体
sum=sum+i;//累加求和
}
//2.求和
printf("sum:%d\n",sum);
结果:sum:5050

3.输出1到100直间的奇数(不能被2整除的是奇数)
4.输出1到100之间的偶数(能被2整除的是偶数)
for (int i = 1; i<=100; i++) {
//2.根据条件取得的数
if(i%2==0){
printf(“偶数:%d\n”,i);
}
}

/*也可以用这样的办法求
for (int i = 1; i<=100; i=i+2) {
printf("i:%d\n",i);
}
*/

5.重构求10个数的最大值、最小值、和
int num = 0;
int sum = 0;

printf("请输入第1个数:\n");
scanf("%d",&num);
int max = num;//标尺
int min=num;
sum = sum + num;//求和
for (int i = 1; i<4 ; i++) {
printf("请输入第%d个数:\n",i+1);
scanf("%d",&num);
sum = sum + num;//求和 求累"积"?
//求最大值 求最小值?
if (num>max) {
max = num;
}
if (num<min) {
min = num;
}
}
printf("sum:%d\n",sum);
printf("max:%d\n",max);
printf("max:%d\n",min);
结果:
请输入第1个数:
50
请输入第2个数:
60
请输入第3个数:
40
请输入第4个数:
10
sum:160
max:60
max:10
6.在键盘上输入一个数(任意正整数),求该数的长度
123—3  4567—4
int i=0,c;
printf("请输入:\n");
scanf("%d",&c);
while(c)
{ c=c/10;
i++;}
printf("长度为:%d\n",i);
结果:
请输入:
123456
长度为:6

7.打印水仙花数,水仙花数是一个3位数100—999,每个位的数值的立方刚好是这个数的本身。
153=1*1*1+5*5*5+3*3*3,求水仙花数有哪些
int i;
int a,b,c;

for(i=100;i<1000;i++){
a=i/100;
b=i%100/10;
c=i%10;
{if(i==a*a*a+b*b*b+c*c*c)

printf("%d\n",i);}}
结果:
153
370
371
407
知识点
九、while循环
/* 标准的while循环
//int i = 0;//表达式1 循环标识
//在while循环中 表达式2是不可以省略的
while (i<10) {//表达式2 循环条件
printf("Hello\n");
//i++;//表达式3 循环规律
}
*/
//通过while循环的使用 只关注条件
/*
while (1<10) { //表达式2 循环条件
printf("hello\n");
}*/

//while循环的使用
int num = 1;//保存用户输入的数据
int count1 = 0;//统计正数有多少个
int count2 = 0;//统计负数有多少个
while (num!=0) {  遇到0就停止循环
printf("执行循环体\n");
printf("请输入一个数:\n");
scanf("%d",&num);
printf("您输入的数为:%d\n",num);
//判断是正数还是负数
if (num>=0) {//正数
count1++;
}
if (num<0) {//负数
count2++;
}
}
printf("正数有:%d个\n",count1++);
printf("负数有:%d个\n",count2++);

printf("程序结束!\n");
//多次输入一个数,只要不为0,就一直输入,统计
//输入的数,有多少个是正数,有多少个是负数。
结果:
执行循环体
请输入一个数:
60
您输入的数为:60
执行循环体
请输入一个数:
-60
您输入的数为:-60
执行循环体
请输入一个数:
0
您输入的数为:0
正数有:2个
负数有:1个
程序结束!

知识点
十、随机数
#include <stdio.h>
//1.导入头文件
#include <time.h>
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, const char * argv[])
{
/*
int i = 200;
char c;
//类型转换 int->char
c = (char)i;//告诉其它程序员 类型转换 有风险
*/
//2.使用函数 (unsigned)将有符号->符号
srand((unsigned)time(0));//种子
//0~21亿
//0~9 %10
//0~99 %100
//1~100 %100+1
int num = rand()%100+1;//随机数
//printf("num:%d\n",num);
bool isFlag = false;//标识是否猜正确
int inputNum = 0;//输入一个数
int count = 0;//统计猜数次数
while (!isFlag) {
printf("请输入您猜的数:\n");
scanf("%d",&inputNum);
count++;
//判断
if (inputNum==num) {
printf("您猜对了!\n");
isFlag = true;
printf("您一共猜了%d次!\n",count);
}else{
printf("请继续猜!\n");
if (inputNum>num) {
printf("您上次输入的数大了\n");
}else{
printf("您上次输入的数小了\n");
}
}
}
结果:
请输入您猜的数:
60
请继续猜!
您上次输入的数小了
请输入您猜的数:
80
请继续猜!
您上次输入的数大了
请输入您猜的数:
70
请继续猜!
您上次输入的数大了
请输入您猜的数:
65
请继续猜!
您上次输入的数小了
请输入您猜的数:
69
您猜对了!
您一共猜了5次!

知识点
十一、do…while循环
//表达式1 循环标识 就算条件不成立 至少执行一次
int i = 20;
do {
printf("HelloWorld\n");//循环体
i++;//表达式3
} while (i<10);//表达式2 循环条件
/* 第一次循环不会进行判断
do{
}while(表达式2)
*/
/* 三个循环的区别
for循环可以直接确定循环的次数
while循环关注循环的条件
do...while循环 第一次循环不会进行判断,每次判断的是下一次循环是否执行
*/
//重构猜数练习
结果:HelloWorld  (先执行do循环体的结果)

2.练习
模拟输入用户名密码(数字),设置一个数据库(模拟数据写死)中用户名密码(123,456),匹配则显示登录成功(则循环停止),否则登录失败,重新登录。

#include <stdio.h>
int main(int argc, const char * argv[])
{
//1.模拟输入用户名密码(数字)
int username = 0;//用户名
int password = 0;//密码
//2.设置一个数据库(模拟数据写死)中用户名密码(123,456)
int d_username = 123;
int d_password = 456;
//3.匹配则显示登录成功(则循环停止),否则登录失败,重新登录。
//a.输入数据
do{
printf("输入用户名:\n");
scanf("%d",&username);
printf("请输入密码:\n");
scanf("%d",&password);
}while ( !(username==d_username && password==d_password) );
printf("登录成功!\n");
//用户名和密码 都相同 登录成功
//(username==d_username && password==d_password)
或(同时使用break和continue)

//1.模拟输入用户名密码(数字)
int username = 0;//用户名
int password = 0;//密码
//2.设置一个数据库(模拟数据写死)中用户名密码(123,456)
int d_username = 123;
int d_password = 456;
//3.匹配则显示登录成功(则循环停止),否则登录失败,重新登录。
//a.输入数据
do{
printf("输入用户名:\n");
scanf("%d",&username);
printf("请输入密码:\n");
scanf("%d",&password);
if (username==d_username && password==d_password) {
printf("登录成功!\n");
break;
}else{
printf("登录失败,请重新登录!\n");
continue;
}
}while (1);
//用户名和密码 都相同 登录成功
//(username==d_username && password==d_password)

三个循环的特点:
for:循环可以直接确定循环次数
while :关注循环的条件
do…while 循环:第一次循环不会进行判断,每次判断的是下一次循环是否执行!

知识点
十二、break,continue
1.循环中使用break;
break;不但可以终止switch,也可以终止for循环语句
举例:
int main()
{
int i=0;
for (; i<10; i++) {
if (i==3) {
break;//终止循环的继续执行
}
printf("hello:%d\n",i);
}
}
练习:
编写一个求和程序。用户从控制台输入的整数的个数 不受限制,直到输入整数0为止。将输入的整数逐个相加后, 把结果输出。
int sum = 0;
while (1) {
//1.输入一个整数
int num = 0;
printf("请输入一个数:\n");
scanf("%d",&num);
//2.循环输入 直接输入0时结束 break
if (num==0) {
break;
}
//3.求输入整数之和并输出
sum+=num;
printf("sum:%d\n",sum);
}
结果:
请输入一个数:
45
sum:45
请输入一个数:
64
sum:109
请输入一个数:
0
2.continue可以终止当次循环,继续下一次循环
相当于跳过当次,接着执行下面的
int main()
{
for (int i=0; i<10; i++) {
if (i==3) {
continue;
}
printf("hello word:%d\n",i);
}
return 0;
}
结果:
hello word:0
hello word:1
hello word:2
hello word:4
hello word:5
hello word:6
hello word:7
hello word:8
hello word:9

3.清空缓冲区
scanf(“%*c”);
举例:有关回车所占的位置清空
int main()
{
char a,b;
printf("input:");
scanf("%c",&a);
scanf("%*c");//清空缓冲区

printf("input:");
scanf("%c",&b);
printf("a;%db:%d",a,b);
}

知识点
十三、for循环嵌套(相当于乘法)
int main()
{
1.循环嵌套 外面的循环执行一次 里面的循环执行一遍
2.描述的是一个二维表 外面的循环代表行  里面的代表列
3.使用循环的嵌套输出指定的图形
4.for可以嵌套 while可以嵌套 do…while 也可以嵌套
5.for…while混合嵌套
for (int j=0; j<2; j++) {//行
for (int i=0; i<3; i++) {//列
printf("i:%d j:%d\n",i,j);
}
printf("|\n");
}
return 0;
}
结果:
i:0 j:0
i:1 j:0
i:2 j:0
|
i:0 j:1
i:1 j:1
i:2 j:1
|
2.输出指定的图形
for (int j=0; j<3; j++) {
for (int i=0; i<5; i++) {
printf("*");
}
printf("\n");
}

3.while里面嵌套while
int main()
{
int i=0;
while (i<9) {//行
int j=0;
while (j<9) {
printf("%d%d ",i,j);
j++;
}
printf("\n");
i++;
}

return 0;
}
执行结果:
00 01 02 03 04 05 06 07 08
10 11 12 13 14 15 16 17 18
20 21 22 23 24 25 26 27 28
30 31 32 33 34 35 36 37 38
40 41 42 43 44 45 46 47 48
50 51 52 53 54 55 56 57 58
60 61 62 63 64 65 66 67 68
70 71 72 73 74 75 76 77 78
80 81 82 83 84 85 86 87 88
4.while里面嵌套for
for (int i = 0; i<9; i++) {
int j = 0;
while (j<9) {
printf("%d%d ",i,j);
j++;
}
printf("\n");
}

作业:

1.打印图形(简单)
a.*****
for (int i = 0;i<5; i++) {
printf("*");
}
printf("\n");
b.   *
**
***
****
*****
for (int j = 1; j<6; j++) { //行
for (int k = 0; k<j; k++) {//列打印内容
printf("*");
}
printf("\n");
}

c.*****
****
***
**
*
for (int j = 1; j<6; j++) { //行
for (int k = 0; k<6-j; k++) {//列打印内容
printf("*");
}
printf("\n");
}

d.    *
***
*****
for(int i=1;i<4;i++){

for(int p=0;p<2*i-1;p++){
printf("*");
}
printf("\n");
}

e. * * * *
* * * *
* * * *
* * * *
for(int i=1;i<5;i++){

for(int p=0;p<i;p++){
printf(" ");
}
for(int j=0;j<4;j++){

printf("* ");

}printf("\n");
}

2.99乘法表(中)
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
……
for (int i=1; i<=9; i++) {
for (int j=1; j<=i; j++) {
printf("%d*%d=%d ",i,j,i*j);
}
printf("\n");
}

3.三角形的输出(中)
for(int i=1;i<5;i++){

for(int p=1;p<5-i;p++){
printf(" ");
}
for(int j=0;j<2*i-1;j++){

printf("*");

}printf("\n");
}
*
***
*****
*******

4.输入一个数 求数的位数…(高)
for/while/do…while
123->3 4567->4
int num = 0;
printf("请输入一个数:\n");
scanf("%d",&num);
int length = 0;//除的次数(长度)
while (1) {
length++;
num = num/10;
if (num==0) {
break;
}
}
printf("length:%d\n",length);
结果:
请输入一个数:
12345
length:5
知识点
十四、一维数组
一维数组
数组是用来存储多条相同数据类型的数据结构(容器)
定义数组:
int array[3];
访问元素:array[0]=10;

数组名是地址:不能给数组名赋值
数组变量只可以在初始化的时候赋值并且是常量
举例:%p
int array[3];//数组类型 元素类型 数组名【长度】
array[0]=10;//数组名【下标】 变量=(存值)=变量(取值)
array[1]=20;
array[2]=30;
printf("array[0]:%d\n",array[0]);
printf("array[1]:%d\n",array[0]);
printf("array[2]:%d\n",array[0]);
return 0;

举例
int array[3];//数组类型 元素类型 数组名【长度】
array[0]=10;//数组名【下标】 变量=(存值)=变量(取值)
array[1]=20;
array[2]=30;
printf("array[0]:%d\n",array[0]);
printf("array[1]:%d\n",array[0]);
printf("array[2]:%d\n",array[0]);

int i=10;
printf("address:%p\n",&i);//&取地址运算符

printf("array address:%p\n",&array);//array数组变量 array[0]数组元素变量
printf("array address:%p\n",array);
//得到数组中首元素的地址 &array[0]
printf("array address:%p\n",&array[0]);
结果:array[0]:10
array[1]:10
array[2]:10
address:0x7fff5fbff8d8
array address:0x7fff5fbff8dc
array address:0x7fff5fbff8dc
array address:0x7fff5fbff8dc

练习:通过键盘输入5个数,输入后输出相应的5个数是什么

int array2[5]={};//初始化
int j;
//数组使用的时候,经常与循环(for)结合使用
//输入5个数
for (int i=0; i<5; i++) {
printf("input:",i+1);
scanf("%d",&array2[i]);

}//输出5个数
for (int j=0; j<5; j++) {
printf("output:%d",array2[j]);
}

2. //数组所占空间=元素所占空间*数组的长度
//?只要知道数组的名字 就能求出数组的长度
//数组的长度=数组所占空间/元素所占空间

float array3[3] = {10.1,20.1,30.1};
//数组变量只可以在初始化的时候赋值并且是常量
//array3 = {10.1,20.1,30.1};
//array3 = &...

int length = 0;
//sizeof 变量 类型 常量 表达式
printf("sizeof(array3) size:%lu\n",sizeof(array3));
printf("sizeof(array3[0]) size:%lu\n",sizeof(array3[0]));
length = sizeof(array3)/sizeof(array3[0]);
printf("length:%d\n",length);

//输出5个数
for (int j=0; j<sizeof(array3)/sizeof(array3[0]); j++) {
printf("第%d个数:%f\n",j+1,array3[j]);
}
结果:
sizeof(array3) size:12
sizeof(array3[0]) size:4
length:3
第1个数:10.100000
第2个数:20.100000
第3个数:30.100000

3.可变数组
1、在C语言中,可变数组指的是数组在声明前其长度是可变的,一旦声明,数组的长度就不可变了。
2、在oc语言中,专门有一种数据类型叫可变数组,数组在使用过程中,其长度是可变的。
int count;
printf("请输入班级的人数:\n");
scanf("%d",&count);
//可变数组在使用前 必须确定数组的长度
//一但声明,数组的长度不可修改
int scores[count];//可变数组 是不能初始化
int sum = 0;
for (int i = 0; i<count; i++) {
printf("请输入第%d个的成绩:\n",i+1);
scanf("%d",&scores[i]);
sum+=scores[i];
}
printf("sum:%d\n",sum);

练习:输入10个数,求10个数中的最大值,最小值,和。并且输入该值所在位置(最大值,最小值)
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{
int nums[5] = {0};
srand((unsigned)time(0));
//1.输入5个数
for (int i = 0; i<5; i++) {
/* 输入5个数
printf("请输入第%d个数:\n",i+1);
scanf("%d",&nums[i]);
*/
/*随机生成5个数*/
nums[i]= rand()%100+1;

}
//2.得到最大值 得到相应的位置
int maxIndex = -1;
int minIndex = -1;
//a.标尺 (1)拿第一个值当标尺
//int max = nums[0];
//(2)指定一个值作为标尺
//给最小值一个最大值的初值
//给最大值一个最小值的初值
int max = 0;
int min = 100;
//b.每一个值和标尺比
//得到数组中的每一个元素 "遍历"
for (int i = 0; i<5; i++) {
if(nums[i]> max){
max = nums[i];
maxIndex = i;//保存最大值的下标
}
if (nums[i]<min) {
min = nums[i];
minIndex = i;
}
}
printf("max:%d maxIndex:%d\n",max,maxIndex);
printf("min:%d minIndex:%d\n",min,minIndex);
//3.得到最小值 得到相应的位置
//4.求和
结果:
max:95 maxIndex:3
min:29 minIndex:1

4.数组的复制、拷贝
int array[3] = {4,5,6};
int array2[3];
//不可以直接赋值数组变量
//array2 = array;//数组一但声明 地址是不可修改
for (int i = 0; i<3; i++) {
array2[i] = array[i];//取出第一个数组中每一个元素
}
//查看数组2中的内容
for (int j = 0; j<3; j++) {
printf("array2[%d]:%d\n",j,array2[j]);
}
结果:
array2[0]:4
array2[1]:5
array2[2]:6

5.数组的乱序

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{
int array[10] = {1,2,3,4,5,6,7,8,9,0};
srand((unsigned)time(0));
for (int i = 0; i<10; i++) {
//x交换位置 随机生成
/*
0~9
1~9
2~9
3~9
*/
int x = rand()%(10-i)+i;//只是为了更随机
//array[i]当前的位置
//array[x]随机生成的交换位置
//交换两个值
int temp = array[i];
array[i] = array[x];
array[x] = temp;
}
//输出交换后的数组内容
for (int i = 0; i<10; i++) {
printf("array[%d]:%d\n",i,array[i]);
}

return 0;
}
结果:
array[0]:4
array[1]:1
array[2]:8
array[3]:0
array[4]:9
array[5]:6
array[6]:3
array[7]:7
array[8]:5
array[9]:2

6.正反向遍历
int main()
{
int array[5]={1,2,3,4,5};
for (int i=0; i<5; i++) {
printf("%d",array[i]);

}
printf("\n");
for (int i=4; i>=0; i--) {
printf("%d",array[i]);
}
return 0;
}
结果
12345
54321
7.数组元素的重复
若输入数据有重复的数字,把重复的数据表现出来
int main()
{
int num=0;
int count=0;
//    int temp=num;//复制一份输入的值
int array[count];

printf("input");
scanf("%d",&num);
int temp=num;
while (temp) {//求长度
count++;
temp/=10;
//       printf("%d",temp);
}
for (int i=0; num; i++) {//求出数组中的每一个数值
array[i]=num%10;//取出每一位的值并保存
num/=10;
}
for (int i=0; i<count; i++) {//每次都是与前一次进行比较
for (int j=0; j<i; j++) {
//        printf("%d%d",i,j);
if (array[i]==array[j]) {
printf("chongf%d\n",array[i]);
}
}
}
return 0;

}
结果:
input5864564
chongf4
chongf8
chongf5

练习:
随机产生6个红球和1个篮球,并且红球不重复,并输出红球和篮球
int main()
{
//1.生成几个随机数
//2.随机数的范围
//3.随机数的样子
//4.所求随机数 红 蓝
int blue=0;
int red[6]={0};
srand((unsigned)time(0));
blue=rand()%16+1;
for (int i=0; i<6; i++) {//red[i]=当前生成的随机数
red[i]=rand()%33+1;
for (int j=0; j<i; j++) {//red[j]=之前生成的随机数
if (red[j]==red[i]) {
i--;
break;//只要发现一个重复的,后面的就不需要判断了
}
}
}

//判断之前是否有重复
for (int i=0; i<6; i++) {
printf("%d ",red[i]);
}
printf("%d\n",blue);
}

练习 日历

int days[40] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,1,2,3,4,5,6,7,8,9,10};//40应该是365
int startIndex = 1;//1号在星期几
int index = 0;//取到几号了
printf("一\t二\t三\t四\t五\t六\t日\n");
if (startIndex==1) {
printf(" \t");
}
do {
if(startIndex%7!=0){//标识 所在位置
printf("%d\t",days[index++]);
}else{
printf("\n%d\t",days[index++]);
}
startIndex++;
if (index==40) {
break;
}
}while (1);
printf("\n");
结果:
一    二    三    四    五    六    日
1    2    3    4    5    6
7    8    9    10    11    12    13
14    15    16    17    18    19    20
21    22    23    24    25    26    27
28    29    30    1    2    3    4
5    6    7    8    9    10

知识点
十五、二维数组
//元素类型 数组名[数组长度];
int array[3]={0};初始化
//array[下标] 下标<数组长度
// 数组= 存值     =数组 取值
//二维数组 3外层(一维)数组的长度,2内层(二维)数组的长度
//元素类型 二维数组名[一维长度][二维长度];
int array[3][2];
//二维数组的操作 array[下标1][下标2]
int array2[4][3]={1,2,3,4,5,6,7,8,9,10,11,12};
//二维数组与循环嵌套使用
//外层循环对应二维数组一维的下标
//内层循环对应二维数组二维的下标
//   printf("%d",array2[2][0]);

int array[3][2]={{1,2},{3,4},{5,6}};//对应元素内容
int array1[3][2]={1,2,3,4,5,6};//整体赋值
int array2[3][2]={1,2,3,4};//依次赋值 自动补零

练习
1.输入5个学生,3门课的成绩,
2.求每个学生 总成绩 X
求每个课程 总成绩 Y
3.显示
#include <stdio.h>

int main(int argc, const char * argv[])
{
//保存5个学生3门课的成绩
int score[3][5] = {0};
int sum[3] = {0};//各门课的总成绩
int psum[5] = {0};//各个人的总成绩
//输入每一个学生的成绩
for (int i=0; i<3; i++) {
for (int j=0; j<5; j++) {
//printf("请输入%d行(课程)%d列(姓名)的成绩\n",i,j);
printf("请输入");
//课程
switch (i) {
case 0:
printf("语文");
break;
case 1:
printf("数学");
break;
case 2:
printf("英语");
break;
}
//姓名
switch (j) {
case 0:
printf("张");
break;
case 1:
printf("李");
break;
case 2:
printf("王");
break;
case 3:
printf("赵");
break;
case 4:
printf("钱");
break;
}
printf("的成绩\n");
scanf("%d",&score[i][j]);
//求每门课的成绩和
sum[i]+=score[i][j];
//求每个人的总成绩和
psum[j]+=score[i][j];
}
}
printf("\t张\t李\t王\t赵\t钱\n");
//输出每一个学生的成绩
for (int i=0; i<3; i++) {
//每一行的行头
switch (i) {
case 0:
printf("语文");
break;
case 1:
printf("数学");
break;
case 2:
printf("英语");
break;
}
printf("\t");
for (int j=0; j<5; j++) {
printf("%d\t",score[i][j]);
}
printf("\n");

}
//查看每门课的总成绩
for (int i = 0; i<3; i++) {
switch (i) {
case 0:
printf("语文");
break;
case 1:
printf("数学");
break;
case 2:
printf("英语");
break;
}
printf("的总成绩为:%d\n",sum[i]);
}
//每个人的总成绩?
return 0;
}
结果:
……
80
请输入英语钱的成绩
80
张    李    王    赵    钱
语文    60    60    60    60    60
数学    70    70    70    70    70
英语    80    80    80    80    80
语文的总成绩为:300
数学的总成绩为:350
英语的总成绩为:400
知识点
十六、函数

特点:1.结构清晰2.重复使用

1.函数的参数
#include <stdio.h>
//1.声明
//返回值类型 函数名(参数);
//推荐:***只要使用函数一定要声明
void sayHello(int i);//函数的原型
//void代表空 声明时不写参数 代表任意个数的参数
//如果不需要参数必须声明成void
//***函数的声明与函数的定义可以一致
//声明的时候 定义的时候 参数形参
//参数:如果函数执行的时候 需要有参考依据就要使用参数
void sayHello(){ //函数体 真正解决问题代码
printf("Hello\n");
}
//void sayHello5();
//2.定义
void sayHello5(){
printf("Hello\n");
printf("Hello\n");

}
练习1:
想输出几个Hello就输出几个Hello
void sayHelloN(int n);//声明
void sayHelloN(int n){
for (int i=0; i<n; i++) {
printf("Hello\n");
}
}
//程序执行的->main()->sayHello();
int main(int argc, const char * argv[])
{
//3.调用 如果定义的时候有参数,调用的时候就必须输入参数,声明与调用要统一
//sayHello(20);//调用时候的参数就是实参
//sayHello5();
sayHelloN(3);
printf("...几百行\n");
//sayHello5();//函数中定义的代码可以多次使用
结果:
Hello
Hello
Hello
...几百行

练习2:
早 晚 中 吃啥?
//写函数根据不同值来决定吃什么
//0鱼香肉丝 1地三鲜 2土豆丝 3.宫爆鸡丁
//other.吃饺子
#include <stdio.h>
//1.声明
void eat(int num);//根据数据决定吃什么
//2.定义
//如果函数需要多个参数,需要用,号分隔开。
//参数的类型不限制,但必须声明其类型。
//void eat(int num1,int num2)
//void eat(int num1,char ch)
void eat(int num){
//0鱼香肉丝 1地三鲜 2土豆丝 3.宫爆鸡丁
switch (num) {
case 0:
printf("鱼香肉丝\n");
break;
case 1:
printf("地三鲜\n");
break;
case 2:
printf("土豆丝\n");
break;
case 3:
printf("宫爆鸡丁\n");
break;
default:
printf("吃饺子\n");
break;
}
}
#include <time.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{
srand((unsigned)time(0));
int temp;
printf("早上起床了,吃啥呢?\n");
//scanf("%d",&temp);
temp = rand()%5;
//参数也可以是一个表达式,但必须有结果
eat(1+2);

printf("又到中午了,吃啥呢?\n");
temp = rand()%5;
eat(temp);

printf("晚上了,吃啥呢?\n");
temp = rand()%5;
eat(temp);
结果:
早上起床了,吃啥呢?
宫爆鸡丁
又到中午了,吃啥呢?
地三鲜
晚上了,吃啥呢?
宫爆鸡丁

2.函数的返回值

练习
/带饭
//吃什么口味的 0甜 1咸 2辣
//0->鱼(Y) 1->土(T) 2->尖(J)

#include <stdio.h>
/char buy(int taste);
//如果定义了返回值类型 函数执行后必须有返回值
char buy(int taste){
switch (taste) {
case 0:
return 'Y';
break;
case 1:
return 'T';
break;
case 2:
return 'J';
break;
default:
return 'Y';
}
}

int main(int argc, const char * argv[])
{
//中午帮我带个饭 我要辣的
//调用一个函数的时候,如果函数有返回值,必须要接收或处理
char ch = buy(0);
printf("ch:%c\n",ch);
结果:ch:Y

3.函数的参数是数组

1.求数组的长度
int a[]={1,2,3,4,5};
int length=sizeof(a)/sizeof(a[0]); 求数组的长度
printf("length:%d\n",length);
结果:
length:5

2.参数是数组
#include <stdio.h>
void func(int length,int *p);
void func(int length,int *p){
for (int i = 0; i<length; i++) {
printf("array[%d]:%d\n",i,*(p+i));
}
}
//参数 如果是数组,必须指定两个值
//1.数组的长度 2,数组名
void func2(int lenght,int array[]);
void func2(int lenght,int array[]){
for (int i = 0; i<lenght; i++) {
printf("array[%d]:%d\n",i,array[i]);
}
}

int main(int argc, const char * argv[])
{
int array[] = {1,2,3,4,5};
int length = sizeof(array)/sizeof(array[0]);
printf("length:%d\n",length);

//int *p = &i;
//int *p = &array[0];
int *p = array;

//func(array);
//如果函数的参数是数组 使用两个参数
//参数1 为数组的长度 参数2 数组的指针
func2(length,array);

return 0;
}
结果:length:5
array[0]:1
array[1]:2
array[2]:3
array[3]:4
array[4]:5

作业:
1.求两个数的和

#include <stdio.h>
#include<stdlib.h>
#include<time.h>

int count(int a,int b);
int count(int a,int b){

//printf("%d",sum);
return a+b;
}

int main(int argc, const char * argv[]) {
int a;
int i,j;
srand((unsigned)time(0));//随机得到两个数
i=rand()%10;
j=rand()%10;
a= count(i,j);// return的返回值赋给a
printf("%d",a);
结果:11

2.重构 成绩打印

#include <stdio.h>
void kemu(int i);
void xingming(int j);

void kemu(int i){
switch (i) {
case 0:
printf("语文");
break;
case 1:
printf("数学");
break;
case 2:
printf("英语");
break;
}

}
void xingming(int j){
switch (j) {
case 0:
printf("张");
break;
case 1:
printf("李");
break;
case 2:
printf("王");
break;
case 3:
printf("赵");
break;
case 4:
printf("钱");
break;
}

}

int main(int argc, const char * argv[])
{
//保存5个学生3门课的成绩
int score[3][5] = {0};
int sum[3] = {0};//各门课的总成绩
int psum[5] = {0};//各个人的总成绩
//输入每一个学生的成绩
for (int i=0; i<3; i++) {
for (int j=0; j<5; j++) {
printf("请输入");
//课程
kemu(i);
//姓名
xingming(j);
printf("的成绩:");
scanf("%d",&score[i][j]);
//求每门课的成绩和
sum[i]+=score[i][j];
//求每个人的总成绩和
psum[j]+=score[i][j];
}
}
printf("\t张\t李\t王\t赵\t钱\n");
//输出每一个学生的成绩
for (int i=0; i<3; i++) {
//每一行的行头
kemu(i);
printf("\t");
for (int j=0; j<5; j++) {
printf("%d\t",score[i][j]);
}
printf("\n");

}
//查看每门课的总成绩
for (int i = 0; i<3; i++) {
kemu(i);
printf("的总成绩为:%d\n",sum[i]);
}
//每个人的总成绩
for (int j=0; j<5; j++) {
xingming(j);
printf("的总成绩为:%d\n",sum[j]);
}
return 0;
}
结果:
请输入语文张的成绩:60
请输入语文李的成绩:60
请输入语文王的成绩:60
请输入语文赵的成绩:60
请输入语文钱的成绩:60
请输入数学张的成绩:70
请输入数学李的成绩:70
请输入数学王的成绩:70
请输入数学赵的成绩:70
请输入数学钱的成绩:70
请输入英语张的成绩:80
请输入英语李的成绩:80
请输入英语王的成绩:80
请输入英语赵的成绩:80
请输入英语钱的成绩:80
张    李    王    赵    钱
语文    60    60    60    60    60
数学    70    70    70    70    70
英语    80    80    80    80    80
语文的总成绩为:300
数学的总成绩为:350
英语的总成绩为:400
张的总成绩为:300
李的总成绩为:350
王的总成绩为:400
赵的总成绩为:60
钱的总成绩为:60

3.使用一个函数调换两个数。
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
void count(int i,int j);
void count(int i,int j){
printf("交换之前的值:i=%d j=%d\n",i,j);
int temp=0;
temp=i;
i=j;
j=temp;
printf("交换之后的值:i=%d j=%d\n",i,j);
}

int main(int argc, const char * argv[]) {
int a=0,b=0;
srand((unsigned)time(0));
a=rand()%100;
b=rand()%100;
// printf("主函数交换之前的值:i=%d j=%d\n”,a,b);去掉
count(a,b);
//实参与形参不是一个内存空间(传递的只是值)
// printf("主函数交换之后的值:i=%d j=%d\n”,a,b);去掉
return 0;
}
结果:
主函数交换之前的值:i=66 j=41
交换之前的值:i=66 j=41
交换之后的值:i=41 j=66
主函数交换之后的值:i=66 j=41

4.求两个数的最大值?
5.求两个数的最小值?
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
void count(int i,int j);
void count(int i,int j){
int min=0,max=0;
max=i;min=i;
if (i<j) {
max=j;
}
if (i>j) {
min=j;
}
printf("max:%d,min:%d\n",max,min);

}

int main(int argc, const char * argv[]) {
int a=0,b=0;
srand((unsigned)time(0));
a=rand()%100;
b=rand()%100;
count(a,b);
结果:
max:54,min:17

6.输入分数求级别,输入级别求分数?重构输入10个学生信息,得到相应结果。
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
//void a(int i);
//void b(char j);
//void xingming(int k);

void a(int i){
i=i/10;
switch (i) {  //输入分数求级别0~60D 60~70C 70~90B 90~100A
case 6:
printf("C\n");
break;
case 7:
case 8:
printf("B\n");
break;
case 9:
case 10:
printf("A\n");
break;

default:printf("D\n");
break;
}
}

void b(char j){
switch(j){
case 'A':
case 'a':printf("90~100\n");break;
case 'B':
case 'b':printf("70~90\n");break;
case 'C':
case 'c':printf("60~70\n");break;
default:printf("60\n");  break;
}

}

void xingming(int k){
switch (k) {
case 0:
printf("张");
break;
case 1:
printf("李");
break;
case 2:
printf("王");
break;
case 3:
printf("赵");
break;
case 4:
printf("钱");
break;
}

}

int main(int argc, const char * argv[]) {

for (int i=0; i<5; i++) {//输入5个人的信息
int fenshu;
printf("请输入");
xingming(i);
printf("的分数:");
scanf("%d",&fenshu);
printf("对应的等级是:");a(fenshu);
}
scanf("%*c");//缓存
for (int i=0; i<5; i++) {//输入5个人的信息
char dengji;
printf("请输入");
xingming(i);
printf("的等级:");
scanf("%c",&dengji);

printf("对应的范围是:");b(dengji);
}

return 0;
}
结果:
请输入张的分数:60
对应的等级是:C
请输入李的分数:50
对应的等级是:D
请输入王的分数:90
对应的等级是:A
请输入赵的分数:80
对应的等级是:B
请输入钱的分数:70
对应的等级是:B
请输入张的等级:a
对应的范围是:90~100
请输入李的等级:对应的范围是:60
请输入王的等级:D
对应的范围是:60
请输入赵的等级:对应的范围是:60
请输入钱的等级:C
对应的范围是:60~70

4.return与exit关键字

return:

1.有返回值类型,必须有return关键字
2.没有返回值类型,也可以使用return关键字
3.当函数的执行过程中,如果碰到return关键字,会终止函数的继续执行

#include <stdio.h>
void fun();
void fun(){
//有返回值类型,必须有return关键字
//没有返回值类型,也可以使用return关键字
return ;//当函数的执行过程中,如果碰到return关键字,会终止函数的继续执行
printf("函数结尾");
}
int main(int argc, const char * argv[]) {
fun();
printf("程序结尾\n");
结果:
程序结尾

exit:(#include <stdlib.h>)
1.终止程序的继续执行
#include <stdio.h>
#include <stdlib.h>
void func();
void func(){
printf("2.func函数开始执行了\n");
//1.有返回值类型 必须有return关键字
//2.没有返回值类型 也可以使用return关键字
//return ;
exit(0);//终止程序的继续执行
//当函数的执行过程中 如果碰到return关键字,会终止函数的继续执行
printf("函数末尾!\n");
}
int main(int argc, const char * argv[])
{
printf("1程序开始!\n");
func();
printf("3.程序末尾!\n");
return 0;
}
结果:
1程序开始!
2.func函数开始执行了

练习:
输出一组数的和、最大值、最小 值 
        在主函数中创建一个长度为10的数组,数组内放置10 个0~99之间(包含0,包含99)的随机数作为数组内容。   按要求分别编制自定义函数求数组中的最大值、最小值并 计算出所有数组元素的和。   在主函数中将各自定义函数的返回值打印显示在界面上。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
//得到一个随机数 0~99
int getRandom();
int getRandom(){
return rand()%100;
}
//得到一组数中的最大值
int getArrayMax(int length,int array[]);
int getArrayMax(int length,int array[]){
int max = 0;
for (int i= 0; i<length; i++) {
if(array[i]>max){
max = array[i];
}
}
return max;
}
//得到一组数中的最小值
int getArrayMin(int length,int array[]);
int getArrayMin(int length,int array[]){
int min = 99;
for (int i= 0; i<length; i++) {
if(array[i]<min){
min = array[i];
}
}
return min;
}
//得到一组数的和
int getArraySum(int length,int array[]);
int getArraySum(int length,int array[]){
int sum = 0;
for (int i=0; i<length; i++) {
sum+=array[i];
}
return sum;
}
//得到数组所有的内容
void outputArrayValue(int length,int array[]);
void outputArrayValue(int length,int array[]){
for (int i = 0; i<length; i++) {
printf("array[%d]:%d\n",i,array[i]);
}
}
int main(int argc, const char * argv[])
{
int array[10] = {0};
//生成随机数
srand((unsigned)time(0));
for (int i=0; i<10; i++) {
array[i] = getRandom();
}
//得到最大值
int max = getArrayMax(10, array);
//得到最小值
int min = getArrayMin(10, array);
//得到和
int sum = getArraySum(10, array);
printf("max:%d min:%d sum:%d\n",max,min,sum);
//显示数组中的所有内容
outputArrayValue(10, array);

return 0;
}
结果:
max:78 min:10 sum:504
array[0]:18
array[1]:30
array[2]:46
array[3]:75
array[4]:78
array[5]:52
array[6]:50
array[7]:10
array[8]:76
array[9]:69

5.递归函数
函数中调用函数就叫做递归。(一不小心死循环)
1.递归工作原理:
1.必须有退出条件
2.必须保证递归后。算法简化
#include <stdio.h>
int func(int num);
int func(int num){
printf("num:%d\n",num);
if (num==1) {
return 1;//终止条件
}
return num*func(num-1);//保证递归后算法简化   复制一个继续执行然后返回值
}//函数中调用函数 递归 一不小心死循环
//程序的编译顺序是自上下向的
//程序的运行顺序main函数的调用顺序
int main(int argc, const char * argv[]) {
int num1= func(3);3的阶乘,是几的阶乘就写几
printf("num1=%d\n",num1);
return 0;
}
结果:
num:3
num:2
num:1
num1=6(6相当于3的阶乘3!=3*2*1)

知识点
十六、变量的作用域
一、变量的作用域  (变量的使用范围)
1.不同级的代码块是可以重名的
2.i取值是就近原则
3.在上一级代码中声明的变量,是可以在下一级代码中使用
4.在下一级代码中声明的变量,是不可以在上一级代码中使用
5.声明在大括号外面的变量叫全局变量(整个程序中都可以用)
6.声明在大括号里面的变量叫局部变量(只能在大括号的内部使用)
7.参数是个特殊的局部变量,作用域范围,是函数的内部
8.for 循环的表达式1也是个特殊的局部变量,作用域的范围只能在for  循环体内部使用
#include <stdio.h>

int main(int argc, const char * argv[]) {
//变量i 作用域
int i=10;上一级代码块    全局变量
{
//代码块
int i=20;//不同级的代码块是可以重名的    下一级代码块      局部变量
//i取值是就近原则
printf("i1:%d\n",i);
}
printf("i2:%d\n",i);
return 0;
}
结果:
i1:20
i2:10

二、变量的生命周期(局部变量)在内存中存在的情况
1.自动变量auto
auto关键字 是没有动态变量一说的  不可使用
2.静态变量static
static在声明的开始,当程序结束时后结束

#include <stdio.h>
void func2(){
//自动变量  默认值就是auto
auto int i=10;//生 创建内存空间    auto可以省略
//静态变量
static int i2=20;//生 死:当程序结束的时候
i++;
i2++;
printf("i:%d\n",i);
printf("i2:%d\n",i2);
}//出了作用域 死 回收内存空间

int main(int argc, const char * argv[]) {
func2();
func2();

return 0;
}
结果:
i:11
i2:21
i:11
i2:22
二、变量的生命周期(全局变量)
全局变量的作用域在整个程序的内部,多个函数可以共享这个全局变量
全局变量的生命周期:
程序开始的时候——生
程序结束的时候——死

三、全局变量中的static和auto

1.auto关键字 是没有动态变量一说的  不可使用
2.static关键字 和生命周期没有关系,在多文件开发中,如果要区分全局变量在不同文件中的访问范围,需要使用static关键字修饰

四、栈操作
先进后出,后进先出
练习:使用程序来模拟放球、取球的问题 
      用数字来代表球,向栈中放入一个数字1代表放入了1 号球,向栈中放入一个数字2代表放入了2号球,依次类推。 同样,从栈中取出数字1代表取出了1号球。
#include <stdio.h>
//网兜
int balls[3]={0};
//网兜状态标识
int ballIndex = -1;//网兜空的时候为-1

//判断有没有满 1.满 0.未满
int isFull(){
if (ballIndex==2) {
return 1;
}else{
return 0;
}
}

//存球
void push(int ball);
void push(int ball){
//判断有没有满
if (!isFull()) {//没满 存
ballIndex++;
balls[ballIndex]=ball;
}else{ //满 不存
printf("网兜已经满了,不能存值!\n");
}
}

//网兜是否为空 1空 0非空
int isEmpty();
int isEmpty(){
if (ballIndex==-1) {
return 1;//为空
}else{
return 0;//非空
}
}

//取球
int pop();
int pop(){
//网兜是否为空
if (!isEmpty()) {//非空 取
int temp = balls[ballIndex];
balls[ballIndex] = 0;//还要将原来位置的值清零
ballIndex--;
return temp;
}else{//空 不能取
printf("网兜为空,不能取球!\n");
return 0;
}
}

//查看网兜状态
void showBalls();
void showBalls(){
printf("===================\n");
for (int i=2; i>=0; i--) {
printf("balls[%d]:%d\n",i,balls[i]);
}
printf("===================\n");
}

int main(int argc, const char * argv[])
{
showBalls();
push(1);
showBalls();
push(1);
showBalls();
push(2);
showBalls();
push(3);
showBalls();
int ball = pop();
printf("取走了一个球:%d\n",ball);
showBalls();
ball = pop();
printf("取走了一个球:%d\n",ball);
showBalls();
ball = pop();
printf("取走了一个球:%d\n",ball);
showBalls();
ball = pop();
printf("取走了一个球:%d\n",ball);
showBalls();
return 0;
}
结果:
===================
balls[2]:0
balls[1]:0
balls[0]:0
===================
===================
balls[2]:0
balls[1]:0
balls[0]:1
===================
===================
balls[2]:0
balls[1]:1
balls[0]:1
===================
===================
balls[2]:2
balls[1]:1
balls[0]:1
===================
网兜已经满了,不能存值!
===================
balls[2]:2
balls[1]:1
balls[0]:1
===================
取走了一个球:2
===================
balls[2]:0
balls[1]:1
balls[0]:1
===================
取走了一个球:1
===================
balls[2]:0
balls[1]:0
balls[0]:1
===================
取走了一个球:1
===================
balls[2]:0
balls[1]:0
balls[0]:0
===================
网兜为空,不能取球!
取走了一个球:0
===================
balls[2]:0
balls[1]:0
balls[0]:0
===================

知识点
十七、指针
1.什么是指针
内存被分为字节,每个字节有唯一的地址,指针指的就是内 存地址
2.指针变量
保存指针的变量,就叫指针变量。(保存地址) 
int i;//int类型变量
i=10;
int* p;//*指针类型变量
p=&i;
printf("p->:%d\n",*p);
结果:
p->:10

3.每个指针变量能指向一种特定类型的对象(地址,内存区 域)

4.指针是引用数据类型,因为本身没有保存数据,只是保存了 数据的地 址,间接的找到内存中的数据

*5.得到一个指针,可以得到两个值
1.直接得到数据在内存的地址    指针的值     地址
2.间接得到内存中保存的数据    指针指向(值)
int i;//int类型变量
i=30;
int* p;//*指针类型变量
p = &i;//得到变量在内存中位置   (指针的值)一块内存地址
printf("p:%p\n",p);

//通过寻址运算符 根据地址直接操作内存
//取
printf("内存中的数据:%d\n",*p);
//存
*p = 40; 指针指向的内存区域
printf("i:%d\n",i);

结果:
p:0x7fff5fbff70c
内存中的数据:30
i:40

6.指针可以作为参数(形参)

定义函数时,可以使指针类型作为参数,多个变量共用一个内存空间

练习 交换两个值的地址

#include <stdio.h>
//共用一块内存区域
void change(int* p1,int* p2);
void change(int* p1,int* p2){
printf("change1 i:%d j:%d\n",*p1,*p2);
int temp = *p1;
*p1 = *p2;
*p2 = temp;
printf("change2 i:%d j:%d\n",*p1,*p2);
}

int main(int argc, const char * argv[])
{
int i = 10;
int j = 20;
printf("main1 i:%d j:%d\n",i,j);
change(&i, &j);
printf("main2 i:%d j:%d\n",i,j);
return 0;
}
结果:
main1 i:10 j:20
change1 i:10 j:20
change2 i:20 j:10
main2 i:20 j:10

求一组数的最大值、最小值   
         在主函数中创建一个长度为10的数组,数组内放置10 个0~99之间(包含0,包含99)的随机数作为数组内容, 按要求编制一个自定义函数同时返回数组中的最大值、最 小值,然后在主函数中将自定义函数的返回值打印显示在 界面上。
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
int num();
int num(){
return rand()%100;
}

void func(int length,int a[],int* maxp,int* minp);
void func(int length,int a[],int* maxp,int* minp){
for (int i=0; i<length; i++) {
if (a[i]>*maxp) {
*maxp=a[i];
}
if (a[i]<*minp) {
*minp=a[i];
}
}
}
int main(int argc, const char * argv[]) {
int max=0,min=99;
int a[10]={0};
//使用随机数生成10个数
srand((unsigned)time(0));
for (int i=0; i<10; i++) {
a[i]=num();
printf("a[%d]=%d\n",i,a[i]);
}
//求一组数的最大值和最小值
func(10,a, &max,&min);
printf("max:%d min:%d\n",max,min);

return 0;
}
结果:
a[0]=72
a[1]=11
a[2]=16
a[3]=38
a[4]=52
a[5]=78
a[6]=20
a[7]=92
a[8]=42
a[9]=53
max:92 min:11

7.指针可以作为返回值

定义函数的时候,可以使用指针类型作为返回值,可以共享函数中的内存空间。注意:函数中的变量不能是自动变量,自动变量一旦超出作用域就销毁了,如果想使用,必须延长变量的生命周期,使它变成静态变量。

#include <stdio.h>
//2.使用全局变量
//int i=30;
int* func();
int* func(){//指针作为参数,共享函数中的内存空间
static int i=10;//1.延长变量生命周期    (只有第一次执行,第二次调用便使用i++)
i++;
printf("i:%d\n",i);
return &i;
}
int main(int argc, const char * argv[]) {
int* ip;
ip=func();
*ip=20;
func();

return 0;
}
结果:
i:11
i:21

8.指针的加减操作
指针支持加整数、减整数、指针的比较和相减,但运算的单位 由指针的类型决定。 
指针变量+1 相当于移动了一个数据位
   int类型指针+1  =  地址+4       
char类型指针+1  =地址+1 
1.int 类型的指针加减

#include <stdio.h>

int main(int argc, const char * argv[]) {
int a[3]={1,2,3};
int* p=a;//等于int* p=&a[0];
printf("*p:%d  %p\n",*p,p);
printf("*(p+1):%d  %p\n",*(p+1),p+1);
printf("*(p+2):%d  %p \n",*(p+2),p+2);
return 0;
}
结果:
*p:1      0x7fff5fbff77c
*(p+1):2  0x7fff5fbff780
*(p+2):3  0x7fff5fbff784

2.char类型的指针加减

#include <stdio.h>

int main(int argc, const char * argv[]) {
char a[3]={'a','b','c'};
char* p=a;//等于int* p=&a[0];
printf("*p:%c  %p\n",*p,p);
printf("*(p+1):%c  %p\n",*(p+1),p+1);
printf("*(p+2):%c  %p \n",*(p+2),p+2);
return 0;
}
结果:
*p:a      0x7fff5fbff77d
*(p+1):b  0x7fff5fbff77e
*(p+2):c  0x7fff5fbff77f

3.通过for循环  根据地址取值

#include <stdio.h>

int main(int argc, const char * argv[]) {
int a[3]={1,5,2};
int* p=a;//等于int* p=&a[0];

//通过for循环 根据地址取值
for (int i=0; i<3; i++) {
//*(p+i)与(*p)+1结果是不同的
printf("*(p+i):%d\n",*(p+i));正确的输出
printf("*(p)+i:%d\n",(*p)+i);
}
结果:
*(p+i):1
*(p)+i:1
*(p+i):5
*(p)+i:2
*(p+i):2
*(p)+i:3

9.二级指针
int i=10;
int* ip=&i;//指针
int** ip2=&ip;//二级指针
int*** ip3=&ip2;//三级指针
printf("ip3:%d\n",***ip3);
结果:
ip3:10

10.指针与数组

共同点:两者都可以表示地址

不同点:
一、所占内存空间不同
1. 和具体内存中,所保存的数据无关
2.所有内存的地址所占内存空间都是一样大的
3.指针地址所占内存空间在macos64位系统下, 地址所占8字节
4.数组所占的内存空间=元素所占的内存空间*元素的长度(个数)
例题:
int i = 10;
char ch = 'a';
int* p1 = &i;
char* p2 = &ch;
//所占内存空间
//和具体内存中,所保存的数据是无关
//所有内存的地址所占内存空间都是一样大的
//macos64位 地址所占8B
printf("p1 size:%ld\n",sizeof(p1));
printf("p2 size:%ld\n",sizeof(p2));

//数组所占的内存空间=元素所占内存空间*元素个数
int array[5];
int* p = array;
printf("p size:%ld %p\n",sizeof(p),p);
printf("array size:%ld *%p\n",sizeof(array),array);

结果:
p1 size:8
p2 size:8
p size:8 0x7fff5fbff790

二、赋值
1.指针变量的值是可以改变的
2.数组一但声明,其值是不可以改变的,而是保存数据在内存中的地址,在使     用的时候通过地址间接得到数据的值。

例题:
int array[5];
int* p = array;
printf("p size:%ld %p\n",sizeof(p),p);
printf("array size:%ld *%p\n",sizeof(array),array);
//赋值
int i2 = 10;
int j2 = 20;
int* p3 = &i2;
p3 = &j2;//指针变量的值是可以改变的 赋值

int array2[5];
int array3[10];
//array2 = array3;错误的表示//是不可以改变数组变量的值的
结果:
array size:20 *0x7fff5fbff790

11、引用———c语言中数据类型主要分为两大类

基本数据类型:int char double float
变量本身就保存了我们需要的数据
引用数据类型:指针
变量本身并没有保存数据

数据->(Create创建Read读取Update更新Delete删除)

12.进程空间

•进程是正在运行的程序,在内存中。  
• 每个进程在内存中占据的空间称进程空间 
1.进程空间的内存分配
1.代码区(正文段,  text)  只读      程序代码
2.全局区(全局静态区)    读、写     全局变量、静态变量
3.堆区(自由区,  heap)   读、写
4.栈区(堆栈,    stack)     读、写     动态变量(局部变量)
知识点
十八、字符串
1.三种字符串的创建:
一、字面值字符串
1.在代码区创建了一个字符串 会在结尾自动加\0 (只读)
2.字符串有自己的占位符%s
3.字符串使用,会从首地址一个字节一个字节的读取数据,直到读到\0位     置表示结束
//在代码区创建了一个字符串 会在结尾自动加\0
char* p= "string1";//可以与指针变量结合使用
printf("string2\n");//直接与输出函数使用
//字符串有自己的占位符%s
printf("%s\n",p);
char* p2= "string1";
//如果字符串的内容相同,代码区只会创建一个字符串
printf("p:%p,p2:%p\n",p,p2);//地址
//字符串使用,会从首地址一个字节一个字节的读取数据,直到读到\0位置 表示结束
char* p3="str\0ing1\n";
printf("p3:%s\n",p3);
结果:
string2
string1
p:0x100000f6e,p2:0x100000f6e
p3:str
4.证明  代码区   只读
char* p3="str\0ing1\n";
printf("p3:%s\n",p3);
char* cp=p3;
printf("cp+1:%c\n",*(cp+1));  //读
//*(cp+1)='w';//如果非要改 程序就异常   //写
结果:
p3:str
cp+1:t

二、字符数组的字符串
1.保存在内存中栈区  内容就算相同,也会开辟不同的内存空间
2.字符数组的字符串与普通的字符数组最大的区别是否有 结束符\0
3.栈区 读写....
char str[4]={'s','t','r','\0'};
char str2[4]={'s','t','r','\0'};
char* cp = str2;
*(cp+1) = 'w';//可以改变栈区的数据
printf("str address:%p value:%s\n",str,str);
printf("str2 address:%p value:%s\n",str2,str2);
结果:
str address:0x7fff5fbff7a4 value:str
str2 address:0x7fff5fbff7a0 value:swr

三、字符指针

对于字符串来讲引用类型:

1.字符指针即可以与字面值字符串结合使用
2.也可以与字符数组的字符串结合使用

练习:通过键盘输入一个字符串
//char* input="*********";通过字面值定义字符串不可取
char input[10];
char* inputp=input;
printf("请输入一个字符串信息:\n");
scanf("%s",input);
printf("str:%s\n",inputp);
结果:
请输入一个字符串信息:
hello
str:hello

三种字符串创建的比较
内存              内容相同               读写        结束符
a.字面值       代码区            只会创建一个      只读         自动
b.字符数组   栈区                会创建多个          读写         手动
c.字符指针   保存地址(栈) 无关                      无关         无关

2.字符串函数库

#include <string.h>

帮我们解决常用字符串的问题
a.字符串的赋值strcpy(参数1,参数2)
参数1:目标字符串位置(复制到哪里)
参数2:源字符串位置(字符串的来源)
*注:
char* str="helloworld\n";
char str2[15];
//复制一个字符串
strcpy(str2, str);
printf("str2:%s\n",str2);
结果:
str2:helloworld

b.字符串的拼接strcat(参数1,参数2)
1. 将第一个字符串的内容与第二个字符串的内容拼接在一起,保存在第一个  字符串中。
*注:参数1的空间>=两个字符串内容之和
char str3[10]={'h','e','l','\0'};
char*str4="wor\n";
strcat(str3, str4);
printf("str3:%s\n",str3);
结果:
str3:helwor

c.字符串的长度  (返回值长度)strlen(参数)
练习:求字符串的长度,不包含结束符
1.  char* str5 = "helloworld!\n";
unsigned long length = strlen(str5);
printf("length:%lu\n",length);
结果:
length:12
2.   char str5[10] = {‘h’,’e’,’l’,’\0’};//   ‘\0’不占内存空间
unsigned long length = strlen(str5);
printf("length:%lu\n",length);
结果:length:3

d.字符串的比较
比较两个字符串的内容strcmp(参数1,参数2)
1. 字符串的比较不可以使用==号,==通常比较的是两个数的值,字符串是引用数据类型,比较的是两个字符串的地址,与使用场景不符
2.标准做法:比较两个字符串中每一个字符的ASC码值,全都相同,两个字符串是相同的。
*注:结果得到的是两个字符串中ASC码的差值,若差值为0,则两个字符串相等。
char *str6 = "Heflo";
char *str7 = "HEllo";
int i = strcmp(str6, str7);
printf("i:%d\n",i);ASC码的差值
结果:i:32

练习:模拟登录,三次输入机会

//输入内容
char username[20],password[20];
//模拟数据库中的数据
char* d_username = "admin";
char* d_password = "123";
int count = 0;
while (1) {
count++;
printf("请输入用户名:\n");
scanf("%s",username);
printf("请输入密码:\n");
scanf("%s",password);
//判断登录是否成功
if (strcmp(username, d_username)==0
&&
strcmp(password, d_password)==0
) {
printf("登录成功!\n");
break;
}else{
printf("用户名或密码错误!\n");
if (count==3) {
exit(0);//程序结束
}
}
}
printf("登录成功后...");
结果:
请输入用户名:
fcp
请输入密码:
lbm
用户名或密码错误!
请输入用户名:
admin
请输入密码:
123
登录成功!
登录成功后...
3.字符串数组

两种形式:
1.字面值字符串数组
字面值字符串数组中的字符串是不能改变的

//字面值字符串数组
char* str = "zhangsan";
char* str2 = "lisi";
char* strs[2] = {str,str2};
printf("strs size:%lu\n",sizeof(strs));
//遍历字符串数组   输出strs[2]
for (int i = 0; i<2; i++) {
printf("strs[%d]:%s\n",i,strs[i]);
}
结果:
strs size:16
strs[0]:zhangsan
strs[1]:lisi

2.数组字符串数组
数组字符串数组中的字符串是可以改变的
//数组字符串的数组
//char str3[10] = {'z','h','a','\0'};
//char str4[10] = {'l','i','s','\0'};
char strs2[2][10]={{'z','h','a','\0'},{'l','i','s','\0'}};
printf("strs2 size:%lu\n",sizeof(strs2));
for (int i=0; i<2; i++) {
printf("strs2[%d]:%s\n",i,&strs2[i][0]);
}
结果:
strs2 size:20
strs2[0]:zha
strs2[1]:lis

作业
a.所有功能在使用前一定要登录
b.先注册才能登录
c.存钱存到帐号中(只有一个帐号)
d.取钱,取帐号中的钱(减),不足,取钱失败提示。
e.查看余额
f.0退出程序 如果不退出系统,循环执行。
/==============/
系统功能
1.注册
2.登录
3.存钱
4.取钱
5.查看余额
0.退出
/==============/
请输入您要选择的功能:_

#include <stdio.h>
#include <string.h>
void registerUser();
int isLogin();
void save();
//登录状态的标识
int flag = 0;

//保存用户名/密码
char username[20];
char password[20];
//临时保存用户输入的内容
char inputUsername[20];
char inputPassword[20];

void menu(){
printf("==================\n");
printf("系统功能\n");
printf("1.注册\n");
printf("2.登录\n");
printf("3.存钱\n");
printf("4.取钱\n");
printf("5.查看余额\n");
printf("0.退出\n");
printf("==================\n");
}

int inputNum(){
int num = 0;
printf("请输入您需要的功能(0~5):\n");
scanf("%d",&num);
return num;
}

void select(int num){
switch (num) {
case 1:
printf("进入注册功能\n");
registerUser();
break;
case 2:
printf("进入登录功能\n");
flag = isLogin();
break;
case 3:
printf("进入存钱功能\n");
save();
break;
default:
printf("您输入的数据有误,请重新输入\n");
break;
}
}
//向银行存钱
void save(){
//判断登录状态 登录成功才可以存钱,未登录不能存钱
if (flag) {
printf("开始存钱!...\n");
}else{
printf("未登录,请先登录!\n");
}
}

//注册一个用户
void registerUser(){
printf("注册一个用户:\n");
printf("输入一个用户名:\n");
scanf("%s",username);
printf("输入一个密码:\n");
scanf("%s",password);
printf("注册成功!\n");
}

//登录功能
int isLogin(){
printf("登录功能!\n");
printf("输入一个用户名:\n");
scanf("%s",inputUsername);
printf("输入一个密码:\n");
scanf("%s",inputPassword);
//和数据库进行匹配
if (strcmp(inputUsername, username)==0
&&
strcmp(inputPassword, password)==0) {
printf("登录成功!\n");
return 1;
}else{
printf("用户名或密码错误!\n");
return 0;
}
}

int main(int argc, const char * argv[])
{
//(高内聚 低耦合)->程序更灵活
while (1) {
//1.显示菜单
menu();
//2.输入选择的选项
int num = inputNum();
//3.输入不同的值,选择相应的功能
select(num);
}
return 0;
}
结果:
==================
系统功能
1.注册
2.登录
3.存钱
4.取钱
5.查看余额
0.退出
==================
请输入您需要的功能(0~5):
1
进入注册功能
注册一个用户:
输入一个用户名:
fcp
输入一个密码:
lbm
注册成功!
==================
系统功能
1.注册
2.登录
3.存钱
4.取钱
5.查看余额
0.退出
==================
请输入您需要的功能(0~5):
3
进入存钱功能
未登录,请先登录!
==================
系统功能
1.注册
2.登录
3.存钱
4.取钱
5.查看余额
0.退出
==================
请输入您需要的功能(0~5):
2
进入登录功能
登录功能!
输入一个用户名:
fcp
输入一个密码:
lbm
登录成功!
==================
系统功能
1.注册
2.登录
3.存钱
4.取钱
5.查看余额
0.退出
==================
请输入您需要的功能(0~5):

9.字符串数组
有两种形式,字面值字符串数组,数组字符串数组。
字面值字符串数组中的字符串是不能改变的。
数组字符串数组中的字符串是可以改变的。

作业:
a.有五虎上将,zhangfei、guanyu、huangzhong、zhaoyun、machao。
输入一个人名,判断是否是五虎上将?
#include <stdio.h>
#include <string.h>

int main(int argc, const char * argv[]) {
char* tigger[5]={"zf","gy","hz","zhy","mc"};
char username[10];
printf("请输入一个人名!\n");
scanf("%s",username);
for (int i=0; i<5; i++) {
if (strcmp(username,tigger[i])==0) {
printf("%s是五虎上将",username);
}
}

return 0;
}
结果:
请输入一个人名!
gy
gy是五虎上将
b.输入三个人的姓名,并保存?
char usernames[3][20];
//输入三个人的姓名
for (int i = 0; i<3; i++) {
printf("请输入第%d个人的名字:\n",i+1);
scanf("%s",&usernames[i][0]);
}
//输出三个人的姓名
for (int i = 0; i<3; i++) {
printf("第%d人的名字:%s\n",i+1,&usernames[i][0]);
}
结果:
请输入第1个人的名字:
fcp
请输入第2个人的名字:
lbm
请输入第3个人的名字:
wjy
第1人的名字:fcp
第2人的名字:lbm
第3人的名字:wjy

知识点
十八、一些计算机操作指令

1.const关键字
1.可以把一个变量,变成常量
2. 由于指针变量相当于两个值:
指针的值  int* const p
指针指向的值 const int* p
3.  有些函数在使用内存地址是,希望内存中的数据是只读的,不需修改,就会加上const关键字
const int i=10;//将变量->常量
//i=20;
printf("i:%d\n",i);

int j=20;
int k=30;
int* p=&j;
//指针的值  int* const p
p=&k;
//指针指向的值 const int* p
*p=40;
printf("k:%d",k);
结果:
i:10
k:40

2.命令行参数
./a.out 640*480->main()……
main(参数1:长度,参数2:值)
数组中第一个内容是命令 …
3.预处理指令

#预编译指令
在编译之前做的事情:
例:1.导入头文件...
2.条件编译....
#ifndef    ZBS
没有条件编译此处
#else
有条件编译此处
#endif
编译:gcc main.c—DZBS
./a.out
#ifdef SIZE //如果定义了SIZE宏条件成立
#ifndef SIZE //如果没定义SIZE宏条件成立              #if 1==1 //条件成立 #if 条件表达式或逻辑表达式
#include <stdio.h>

int main(int argc, const char * argv[]) {
int num=0;
printf("轻点菜:");
scanf("%d",&num);
#ifndef ZBS
if (num==1) {
printf("您点的是鱼香肉丝\n");
}else if (num==2){
printf("您点的是地三鲜\n");

}else {
printf("没有这个菜\n");

}
#else
if (num==1) {
printf("没有这个菜\n");
}else if (num==2){
printf("没有这个菜\n");

}else {
printf("真没有这个菜\n");

}
#endif
return 0;
}
结果:gcc main.c—DZBS就执行else的代码

3.宏…  (#define  PI …)
1.把复杂的操作变得更简单 ,不会改变原代码
2.宏与变量最大的区别,不占内存空间,当编译前会自动替换代码中的变量
3.宏的值一旦确定是不可改变的
#include <stdio.h>
//#预编译指令 PI文本标识  3.1415926替换内容
//宏与变量最大的区别,不占内存空间,当编译前会自动替换代码中的变量
#define PI 3.1415926//PI宏的文本

int main(int argc, const char * argv[]) {
//圆的面积=派*r*r;
int r=0;
printf("请输入一个半径:\n");
scanf("%d",&r);
//printf("圆的面积为:%lf\n",3.1415926*r*r);
printf("圆的面积为:%lf\n",PI*r*r);
return 0;
}
结果:
请输入一个半径:
8
圆的面积为:201.061926

4.宏可以和数组搭配使用
#define SIZE 6
int main(int argc, const char * argv[]) {

int a[SIZE]={0};
5.宏函数
与内存空间没有关系 跟类型与没有关系
#include <stdio.h>
#define MUL(x,y)x*y
int i=10;
int j=20;
printf("i:%d*j:%d=%d",i,j,i*j);
printf("%d\n",MUL(i,j));
printf("%d\n",MUL(2+3,4+5));//2+3*4+5
printf("%d\n",21/MUL(2+3,4+5));//21/2+3*4+5
结果:
i:10*j:20=200
200
19
27

练习:
1.输入一个字母将小写->大写…
2.条件编译
iphone4
iphone5~5s
iphone6
iphone6plus
ipad1~4
ipad mini

知识点
十九、大型软件开发
1.多文件编程
当程序较大时,为了提高可读性,一般将程序拆分成多个文 件,每个文件负责一个功能块
2.多文件编程的操作步骤
多人开发  将原文件拆分成三个文件,分别为*.h、*.c、 main.c
例:输入一个数并输出
1.输入功能拆分放到两个文件中
.h函数的声明
.c函数的定义
2.使用前必须导入头文件
3.编译的时候,必须连接
系统的函数库已经默认与程序连接到了一起
连接:将多个文件的的目标文件合在一起,就是连接
gcc -c input.c 目标文件->*.o
如: gcc -c  input.c转成input.o
gcc 目标文件1 目标文件2....->a.out
如:gcc  input.o  main.o——>./a.out——-得到编译结果
’           总:1.只有.h 和.o别人可以使用你的函数了,但无法得到源代码。闭源
2 .h 和.c别人可以使用你的函数了,并且知道你是如何实现的。开源
3.在多文件开发中
.h文件中 ,主要放的是函数声明、宏,但不能放变量的声明,一切与内存有关的操作都不可以
.c文件中,主要放程序源代码,变量的声明、函数的定义..
全局变量只能放在.c文件中
**如果想使用其他文件中的全局变量必须使用extern关键字修饰。
extern  int  array;
**使用static修饰全局变量,该全局变量只能在当前文件中使用(私有)
static不但可以修饰全局变量,还可以修饰函数
4.批处理命令:make

知识点
二十、结构体

• 结构体语法格式 
1.struct{ 
      成员;       
   }变量名; 
2.typedef  struct  {  //常用格式
      int  age;//成员               
char  name[20]; 
   }Student2;//别名 
例: (标准定义)
//给类型(定义)起名字
typedef struct {
int age;//成员
char sex;
}NewPerson2;//新名字 //变量名
NewPerson2 person5 = {22,'F'};
//结构体如果声明在函数的外部,所有函数都可以使用
NewPerson2 person6 = {23,'M'};
printf("age5:%d sex5:%c\n",person5.age,person5.sex);//取值
printf("age6:%d sex6:%c\n",person6.age,person6.sex);//取值
结果:
age5:22 sex5:F
age6:23 sex6:M

*结构体其他表示方法
一、//数据结构 人的信息(年龄,性别)
struct{
int age;//成员
char sex;
}person1,person2={19,'F'};//变量名
person1.age = 18;//赋值
person1.sex = 'M';
printf("age:%d sex:%c\n",person1.age,person1.sex);//取值
printf("age2:%d sex2:%c\n",person2.age,person2.sex);//取值
//int i
//i = 10;
//int i = 10;
//给结构起个名字 struct Person == int
二、   struct Person{
int age;
char sex;
};

//struct Person person3 = {20,'M'};
struct Person person3;
person3.age = 21;
person3.sex = 'F';
printf("age3:%d sex3:%c\n",person3.age,person3.sex);//取值

三、    //给类型起名字 typedef 原来的名字 新名字
typedef struct Person NewPerson;
NewPerson person4 = {22,'M'};
printf("age4:%d sex4:%c\n",person4.age,person4.sex);//取值

结果:
age:18 sex:M
age2:19 sex2:F
age3:21 sex3:F
age4:22 sex4:M

2.结构体所占内存空

//结构体所占内存空
typedef struct{
char ch;//1
short i;//2
} Stu;
printf("Stu size:%ld\n",sizeof(Stu));
结果:
Stu size:4

作业:
练习:创建四个学生信息(学号、姓名、性别、年龄),所有的信息要使用键盘输入并保存。
typedef struct{
int num;
char name[10];//保存字符串的内容
//char *cp;//保存字符串的地址
char sex;
int age;
} Student;
Student stus[4];
for (int i = 0; i<4; i++) {
printf("请输入学号:\n");
scanf("%d",&stus[i].num);
printf("请输入姓名:\n");
scanf("%s",stus[i].name);
scanf("%*c");
printf("请输入性别:\n");
scanf("%c",&stus[i].sex);
printf("请输入年龄:\n");
scanf("%d",&stus[i].age);
}

for (int i = 0; i<4; i++) {
printf("学号:%d\n",stus[i].num);
printf("姓名:%s\n",stus[i].name);
printf("性别:%c\n",stus[i].sex);
printf("年龄:%d\n",stus[i].age);
}

知识点
二十一、联合、枚举

一、联合
1. 联合的用法、语法和结构非常相似,但联合中所有成员分配 的内存是同一块。(只能保存一个 成员信息,联合的空间以 最大成员所占的空间为值)   
2. 联合可以用一块内存对应多种数据类型  
   3. 联合与结构的区别,结构可以保存多个成员信息,而联合只能保存一个成员信息且最后一个

#include <stdio.h>

typedef union{ //联合语法格式
int i;
char ch;

}LianHe;

int main(int argc, const char * argv[])
{
printf("LianHe:%ld\n",sizeof(LianHe));
LianHe lh;
lh.i=10;
printf("i:%d\n",lh.i);
lh.ch='a';
printf("ch:%c\n",lh.ch);
printf("i:%d\n",lh.i);

return 0;
}
结果:
LianHe:4
i:10
ch:a
i:97

二、枚举

1.语法格式:
//定义一个枚举
enum{MON,TUE,WEN};
或
//typedef 类型名字  新名字
typedef enum{  //常用类型
MON,TUE,WEN
}week;

2.在声明的时候修改枚举值
//如果需要修改枚举值 只能在声明的时候修改
//后面的元素=前面的元素+1
1. typedef enum{
MON=1,TUE,WEN
}week;
结果:
MON:1
TUE:2
WEN:3
2. typedef enum{
MON,TUE=2,WEN
}week;
结果:
MON:0
TUE:2
WEN:3

3.typedef enum{false,true} bool;
bool b1 = false;
printf("b1:%d\n",b1);
结果:0

练习:
#include <stdio.h>

//定义一个枚举
//enum{MON,TUE,WEN};

//typedef 类型名字  新名字
//如果需要修改枚举值 只能在声明的时候修改
//后面的元素=前面的元素+1
typedef enum{
MON=1,TUE,WEN
}week;

void take(week i){
switch (i) {
case MON:
printf("星期一:要去交水费\n");
break;
case TUE:
printf("星期二:要去交电费\n");
break;
case WEN:
printf("星期三:要去交煤气费\n");
break;
default:
break;
}
}

int main(int argc, const char * argv[])
{
printf("MON:%d\n",MON);
printf("TUE:%d\n",TUE);
printf("WEN:%d\n",WEN);

int week=0;
printf("请选择今天星期几:\n");
printf("1.星期一\n");
printf("2.星期二\n");
printf("3.星期三\n");

scanf("%d",&week);
take(week);
return 0;
}
结果:
MON:1
TUE:2
WEN:3
请选择今天星期几:
1.星期一
2.星期二
3.星期三
1
星期一:要去交水费

练习
输入一个整数,求春夏秋冬   
       用户从控制台输入一个整数,由程序判断该整数是春 夏秋冬哪个季节。春夏秋冬分别用一个枚举常量表示
#include <stdio.h>

typedef enum{
SPRING,SUMMER,AUTUMN,WINTER
}Season;

void func(int num){
switch (num%4) {
case SPRING:
printf("春天来了!\n");
break;
case SUMMER:
printf("夏天来了!\n");
break;
case AUTUMN:
printf("秋天来了!\n");
break;
case WINTER:
printf("冬天来了!\n");
break;

default:
break;
}

}

int main(int argc, const char * argv[])
{   int num=0;
printf("请输入任意一个整数数字:");
scanf("%d",&num);
func(num);
结果:
请输入任意一个整数数字:897231
冬天来了!

知识点
二十二、高级指针

一.双指针(二级指针)
#include <stdio.h>
void change(int j){//值传递
j = 20;
printf("j:%d\n",j);
}
void change2(int* p){//地址传递
*p = 20;
printf("*p:%d\n",*p);
}
/*
char** change3(){
char* str = "Hello";
return &str;
}
*/
void change4(char** p){
*p = "Hello";
}
int main(int argc, const char * argv[])
{
int i = 10;
//change(i);
change2(&i);
printf("i:%d\n",i);
char *p;//保存一个字符串的位置
change4(&p);
printf("p:%s\n",p);
return 0;
}
结果:
*p:20
i:20
p:Hello

二、void指针

1.任意类型的指针
2.malloc分配堆内存时,由于无法确定内存存储类型,所以可 以使用void*代表任意指针类型
#include <stdio.h>
typedef enum{INT,CHAR,FLOAT,DOUBLE} type;
void output(void* p,type t){
switch (t) {
case INT:
//char c = (char)200;//类型转换
printf("%d\n",*((int*)p));
break;
case CHAR:
printf("%c\n",*(char*)p);
break;
case FLOAT:
//char c = (char)200;//类型转换
printf("%f\n",*((float*)p));
break;
case DOUBLE:
printf("%lf\n",*(double*)p);
break;
}
}
int main(int argc, const char * argv[])
{
int i = 10;
output(&i,INT);
char c = 'a';
float f = 10.1f;
double d = 20.1;
output(&f,FLOAT);
return 0;
}
结果:
10
10.100000

三、函数指针
#include <stdio.h>
//1.返回值类型
void func(){
printf("Hello, World!\n");
}
//2.
int func2(){
return 10;

}
//3.
int func3(){
return 1;

}
int main(int argc, const char * argv[])
{    printf("%p\n",&func);
printf("%p\n",func);
//函数指针变量*funcp 保存函数指针 func
//1.返回值类型....参数...
void(*funcp)()=func;//调用没有括号func
funcp();
//2.
int(*funcp2)()=func2;
int i=funcp2();
printf("i:%d\n",i);
//3.
int(*funcp3)(int)=func3;
int i2=funcp3(5);
printf("i2:%d\n",i2);

return 0;
}
结果:
0x100000e40
0x100000e40
Hello, World!
i:10
i2:1

四、对内存管理

1.malloc函数
a.导入头文件
#include <stdlib.h>
b.分配一个堆内存的空间,可以根据参数大小分配相应内存空间
空间的首地址  malloc(空间大小)
语法:void*malloc(4);//字节
c.分配变量
int  *p;   p  =  (int*)malloc(sizeof(int));
练习:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{   //输入三个数并输出
int a[3]={0};//栈
printf("a address:%p\n",a);
//开辟堆空间 void*malloc(size_t)
//堆内存的分配不一定成功
//如果成功则得到一个地址,如果不成功得到NULL
int*p;//分配变量
p=(int*)malloc(sizeof(int)*3);//语法格式
if (p!=NULL) {
//使用前做类型转换
printf("p address:%p\n",p);
for (int i=0; i<3; i++) {
printf("请输入%d第个数:",i+1);
//scanf("%d",&a[i]);
scanf("%d",(p+i));
}

//输出函数
for (int i=0; i<3; i++) {
//printf("第%d个数为:%d\n",i+1,a[i]);
printf("第%d个数为:%d\n",i+1,*(p+i));
}
}
else{
printf("分配内存失败");

}
return 0;
}
结果:
a address:0x7fff5fbff83c
p address:0x100103b10
请输入1第个数:3
请输入2第个数:5
请输入3第个数:6
第1个数为:3
第2个数为:5
第3个数为:6

2.calloc函数
a.分配一个堆内存空间
b.#include <stdlib.h>
c.空间的首地址 calloc(元素的个数,元素的大小)
语法:void*calloc(4,size(int));
calloc与malloc的区别是,不但分配内存空间,而且还会将分配到的内存空间清0
//开辟堆空间 void*calloc(size_t,size_t)
//参数1 元素的个数 参数2 元素的类型
int*p;//分配变量
p=(int*)calloc(3,sizeof(int));
以上输入输出函数程序只改变此句,结果不变

3.realloc函数
调整一个内存空间,存在两种情况,如果原来的位置可以调整,则首地址不变。如果原来的位置不可以调整,创建一个新的内存空间,并将原来数据自动复制过来,将原来的内存自动销毁,返回新的内存的首地址。调整内存空间也可能有风险,即创建不成功。
a.空间的首地址 realloc(原来首地址,调整后的空间大小)
void* realloc(p,sizeof(int)*5);
b.调整内存空间也不一定成功,所以尽量创建一个新的变量来保存。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{
//输入三个数,保存并输出
int array[3]={0};//栈
printf("array address:%p\n",array);
//开辟堆空间 void* calloc(size_t,size_t)
//叁数1 元素的个数 参数2 元素的类型
//堆内存分配不一定成功
//如果成功则得到一个地址,如果不成功得到NULL
int* p = (int*)malloc(sizeof(int)*3);
printf("p address:%p\n",p);
//调整内存空间 参数1 原来空间的首地址 参数2 调整后的大小
int* p2=(int*)realloc(p,sizeof(int)*4);
printf("p2 address:%p\n",p2);
if (p2!=NULL) {//分配内存成功
p = p2;//分配成功后,如果得到新的地址,会自动将原来的销毁。
printf("p address:%p\n",p);
//使用前做类型转换
for (int i = 0; i<4; i++) {
printf("请输入第%d个数:\n",i+1);
//scanf("%d",&array[i]);
scanf("%d",(p+i));
}
for (int i = 0; i<4; i++) {
printf("第%d个数:%d\n",i+1,*(p+i));
}
}else{
printf("分配内存失败!\n");
}
free(p);//释堆空间
//野指针:一个指针指向一个不合法区域
p = NULL;//空指针 用来解决野指针
//在OC访问一个空指针是合法并且不会报错
//printf("p->value:%d\n",*p);
//printf("p address:%p\n",p);
return 0;
}
结果:
array address:0x7fff5fbff82c
p address:0x100103b10
p2 address:0x100103b10
p address:0x100103b10
请输入第1个数:
6
请输入第2个数:
4
请输入第3个数:
3
请输入第4个数:
4
第1个数:6
第2个数:4
第3个数:3
第4个数:4

4.free函数
可以将堆空间销毁掉(释放)
free(堆空间首地址);
销毁堆空间时,指针变量依然是有值的,但是指向了一个不合法的内存区域,野指针。当程序对野指针进行操作是不合法的,会报错的。标准的做法,将野指针赋NULL值,变成空指针。在OC当中,就可避免操作问题,并且不会报错。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: