编辑器:程序员写代码的过程(记事本、VC6.0、vim…)(让程序员看懂)
编译器:查看代码的语法错误,生成汇编语言。
汇编器:将生成好的汇编语言生成二进制语言(也叫做目标文件)
连接器:将生成好的二进制语言+用到的库+启动代码=====>可执行文件
Visual C++6.0下载地址:https://pan.baidu.com/s/1UoyJD6FUARS2EvDdC9l7qA 提取码: 1314.
解压单击安装即可,默认下一步
打开VC6.0,关闭每日提示
文件——》新建——》工程——》win32 console Application控制台程序——》确定
从0开始学,选择一个空工程——》完成
单击FileView就可以看到工程的目录结构
文件——》新建——》文件——》C++ Source File——》写文件名(后缀名为.C,若不写则默认为.cpp为C++源文件)——》确定
# include //std是标准的意思 i表示输入 o表示输出(标准的输入输出头文件)
// 双斜杠//是行注释 /**/是块注释,注意块注释不能嵌套
//()里面的是函数的形参(函数外部将数据传递到函数内部的桥梁)
int main(int argc, char *argv[])
//main主函数 是程序的入口,有且仅有一个主函数
//main左边的int代表的是函数的返回类型
{
// 使用任何东西 必先存在
printf("hello iot\n");// printf来自系统库文件,printf:将双引号的字符串输出(o)到终端上
return 0;//0是一个int类型
}
//{}函数的功能都在大括号里面实现,每敲一行代码记得用tab缩进,不要用空格
//分号是C语言的结束标记
//如果你的代码一闪而过 可以用带阻塞的代码 getchar();
// int char return都是关键字
总结:
1、main有且只有一个
2、printf的头文件是stdio.h
3、注释 行注释和块注释(块注释不能嵌套)
调整VC6.0字体大小:工具——》选项——》三角符号往后点有个格式——》选择原窗口——》选择合适大小
知道的条件:半径r
算法:面积=πrr
解析步骤:
①r通过键盘输入或者用特定的值
②定义一个面积变量 area=πrr
③将圆的面积输出到终端上
# include
# define PI 3.14 //定义一个宏 建议用大写表示(和普通变量区分开)
int main(int argc,char *argv[])
{
float r=0.0f;//定义一个r变量 系统给r开辟4字节的空间
float area=0.0f;//定义一个面积变量
//获得半径 从键盘获得scanf(要使用必先存在)
printf("请输入圆的半径r:");
scanf("%f",&r); //对r变量取地址 scanf是带阻塞的
//测试
//printf("r=%f\n",r);//测试有没有得到r
//算法:计算面积 area=PI * r * r 要使用面积就要先存在
//float area=0.0f; //在VC6.0中不能这样定义(必须在语句的前方),在visual studio就没有这个问题
area=PI*r*r;
//将面积输出 %.2f中的.2表示小数部分保留两位
printf("area=%.2f\n",area);
return 0;
}
//不同的代码之间一定要空个行,这样代码更整洁
步骤分析:
1、定义两个变量data1、data2 获取键盘输入
2、定义一个函数 去计算上面两个变量data1、data2的和
在函数内部计算计算(怎么将数据传递到函数内部?)
需要用形参 将data1 data2传递到函数内部
3、得到函数的计算结果(怎么得到呢?)
通过函数的返回值 得到函数的计算结果
#include
int add_fun(int a,int b) //ret是整型 data1和data2也是整型
{
return a+b;
}
int main(int argc, char *argv[])
{
//定义两个变量 获取键盘输入
//int data1=0;
//int data2=0;
int data1=0,data2=0;
int ret=0; //定义一个ret去存放函数结果
printf("请输入两个int变量:");
scanf("%d %d",&data1,&data2);//门牌号?
//函数的调用
ret=add_fun(data1,data2);// a=data1 b=data2
//输出ret的结果
printf("ret=%d\n",ret);
return 0;
}
数据分为不同类型 是为了 更加合理的利用内存空间
计算机存储的是二进制,一位二进制只能存放0或者1(低电平或高电平)
1byte=8bit (0000 0000~ 1111 1111)
1kb=1024byte 10月24日是程序员节
1MB=1024kb
1GB=1024MB
1TB=1024GB
1PB=1024TB
1EB=1024PB
-----------------------------------在32位平台-----------------------------------------
char 字符类型 占1个字节 (8个二进制位)
short 短整型 占2个字节 (16个二进制位)
int 整型 占4个字节(32个二进制位)
long 长整型 占4字节空间(32个二进制位)
float 单精度浮点型 占4字节空间(32个二进制位)
double 双精度浮点型 占8字节空间(64个二进制位)
-----------------------------------在64位平台-----------------------------------------
char 字符类型 占1个字节 (8个二进制位)
short 短整型 占2个字节 (16个二进制位)
int 整型 占4个字节(32个二进制位)
long 长整型 占8字节空间(64个二进制位)
float 单精度浮点型 占4字节空间(32个二进制位)
double 双精度浮点型 占8字节空间(64个二进制位)
sizeof是测量类型的长度
#include
int main(int argc,char *argv[])
{
printf("sizeof(char)=%d\n",sizeof(char));
printf("sizeof(short)=%d\n",sizeof(short));
printf("sizeof(int)=%d\n",sizeof(int));
printf("sizeof(long)=%d\n",sizeof(long));
printf("sizeof(float)=%d\n",sizeof(float));
printf("sizeof(double)=%d\n",sizeof(double));
return 0;
}
数据没有符号位,自身所有二进制位都是数据位
比如:unsigned char ——》 0000 0000~ 1111 1111
二进制的最高位为符号位,其他为是数据位
signed char ——》 xxxx xxxx(x为0或1)
最高位为1表示负数,最高位为0表示正数
比如:一个字节: -10==1000 1010
案例:
#include
int main(int argc,char *argv)
{
//定义一个有符号int
signed int num1=10; //系统给num1开辟4字节的空间(这个4字节的最高位是符号位)
// signed 默认是省略的(推荐)
int num2=10; //num2也是有符号数
//unsigned表示无符号数 不能省略
unsigned int num3=10;
return 0;
}
struct data1{
char a;
short b;
int c;
};
a b c就是结构体data1中的成员
union data2{
char a;
short b;
int c;
};
1、enum枚举 将变量要赋值的值一一列举出来
enum BOOL(false,true);
enum BOOL bool=false;
2、void 无类型 (重要)
不能用void定义变量
int num; // √
void num; //X 系统不能确定给num开辟多大的空间
auto 自动类型 ,register 寄存器变量,static 静态变量,const 只读变量
sizeof 测类型的大小
typedef 为已有的类型 重新取一个别名
volatile 防止编译器优化
总结:
1、如果没有显示表明register,就类似int num,如果num被高频繁使用系统也会放入寄存器中。
2、register int num; //显示的将num放入寄存器中
3、寄存器的变量不能取地址 &num(X)
#include
int main(int argc,char *argv[]){
register int num=10;
// %p输出地址
printf("%p\n",&num); //**错误**,不能对寄存器变量 取地址
//我们讲的是内存地址,寄存器已经不在内存中,怎么取地址?
return 0;
}
#include
void test01()
{
register int num=10;
// %p输出地址
//printf("%p\n",&num); //**错误**,不能对寄存器变量 取地址
}
typedef int INT32; //给已有的int类型 取了一个别名叫INT32
void test02()
{
int num1=10;
INT32 num=20;
printf("num1=%d\n",num1);
printf("num2=%d\n",num2);
}
int main(int argc,char *argv[]){
test02();//想运行那个就写哪个
return 0;
}
10 20 4.14 ‘a’ “abv”
变量名num代表的是空间的内容
操作变量名就是对空间 内容 的操作
变量名的命名规则:由数字字母下划线组成,但是不能以数字开头
建议:小写英文字母 + "_"线 构成(C语言命名风格)
C++一般用小驼峰法命名:numName
十进制: 0~9
八进制:0~7
十六进制:0 ~ 9 ,a ~ f
八进制 十进制 十六进制都是整型的输出形式
十进制输出 %d %u %ld %lu
八进制输出 %o
十六进制输出 %x
八进制是以0开头
printf("八进制:num=%#o\n",num); //0144
十六进制是以0x开头
printf("十六进制:num=%#x\n",num); //0x64
不同的进制仅仅是数据的表现形式, 并不能修改数据本身
void test01()
{
//在大括号内部定义的变量叫局部变量(局部变量不初始化,内容随机)
int data=0;
int num=0;
printf("num=%d\n",num);// 读操作 取值
//写操作 赋值
num=100;
printf("num=%d\n",num);
data=num; //将右边的值赋值给左边 ,对于num来说是读取它的值100(读操作),赋值给data(写操作)
printf("data=%d\n",data);
//获取键盘输入
printf("请输入一个int数据:");
scanf("%d",&data); //&data 代表的是data空间的起始地址
printf("data=%d\n",data);
}
void test02()
{
int num1=0;
//%d 有符号int数据输出
printf("num1=%d\n",num1);
unsigned int num2=0;
//%u 无符号int数据输出 (u是unsigned的简写)
printf("num2=%u\n",num2)
long num3=0;
//%ld 有符号long型数据输出
printf("num3=%ld\n",num3);
unsigned long num4=0;
//%lu 无符号long型数据输出
printf("num3=%lu\n",num4);
long long num5=0;
//%ld 有符号long long型数据输出
printf("num3=%lld\n",num3);
unsigned long long num6=0;
//%lu 无符号long long型数据输出
printf("num3=%llu\n",num4);
//注意:VC6.0不支持long long但在其他集成环境支持
short num7=0; //short本来就是整型,所以一般不写int
// %hd是有符号short数据输出
printf("num7=%hd\n",num7);
short num8=0; //short本来就是整型,所以一般不写int
// %hu是无符号short数据输出
printf("num8=%hu\n",num8);
}
unsigned short num6=0;
scanf(“num6=%hu\n”,num6); //输入
x
注意:赋值语句 等号 两边类型尽量保证一致
%lf double型浮点型
加f的是float类型,不加f的是double类型
void test03()
{
//不以f结尾的实型常量 为double类型
printf("sizeof(3.14)=%d\n",sizeof(3.14));//8byte
//sizeof针对于变量可以不加小括号,针对类型要加小括号
//为了通用 最好都加小括号
//以f结尾的实型常量 为float类型
printf("sizeof(3.14)=%d\n",sizeof(3.14f));//4byte
float f=3.14; //有没有问题? 赋值语句要保证两边类型相同
// f是float类型4字节 3.14是double类型 8字节
//把8字节赋值给4字节(这样赋值是有问题的) float f=3.14f;(√)
//%f输出 float数据
printf("f=%f\n",f);
//%lf 输出 double数据
double d=3.14;
printf("%d=%lf\n",d)
scanf("%f",&f);
scanf("%lf",&d);
}
float类型占四个字节
double类型占八个字节
直接常量:用单引号括起来,如:‘a’ 、 ‘b’ 、‘12’等
转义字符:以反斜杠\开头,后面跟一个或者几个字符,如’\n’ '\t’等,分别代表换行、横向跳格
void test01()
{
// %c输出的是字符
printf("%c\n",'a');//字符常量
//字符变量
//ch存储的是'a'的ASCII值
char ch='a';
// %c 输出的是符号本身
printf("ch=%c\n",ch);// ch=a
// %d 输出的是字符的ASCII值
printf("ch=%d\n",ch);// ch=97
// 'a' 单引号表示取字符的ASCII
// 'a'==97是完全等价
ch=97;
printf("ch=%c\n",ch); //ch=a
printf("ch=%d\n",ch); //ch=97
ch=ch+1;
printf("ch=%c\n",ch); //ch=b
printf("ch=%d\n",ch); //ch=98
}
ASCII码表:
总结:
1、‘a’ 单引号表示取a的ASCII值
2、字符在计算机中存储的是ASCII
3、‘a’==97
思考:
char ch='a';
printf("%d\n",sizeof('a'));//4byte sizeof测量的是小括号里面类型的长度
printf("%d\n",sizeof(char));//1byte 为什么?
‘a’,单引号是取字符的ASCII值——》97,本质是sizeof(97); 97是int类型,所以是4byte。
字符类型如何去获取键盘输入呢?
void test03()
{
char ch;
printf("请输入一个字符");
//字符变量获取键盘输入
scanf("%c",&ch);//scanf中%c只能**提取一个字符**
printf("ch=%c\n",ch);//输出字符用%c
printf("ch=%d\n",ch);//输出ASCII用%d
//ch=getchar();//这也是获取一个字符,把值赋给变量ch
//getchar是一个函数调用,其实scanf也是一个函数调用
}
char ch1,ch2;
printf("请输入abc:");
//提取a
ch1=getchar();
getchar();//丢弃一个字符
ch2=getchar();//提取c
printf("ch1=%c\n",ch1);
printf("ch2=%c\n",ch2);
// '\n'换行 '\t' tab
//printf("##%c##\n",'\\');//两个反斜杠输出一个反斜杠
//printf("#%%90#\n");//两个百分号输出一个百分号
//ABCD中哪两个相等?BC
//判断哪两个相等,其实就是查看这两个在计算机中存放的ASCII值是不是一样
printf("A:%d\n",'0');//字符0的ASCII是48 字符本质存放的就是ASCII
printf("B:%d\n",'\0');//’\0‘的ASCII值是0
printf("C:%d\n",0); //0
printf("D:%d\n","0");//字符串0 取的是字符0的地址
%s的本质作用就是:从字符串的首元素地址开始,逐个字符输出,遇到’\0’自动结束输出(重要)
void test06()
{
//%s就是输出字符串
//''取的是字符的ASCII值,双引号取的是字符串的首元素的地址
//%s的本质作用就是:从字符串的首元素地址开始,逐个字符输出,遇到'\0'自动结束输出(重要)
printf("%s\n","hello world");
//系统会在字符串末尾自动添加一个结束字符'\0'
printf("%d\n",sizeof("hello world"));//12byte 因为字符串默认以反斜杠0结尾
printf("%s\n","hello\0world");//只能输出hello
printf("##%s##\n","\0hello\0world");//####
}
int main(int argc,char *argv[]){
test06();
return 0;
}
请描述‘a’和“a”的区别:
1、单引号a只占一个字节,双引号a占2个字节(一个字节存放字符a,一个字节存放\0)
2、'a’取的是字符a的ASCII值,双引号a取的是字符串a的首元素的地址
printf("%d\n",sizeof("ab"));//3byte ——》‘a’‘b’‘\0’
"ab"作为类型代表的的字符串占空间的大小
“ab”作为地址 代表的是字符串 首元素 的地址
格式化输出字符:
%d 十进制有符号整数
%x 以十六进制表示的整数
%f float型浮点数
%e 指数形式的浮点数
%c 单个字符
%u 十进制无符号整数
%o 一八进制表示的整数
%lf double型浮点数
%s 字符串
%p 指针的值
特殊应用:
%3d , %03d , %-3d , %5.2f
void test07()
{
printf("##########\n");
//%5d表示占五个终端位宽 右对齐
printf("##%5d##\n",123);
//%-5d表示占五个终端位宽 左对齐
printf("##%-5d##\n",123);
//%05d表示占五个终端位宽 右对齐 不足补0
printf("##%05d##\n",123);
//千万不能写 %-05d(不起作用)
printf("##%-05d##\n",123);
//%5.2f 5表示总位宽为5 .2表示小数位保留两位
printf("%5.2f\n",3.14159f);
}
为已有的类型重新取个别名
★步骤:
1、用已有的类型定义一个变量
2、用别名替换变量名
3、在整个表达式的前方加上typedef
案例1
int INT32
typedef int INT32;
案例2:给int arr[5]取个别名
int arr[5] //用已有的类型定义一个变量
typedef int ARR[5];//用别名替换变量名
ARR arr;//arr就是一个拥有5个int元素的数组
int data1=-20;
unsigned int data2=10;
//有符号数data1和无符号数data2进行转换的时候
//会先将data1转换为无符号(-20的补码——》很大的正数)
//很大的数 + 10 必然 >0
if(data1+data2>0)
{
printf(">0\n");// √
}
else if(data1+data2<0)
{
printf("<0\n");
}
运行结果是:大于0
int data1=10;
//int和double转换时,会将int转换为double
printf("%d\n",sizeof(data1+3.14));// double是8字节
char ch='a';
short data=20;
//由于char,short自身字节数过小,很容易溢出
//所以,只要char,short参与运算,都会将自身转换成int
printf("%d\n",sizeof(ch+ch));//4
printf("%d\n",sizeof(data+ch));//4
printf("%d\n",sizeof(data+data));//4
(类型说明符)(表达式)
例如:
(float)a;
(int)(x+y);
void test11()
{
float x=3.14f;
int j=0;
//j=x;//赋值时,等号左右两边类型要匹配, j只能拿x的整数部分
//强制类型转换,只是临时的转换,当前语句有效 在后面的语句中不会更改x的值
j=(int)x;
printf("j=%d,x=%f\n",j,x); //3
}
注意:无论是强制转换还是自动转换,都只是为了本次运算的需要,而对变量的数据长度进行临时性转换,而不改变数据定义的类型。
运算对象:常量、变量、函数(返回值)等
a/b (a,b都为整数) 取整
%取余
printf("%d\n",5/2);//2 取整 (5和2都为整数)
printf("%d\n",5%2);//1 取余
int num=0;
//键盘输入一个整数
printf("请输入一个整型数据:");
scanf("%d\n",&num);
//判断能否被3整除
if(num%3==0)
{
printf("ok\n");
}
else{
printf("no\n");
}
printf("%d\n",5/2);//如果反斜杠两边都是整数,就是单纯的取整 2
printf("%f\n",5/2.0f);//如果有浮点型,就是真正的除法 2.5
printf("%d\n",!1);//0
printf("%d\n",!0);//1
//C中0为假,其他都为真 -1也是真
printf("%d\n",!-1);//0
A&&B —— A、 B同时为真 则 整个表达式,AB只要有一个为假,结果就为假。
if((3>2) && (5>4))
{
printf("ok\n");//ok
}
else
{
printf("no\n");
}
逻辑与有短路特性
A&&B ——》如果发现A为假,系统不会判断执行B,这就是短路特性
A||B 只要AB任意一个为真,整个表达式都为真,AB同时为假的时候,结果才为假。
逻辑非也有短路特性:只要A为真,编译器不会判断B的真假
int num=10;
printf("比较之前num=%d\n",num);//10
(3>2) || (num=100);
printf("比较之后num=%d\n",num);//10 num=100得不到执行
语法:全1为1,其他为0
1010 1010
& 1111 0000
-------------------
1010 0000
特点:和1相与 保持不变,和0相与 清零
应用场景:将固定位清零
语法:有1就为1,全0才为0
1010 1010
| 1111 0000
-------------------
1111 1010
特点:和0相或 保持不变,和1相或置1
应用场景:将固定位置1
1010 1010
| 0000 1100
-------------------
1111 1010
语法:0变1,1变0
~ 1010 1010=0101 0101
应用场景:配合&|操作
语法:相同为0,不同为1
1010 1010
^ 0000 1111
-------------------
1010 0101
特点:和0异或保持不变,和1异或 取反
应用场景:将固定的位 发生高低电频翻转
1010 1010
^ 0000 0001
-------------------
1010 1011
(将二进制位向左移动)
注意:移动的位数不要超过自身长度
逻辑右移:右边丢弃,右边补0
算术右移:
①无符号数:右边丢弃,左边补0
②有符号数:
<1>正数:右边丢弃,左边补0
<2>负数:右边丢弃,左边补1
右移基本上是右边丢弃,左边补0
只有负数且算术右移,才会左边补1
逻辑右移和算术右移是编译器决定,但是我们可以检测。
作业:自己写代码,判断你的编译器是逻辑右移还是算术右移
char ch=0x85; // 1000 0101>>4
//逻辑右移:1000 0101>>4 == 0000 1000 ==0x08
//算术右移:1000 0101>>4 == 1111 1000 ==0xf8
ch=ch>>4;
printf("ch=%#x\n",ch);//0xf8是算术右移
//逻辑右移、算术右移是编译器决定的,我们只能测试,不能改变
综合案例:将data第1,5位清零(按位与),3、4位置1,其他位保持不变★
unsigned char data=0xaa; //1010 1010
//将data第1,5位清零
data = data & 1101 1101;// 与 完之后要赋值为data,才能更新它的值
1101 1101= ~(0010 0010)取反= ~(0010 0000 | 0000 0010)
0010 0000= 0000 0001 <<5
0000 0010= 0000 0001 <<1
所以:1101 1101= ~(0x01 <<5 | 0x01<<1)
data=data & ~(0x01<<5 | 0x01 <<1);//很清楚的能看出是第一位和第五位清零
第3、4位 置1
data=data | 0001 1000;
0001 1000 = 0001 0000 | 0000 1000=0x01<<4 | 0x01<<3
data = data | (0x01<<4 | 0x01<<3);
规律:只有按位与有取反,清零就 与、取反,后面第几位就写左移第几位;要置1,只写或,不写取反,里面第几位,就写左移第几位,每一位用或或上
表达式1 ? 值1:值2
语法:如果表达式1为真,那么整个表达式的值为“值1”,反之为“值2”
int ret=0;//最好先初始化再去赋值
ret=3>2 ? 5:6;
printf("ret=%d\n",ret);//ret=5
int data1=0;
int data2=0;
//赋值运算符和逗号运算符,逗号运算符优先级其实是最低的
data1=3,4,5,6;//先执行data1=3
data2=(3,4,5,6);//小括号优先级最高,逗号运算符结合性是从左往右,所以data2=6
printf("data1=%d\n",data1);//3
printf("data2=%d\n",data2);//6
+= 、 -= 、 = 、 /= 、%= 等等
a+=b ===》a=a+b
a * =b ===》a= a * b
注意:等号的右边必须看成一个整体
int data = 3;
//将等号右边看成一个整体
data *= 3+5;//data=data * (3+5);
printf("data=%d\n",data);//24
++i 或者 --i :先加、减 ,后使用
i++或者i–:先使用,后加、减
int i=3;
int j=0;
j=++i;//先加,后使用
//先执行i=i+1,i变为4;后执行j=i,4赋值给j,所以j也变成4
printf("i=%d,j=%d\n",i,j);//4,4
优先级高的先执行,同级别的优先级要看结合性
C语言运算符的优先级
自己写代码,尽量加小括号
if(表达式)
{
语句1;
}
表达式为真,才会执行语句1;
void test21()
{
int data=0;
printf("请输入一个int数据:");
scanf("%d",&data);
//判断能被2整除
if(data%2==0)//注意:这里不能写分号!
{
printf("能被2整除");
}
}
if(表达式)
{
语句1;
}
else
{
语句2;
}
表达式为真执行语句1,否则执行语句2
void test22()
{
int data=0;
printf("请输入一个int数据:");
scanf("%d",&data);
//判断data对2的余数(只有0,1两种情况)
if(data % 2==0)
{
printf("余数为0\n");
}
else
{
printf("余数为1\n");
}
}
if(表达式1)
{
语句1;
}
else if(表达式2) //if后面要加表达式
{
语句2;
}
else //可以省略
{
语句n;
}
只有表达式1位真,执行语句1,;只有表达式2位真,执行语句2;所有表达式都为假,才执行语句n。
void test22()
{
int data=0;
printf("请输入一个int数据:");
scanf("%d",&data);
//判断data对3的余数(有0,1,2三种情况)
if(data % 3==0)
{
printf("余数为0\n");
}
else if(data % 3==1)
{
printf("余数为1\n");
}
else if(data % 3==2)//其实这条语句可以直接写else,但是为了增加代码可读性,还是写else if吧
{
printf("余数为2\n");
}
}
注意:只有前面的条件不满足,才会判断后面的条件,如果前面的条件满足,后面的条件不管真假都不会执行。
if(表达式1)
{
语句1;
}
if(表达式2)
{
语句2;
}
if(表达式3)
{
语句3;
}
每个if语句都是独立的。
作业:键盘输入一个数,能否被3和7同时整除
switch(表达式)
{
case 值1: // 不能是实型、字符串,只能是整型和字符(本质是ASCII)
语句1;
break;
case 值2:
语句2;
break;
case 值3:
语句3;
break;
default: //可以省略
语句n;
break;
}
switch就是判断表达式的值是否和值1,值2,值3相等,来找到接下来程序的进入点。
int data=0;
printf("请输入一个int数据:");
scanf("%d",&data);
//判断data对3的余数(有0,1,2三种情况)
switch(data%3){
case 0:
printf("余数为0\n");
break;
case 1:
printf("余数为1\n");
break;
case 2:
printf("余数为2\n");
break;
}
void test23()
{
char ch=0;
printf("请输入你的方向:wasd\n");
ch=getchar();
switch(ch)
{
case 'w':
case 'W':
printf("向上移动\n");
break;
case 'a':
case 'A':
printf("向左移动\n");
break;
case 's':
case 'S':
printf("向下移动\n");
break;
case 'd':
case 'D':
printf("向右移动\n");
break;
}
}
for(初始语句; 循环条件 ; 步进条件)
{
//循环语句
}
//初始语句:只在循环开始时执行一次
//循环条件:每次循环都要执行,如果循环条件为真,进入循环体 如果为假,退出循环体
//步进条件:每次循环结束的时候要执行的语句
//1~100的和 1+2+3+4+...+100
int i =0;
int sum=0;
for(i=1;i<=100;i++)// i++ ==> i=i+1
{
sum=sum+1
}
printf("sum=%d\n",sum);
//1~100的和 1+2+3+4+...+100
int i =1;
int sum=0;
//如果变量提前初始化了,for循环的初始化语句可以省略
for(;;)//建议不要这么做
{
//如果for省略循环条件,必须在循环语句中实现退出循环的条件
if(i>100)
break;//跳出循环
sum=sum+i;
i++;//如果for省略步进条件,必须在循环语句中实现步进动作
}
printf("sum=%d\n",sum);
void test26(){
for(;;)
{
for(;;)
{
break;//只能跳出离他最近的一层循环
}
}
}
continue:结束本次循环,立即从当前位置直接进入下一次循环
作业:
1、求出1~100中能被7整除的数。
//求0 2 4 6...100的和
int i=0;
int sum=0;
for(;i<=100;i=i+2)//步进条件不是单纯的i++
{
if(i==50)
continue;//结束本次循环,立即从当前位置直接进入下一次循环
sum+=i;
}
printf("sum=%d\n",sum);//2550
break语句用于跳出本层循环
continue用于结束本次循环
//外层循环的次数 * 内层循环的次数 == 总循环次数
void test28(){
int i=0;
int j=0;
for(i=0;i<10;i++)// 0~9=10
{
for(j=0;j<10;j++)// 0~9=10
{
printf("i=%d,j=%d\n",i,j);//输出几次?100次
}
}
}
while(循环条件)
{
//循环语句
}
//如果循环条件为真就进入循环体执行循环语句
注意:
1、while没有初始化语句 ,用户要提前初始化
2、while没有步进语句, 用户必须在循环语句中写好步进语句。
int i=1;
int sum=0;//注意初始化
while(i<=100)//1~100和
{
sum+=i;
i++;
}
printf("sum=%d\n",sum);//5050
do
{
//循环语句
}while(循环条件);
先执行循环语句,在判断循环条件是否满足, 如果为真,进行下一次循环,如果为假,直接退出循环
int num=0;
do
{
printf("ok\n");
}while(num>0);//先进do再去判断条件,所以会将ok打印出来
void test31(){
printf("---------001---------\n");
printf("---------002---------\n");
goto here;//注意这里是分号
printf("---------003---------\n");
printf("---------004---------\n");
printf("---------005---------\n");
here://注意这里是冒号
printf("---------006---------\n");
printf("---------007---------\n");
}
int main(int argc,char *argv[]){
test31();
return 0;
}
作业:
重复输入1~7的数字判断星期几,注意输入0,就结束程序,如果是0或1 ~7以外的数,请提示“请重新输入有效数值“
总结:
for 和 while 我们如何选择呢?
for和while低位一样
建议:
如果循环次数是确定的,建议选择for。
如果循环次数不确定,只知道退出的条件,建议选择while
需求:请定义一个数组,该数组有十个元素,每个元素为int类型
在定义的时候:(按照步骤来,因为以后的数组很复杂)
a、arr[ ] arr和中括号结合时就是数组
b、将确定的元素的个数放入中括号中
c、用元素的类型定义一个普通变量
d、从上往下整体替换(变量名)
arr[10]
int num;
用arr[10]整体替换num——》int arr[10];
需求:请定义一个数组,该数组有十个元素,每个元素为地址,每个地址为int变量的地址。
arr[10]
*p //每个元素为地址,地址就是指针
int num;
//从上往下依次替换
arr[10]替换p——》 * arr[10]
星花 * arr [10]替换num——》int * arr [10]
注意:
1、数组名arr不能和其他变量名同名
2、数组的元素下标是从0开始的:0~9
3、数组的元素分别是:arr[0]、arr[1]…arr[9],如果访问arr[10]数组越界
4、数组的元素等价于普通变量
5、在定义数组的时候,中括号里面的值必须为常量,不能是变量。
//局部数组(变量)如果不初始化,内容也是不确定的
int arr[10];
//遍历数组——》for循环
int i=0;
for(i=0;i<10;i++)
{
printf("%d ",arr[i]);//输出的都是不确定的值
}
printf("\n");
初始化:定义的时候给变量或者数组元素赋值的动作,叫做初始化。
int arr[5]={
10,20,30,40,50};
//如果是全部初始化,数组元素的个数可以省略,实际元素个数由初始化个数决定
int arr[]={
10,20,30,40,50};//少用
//错误演示:
int arr[];//没有初始化,不知道开辟多大空间
int arr[5]={
10,20,30};//部分初始化,未被初始化的部分补0(重要)
//初始化数字常见操作(将数组所有元素清零)
int arr[5]={
0};//初始化arr[0]=0,未被初始化部分自动补0
int arr[5]={
2};//2 0 0 0 0
//了解
int arr[5]={
[2]=3,[4]=7}; // 0 0 3 0 7
//[2]=3 将数组的第二个元素 初始化为 3
//[4]=7 将数组的第四个元素 初始化为 7
//arr数组名 作为数组类型 代表的是数组空间的总大小
int arr[5]={
10,20,30,40,50};
int n=0;
printf("数组的总大小:%d\n",sizeof(arr));//20个字节
//数组的总大小=元素的个数*每个元素的大小
// 20 = 5 * 4
//数组元素的大小 arr[0]是数组第0个元素,数组的每个元素都是相同类型
printf("数组元素的大小=%d\n",sizeof(arr[0]));//4
//数组元素的个数=数组的总大小 / 每个元素的大小
n= sizeof(arr) / sizeof(arr[0]);
printf("数组元素的个数为:%d\n",n)//5;
//arr数组名 作为数组类型 代表的是数组空间的总大小
int arr[5]={
10,20,30,40,50};
int n= sizeof(arr) / sizeof(arr[0]);//是求数组的元素个数
int i=0;
//遍历数组
for(i=0;i<n;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
int arr1[5]={
1,2,3};
int arr2[]={
1,2,3};
char arr3[5]={
1,2,3};
int arr4[]={
[5]=7};//VC6.0不支持
printf("%d\n",sizeof(arr1));//20
printf("%d\n",sizeof(arr2));//12
printf("%d\n",sizeof(arr3));//5
printf("%d\n",sizeof(arr4));//6*4=24
数组元素等价于普通变量
int arr[5]={
1,2,3,4,5};
int n=sizeof(arr)/sizeof(arr[0]);
int i=0;
//给数组元素赋值
arr[0]=100;
//num++
arr[1]++; //arr[1]=arr[1]+1;
//scanf("%d",&num)
scanf("%d",&arr[2]);
for(i=0;i<n;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
//数值数组只能逐个元素操作 不能整体操作
int arr[5]={
0};
int n=sizeof(arr)/sizeof(arr[0]);
int i=0;
printf("请输入%d个int型数据\n",n);
for(i=0;i<=n;i++)
{
scanf("%d",&arr[i]);//中括号[]的优先级高于&
//&arr[i] 表示取第i个元素的地址
}
for(i=0;i<n;i++)
{
printf("%d ",arr[i]);//arr[i]访问数组的第i个元素
}
int arr[3][4];
//第一个中括号里面的值表示行数
//第二个中括号里面的值表示列数
//arr数组有三行四列
//三行:0~2行
//四列:0~3列
//先写内层循环,再把它粘贴到外层循环中去
int i=0;
for(i=0;i<3;i++)
{
//遍历第i行
int j=0;
for(j=0;j<4;j++)
{
printf("%d ",arr[i][j])
}
}
#include
void test01()
{
int arr[3][4];//局部数组不初始化,内容不确定
int i=0,j=0;
for(i=0;i<3;i++)//行的变化
{
//先写内层循环,再写外层循环,将内层循环复制到外层循环
for(j=0;j<4;j++)//列的变化
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
int main(int argc,char *argv[])
{
test01();
return 0;
}
int arr[3][4]={
{
1,2,3,4},{
5,6,7,8},{
9,10,11,12}};
int arr[3][4]={
1,2,3,4,5,6,7,8,9,10,11,12};
int arr1[3][4]={
{
1,2},{
3},{
4,5}};
int arr2[3][4]={
1,2,3,4,5};
//作业:定义int arr[3][4]的二维数组,获取键盘输入,并求出每一行的平均值。
void test03()
{
int arr[3][4]={
0};//将整个数组初始化为0
//获取键盘输入
int i=0,j=0;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
scanf("%d",&arr[i][j]);
}
}
for(i=0;i<3;i++)
{
//求每一行的平均值
float sum=0;
for(j=0;j<4;j++)
{
sum+= arr[i][j];
}
printf("第%d行的平均值为%.2f\n",i,sum/4.0);
}
void test03()
{
int arr[3][4]={
0};//将整个数组初始化为0
//获取键盘输入
int i=0,j=0;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
scanf("%d",&arr[i][j]);
}
}
for(i=0;i<3;i++)
{
//求每一行的平均值
float sum=0;
for(j=0;j<4;j++)
{
sum+= arr[i][j];
}
printf("第%d行的平均值为%.2f\n",i,sum/4.0);
}
for(j=0;j<4;j++)
{
int sum=0;
for(i=0;i<3;i++)
{
sum+=arr[i][j];
}
printf("第%d列的平均值为%d\n",j,sum/3);
}
// 计算第0列
}
int main(int argc,char *argv[])
{
test03();
return 0;
}
字符数组:本质是数组,只是数组的美国元素是字符。
//定义一个数组有五个元素,每个元素为char
arr[5]
char ch;
从上往下替换======>
char arr[5];
//初始化:逐个字符初始化(不推荐)
char str[6]={
'h','e','l','l','o'};
//str[0]== 'h'的ASCII码值
//初始化:以字符串的形式初始化(推荐)
char str[6]="hello";//初始化更加简洁
char str[6]="hello";
//逐个字符遍历(不推荐)
int i=0;
for(i=0;i<6;i++)
{
printf("%c",str[i]);
}
printf("\n---------\n");
//字符数组可以整体遍历(推荐)
printf("%s\n",str);//%s: 从给定字符串的首元素地址开始逐个字符遍历,直到遇到\0结束
//%s加数组名str
运行结果:
%s:只要告诉字符串第0个元素的地址,那么就可以逐个元素打印,直到遇到\0结束
非常重要:一维数组名代表的是 数组第0个元素的地址。(必须记住)
char str[6]="hello";
//%p是十六进制输出地址
printf("第0个元素的地址:%p\n",&str[0]);
printf("数组名:%p\n",str);
char str1[]={
'h','e','h','e'};//逐个元素初始化,系统不会给它添加‘\0’
char str2[]="hehe";//以字符串初始化,系统会给字符串添加'\0'
//以上情况的前提条件是中括号里面没给数组长度
//开辟的空间大小
printf("sizeof(str1)=%d\n",sizeof(str1));//4
printf("sizeof(str2)=%d\n",sizeof(str2));//5
数组中括号里面没有给定元素的个数那么元素的实际个数由初始化情况决定
%s输出的内容
%s的作用是:从数组的第0个元素开始,逐个元素输出,直到遇到\0结束
//%s输出的内容
//%s的作用是:从数组的第0个元素开始,逐个元素输出,直到遇到\0结束
printf("str1=##%s##\n",str1);
printf("str2=##%s##\n",str2);
定义一个字符数组,有足够大的空间
char buf[128]="";
printf("请输入一个字符串\n");
scanf("%s",buf);//不能获取带空格的字符
printf("buf=%s\n",buf);
解决方法:用gets()——》把键盘输入的大小全搬给你
案例:
char buf[128]="";
printf("请输入一个字符串\n");
//scanf("%s",buf);//不能获取带空格的字符串
gets(buf);//能获取带空格的字符串 缺点:不会管buf的大小,容易造成内存污染
printf("buf=%s\n",buf);
#include
char *fgets(char *s, int size, FILE *stream)
//s表示存放字符串的空间地址
//size表示能提取字符串的最大长度 size-1(留一个给'\0')
//stream stdin表示标准输入设备
返回值:就是获取到的字符串的首元素地址
void test07()
{
char buf[10]="";
printf("请输入一个字符串\n");
fgets(buf,sizeof(buf),stdin);
printf("buf=%s\n",buf);
}
int main(int argc,char *argv[])
{
test07();
return 0;
}
//'a' 97 'b' 98 'c'99 ~ 'z'122
//'A' 65 'B' 66 'C'67 ~ 'Z'90
//规律:小写字母的ASCII值比大写字母的ASCII值相差32
//printf("%d %d\n",'a','z');
//printf("%d %d\n",'A','Z');
char ch='a';
//小写变大写 -32
ch=ch-32; //其实也可以写:ch=ch-('a'-'A');
printf("ch=%c\n",ch);
//大写变小写 +32
ch=ch+32;//其实也可以写:ch=ch+('a'-'A');
printf("ch=%c\n",ch);
作业:键盘获取一个字符串,大小自定义,将字符串的大写字母变小写,小写字母变大写,其他符号保持不变
思路如下:
1、获取一个字符串
2、用for循环将字符串的逐个字符进行大小写转换
一维字符数组是存放多个字符的
二维字符数组是存放多个字符串的 ,每个字符串占一行
//不管是数值还是字符的二维数组,在初始化的时候是库省略行标的,行数又具体初始化决定
char str[3][16]={
"hehe","haha","heihei"};//要保证每个字符串小于16个字节
str[0]="hehe"; str[1]="haha"; str[2]="heihei";
char str[3][16]={
"hehe","haha","heihei"};
//对整体字符串输出,只需要使用行标
printf("%s\n",str[0]);//hehe
printf("%s\n",str[1]);//haha
printf("%s\n",str[2]);//heihei
//输出的是 字符串中某个字符 必须用行标和列表
printf("%c\n",str[1][3]);//a
应用场景:当键盘需要输入多个独立的字符串,用户必须单独存储好,请选择二维字符数组
输入的字符串个数,决定了二维数组的行数 , 输入字符串中最大长度,决定了二维字符数组的列数。
//hehe haha xixi heihei
char buf[4][16]={
""};//二维字符数组初始化为0
int i=0;
//获取键盘的字符串
for(i=0;i<4;i++)
{
scanf("%s",buf[i]);//buf[i]已经代表是第i行的首元素地址,所以这时候不要取地址
}
//输出键盘的字符串
for(i=0;i<4;i++)
{
printf("buf[%d]=%s\n",i,buf[i]);
}
作业:
1、键盘输入十个int数据,对其从小到大排序
2、键盘输入一个字符串“abcdef”进行前后的颠倒(逆置)——》“fedcba”
1、函数的定义:实现函数的功能,确定函数体、返回值、形参类型。让函数存在
2、函数的声明:不是实现函数功能,仅仅是说明函数该函数有返回值类型,形参类型,函数名。
3、函数的调用:函数的执行
// 返回值类型:函数将来返回值的类型
//函数名:函数的入口地址
//形参类型:函数外部数据 传递到函数内部的桥梁
//函数体:具体的函数功能代码
返回值类型 函数名(形参类型 形参)
{
函数体;
}
返回值类型 函数名(形参类型 形参);
//函数外部的实际数据
函数名(实参);//没有函数返回值类型
案例:
#include
//函数声明(必须在函数调用的前方声明才有作用)//编译器是从上往下执行的
void my_fun();//函数声明:告诉编译器,该函数存在,请通过编译。
int main(int argc,char *argv[])
{
//函数的调用:函数名+()
my_fun();
return 0;
}
//函数的定义
void my_fun()
{
printf("my fun\n");
return;//void没有返回值,return后面什么都不写
//return功能:1、返回函数结果 2、结束函数
}
可以省略函数声明:函数的调用在函数定义的下方,就可以省略函数声明
#include
//函数声明(必须在函数调用的前方声明才有作用)//编译器是从上往下执行的
//void my_fun();//函数声明:告诉编译器,该函数存在,请通过编译。
//函数的定义
void my_fun()
{
printf("my fun\n");
return;//void没有返回值,return后面什么都不写
}
int main(int argc,char *argv[])
{
//函数的调用:函数名+()
my_fun();
return 0;
}
建议:
往往建议将主函数写在上方,将函数定义写在下方。(通过主函数,一眼就能看出大致框架)
#include
void my_fun(10,20);
int main(int argc,char *argv[])
{
my_fun();
return 0;
}
//如果函数的形参什么都不写 在调用的时候可以传实参,只是实参得不到使用
void my_fun()
{
printf("my fun\n");
return;
}
#include
void my_fun(void);
int main(int argc,char *argv[])
{
//my_fun(10,20);//error
my_fun();
return 0;
}
//如果函数的参数为void,在调用的时候就不要给函数传递实参
void my_fun(void)
{
printf("my fun\n");
return;
}