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当中,就可避免操作问题,并且不会报错。
相关文章推荐
- C语言实现用星号在屏幕上打印菱形
- C语言函数不能返回局部变量的地址
- Leetcode 2 - Add Two Numbers
- Leetcode 1 - Two Sum
- C++11 gcc升级到5.2.0后报错:/usr/lib64/libstdc++.so.6: version 'GLIBCXX_3.4.17' not found
- 指定输入一组数
- C++中sort和qsort的用法
- 高质量C++编程之第2章 程序的版式
- C语言strerror()函数:返回错误原因的描述字符串
- C++异常规范
- effective c++学习笔记
- C++ 多态之继承2-继承的相关基础
- c++在vs2012中链接mysql操作
- C++模板:函数模板和模板函数 .
- 静态检测工具-cppcheck
- OC语言-02面向对象的三大特性
- 解决C/C++ 头文件相互包含 问题的方法
- [转][C/C++] 怎样不用中间变量temp 实现两个数交换
- C++常用库函数
- C++中public,protected,private访问