Day3
1. 变量
-
定义:意味着在内存中开辟空间
-
c语言的内存分配图:
- 如何定义变量?
存储类型 数据类型 变量名;
存储类型:决定了开辟的空间在内存分区中的哪个区
数据类型:决定了开辟的内存空间的大小
变量名:开辟的内存空间的名字
1.1 局部变量
定义在函数体(任何函数体)内部的变量
1.2 全局变量
定义在函数体外的变量
1.3 存储类型
存储类型:auto、extern、register、static
- auto:修饰的变量存储在栈区,只能修饰局部变量。
- extern:修饰的变量存储在静态区(.bss和.data统称为静态区)。只能修饰全局变量。
- static:修饰的变量存储在静态区,局部变量和全局变量都可以修饰
- register:修饰的变量存储在寄存器中,只能修饰局部变量。
总结:
- 除了static和register修饰的局部变量,其他都存储的栈区
- 全局变量存储在静态区
- 静态变量只能存储在静态区
1.4 初始化
初始化:在定义变量时对变量赋值
-
int a = 10; //初始化
-
int a; a=10; //赋值
总结:
-
全局变量没有初始化其值默认为0
-
局部变量没有初始化其值默认为随机值
-
auto:修饰局部变量,存储在栈区
-
register:修饰局部变量,存储在寄存器中。建议将变量存储在寄存器中,可以提高程序运行速度
由于寄存器的数目较少,最终是否存储在寄存器中,取决于编译器
-
extern:修饰全局变量,存储在静态区
注意:程序可以有多个.c文件组成,但是一个程序只能有且仅有一个main函数
main.c gcc main.c---->a.out(程序)
extern作用:告诉编译器,这个全局变量已经在其他文件定义过来
static:修饰的变量存储在静态区,局部和全局变量都可以修饰
1.static修饰局部变量,延长了局部变量的生命周期,如果局部变量没有初始化,其值为0,仅可初始化一次
2、static修饰全局变量/函数,只能在本文件内使用(限制了全局变量的作用域)
1.5 生命周期和作用域
1.5.1 生命周期
从什么时候开辟空间到什么时候释放空间
1.5.2 作用域
使用的范围
- 局部变量:
生命周期:从定义开始,到模块(大括号)结束
作用域:大括号内
- static修饰的局部变量
生命周期:从定义开始,到程序结束
作用域:大括号内
- 全局变量
生命周期:从定义开始,到程序结束
作用域:整个程序
- static修饰的全局变量
生命周期:从定义开始,到程序结束
作用域:本文件内
2. 数据类型的转换
2.1 强制类型转换(我们自己转)
2.2 隐式类型转换
-
横向箭头:不管我们有没有进行混合运算,都势必进行转换
-
竖向箭头:只有在进行混合运算的时候,才会进行转换
案例:
1、 char ch = 130;
printf(“%d\n”,ch);
2、 unsigned char ch = 260;
printf(“%d\n”,ch);
3. 运算符
单算移关与,异或逻条赋
单目运算符、算术运算符、左移右移、关系运算符、按位与,异或、按位或、逻辑运算符、条件运算符、赋值
(作业)案例:
1、设int i=2,j=3,k=4,a=4,b=5,c=3;,则执行表达式(a=i<j)&&(b=j>k)&&(c=i,j,k)后,c值是:3
2、a=1,b=2,c=3,d=4,则表达式a<b?a:c<d?a:d的值为___ 1________
3、若以定义int a=25,b=14,c=19;以下语句的执行结果是______ 26 13 19_-。
a++<=25&&b–<=2&&c++<=18?printf(“***a=%d,b=%d,c=%d\n”,a,b,c):
printf(“###a=%d,b=%d,c=%d\n”,a,b,c);
4、以下程序的输出结果是____________ 0 0 4__。
Main()
{int a= -1,b=4;
k=(++a<0)&&!(b–<0);
printf(“%d %d %d\n”,k,a,b);}
3.1 算术运算符
+、-、*、/、++、–
注意:%不能用于浮点数,只能用于整数
3.2 关系运算符
<、>、<=、>=、==、!=
3.3 逻辑运算符
&&、||、!
-
表达式1&&表达式2 &&的截断法则:有一个为假,结果就为假;前一个为假,后面就不再运算
-
||的截断法则:有一个为真,结果就为真;前一个为真,后面就不再运算
3.4 sizeof运算符
sizeof作用:计算内存大小
内存的基本单位是字节,1字节占8个位
3.5 三目运算符(条件运算符)
表达式1?表达式2:表达式3
判断表达式1的值是否成立,如果成立,将表达式2的值作为整个表达式的值;反之表达式3
3.6 逗号运算符
表达式1,表达式2,……,表达式n;
从左至右,依此计算表达式的值,将最后一个表达式的值作为整个表达式的值
3.7 位运算
&、|、~、^、<<、>>
3.7.1 按位与
1101 0011
&1010 1101
1000 0001
-
案例1:将1101 0011 的3-5位清零
1101 0011
&1100 0111
1100 0011
-
案例2:将1101 0011的0~2位清零
1101 0011
&1111 1000 ~(0000 0111)
1101 0000
3.7.2 按位或
1101 0011
| 0101 1001
1101 1011
-
案例:将1101 0011的0~3位变成1100
1101 0011
&1111 0000 ~(0000 1111)
1101 0000
| 0000 1100
1101 1100
3.7.3 按位取反
~(1101 0011) —> 0010 1100
3.7.4 异或
相同为0,不同为1
1101 0011
^1110 0110
0011 0101
3.7.5 左移
高位丢弃,低位补0
3.7.6 右移
1、无符号数(低位丢弃,高位补0)
2、有符号数
正数:低位丢弃,高位补0
负数:低位丢弃,高位补1
Day4
1. 输入输出
函数:一个独立的功能模块
标准输入(scanf)、输出(printf),对变量的数据类型没有要求
字符的输入(getcahr)、输出(putchar)
1.1 输出
printf(“格式控制串”,输出表);
格式控制串:“原样输出的内容+格式化符”
输出表:要输出的对象
整型:
%d:十进制整数
%o:八进制整数
%x:十六进制整数
#:自动在八进制、十六进制前面添加前缀
%u:无符号整数
%hd:short
%ld:long
%lld:long long
字符型:
%c
浮点型:
%f:float
%lf:double
%e:指数型
%g:选择指数和小数中较短的一个
.n:保留小数点后一位 例:%.3f
m:指定输出的宽度,默认是右对齐,如果m小于要原样输出的数据,则原样输出;如果大于
原样输出的数据,左边补空格
1.2 输入
scanf(“格式控制串”,地址表);
1、scanf中不要添加修饰语,如果添加,输入的时候原样输入
2、如果以%d%d这种形式进行输入的时候,以空格、Tab、回车作为一个变量的输入结束
3、全部输入结束,必须以回车作为结束符
4、以%c%c输入的时候,不能以空格、回车、Tab键作为一个变量的结束,因为它们是字符
解决办法:
1、在连个变量之间添加空格或者逗号(输入的时 候原样输入)
2、添加%*c(表示抑制符)
1.3 字符的输入输出
输入:int getchar(void)
返回值:读到的ASCII码值
输出:int putchar(int c)
参数:要输出的ASCII码值
2. 控制语句(三大结构)
if else, switch case, for, do while,goto,
顺序结构、选择结构、循环结构
2.1 顺序结构
语句按照一定的先后顺序去执行
2.2 选择结构
2.2.1单分支选择语句
if(表达式)
{
语句;
}
判断表达式的值是否为真,如果为真,执行相对应的语句,否则不执行语句
2.2.2双分支if语句
if(表达式)
{
语句1;
}
else
{
语句2;
}
实例:输入一个年份,判断是平年还是闰年
闰年:能被4整数但是不能被100整除,或者能被400整除
2.3.3 多分支if语句
if(表达式1)
{
语句1;
}
else if(表达式2)
{
语句2;
}
else if(表达式n)
{
语句n;
}
else
{
语句n+1;
}
从上往下,依次判断表达式的值,如果表达式的值为真,则执行相对应的语句,然后跳出整个if语句
案例:
输入一个成绩,判断成绩的等级
60分以下:D
60 ~ 70分:C
70 ~ 80分:B
80以上:A
2.3.4 switch语句
案例:输入年,月,输出这一年的这个月有多少天?
2.3 循环结构
循环:重复的做某一件事
循环三要素:循环的起始条件;循环的终止条件;循环变量的变化
2.3.1 for 语句
for(表达式1;表达式2;表达式3)
{
语句;
}
表达式1:循环初始条件
表达式2:循环终止条件
表达式3:循环变量的变化
执行顺序:先执行表达式1的值,再执行表达式2的值,如果表达式2的值为真,执行循环体,
然后再执行表达式3的值,如此反复,直到表达式2的值为假的时候,跳出循环
for语句中的表达式1,表达式2,表达式3可不可以省略
总结:表达式1,2,3的值都是可以省略的,但是分号不能省
2.3.2 循环的嵌套
2.3.3 while 语句
while(表达式)
{
语句;
}
2.3.4 do while 语句
do
{
语句;
}while(表达式);
while和do while的区别:
1、while是先判断再执行,do while 是先执行再判断
2、while中的语句至少执行0次;do while中的语句至少执行1次
2.3.5 break
1、跳出switch语句 2、跳出循环
2.3.6 continue
结束本次循环,开始下一次循环
2.3.7 goto 语句
无条件跳转语句,goto 语句标号
语句标号:符号标识符的命名规范
练习:1、打印9*9乘法表
2、输入年,月,日,输出这一天是这一年的第多少天
Day6
1. 数组
1.1 概念
一组数据类型相同的元素的组合
(1)数据类型相同 (2)地址连续
1.2 定义
存储类型 数据类型 数组名[元素个数]
int a[5];
存储类型:auto、static、extern、register
数据类型:数组中每一个元素的数据类型
数组的数据类型:数据类型 [元素个数]; int [5]
数据类型:去掉变量名就是数据类型
数组名:(1)数组名代表的是数组首元素的地址
(2)代表的是整个数组
元素个数:必须是一个确定的数(常量)
1.3 初始化
1.3.1 部分初始化
int a[5] = {1,2,3};
a[0]=1,a[1]=2,a[2]=3,a[3]=0,a[4]=0
在进行部分初始化的时候,未初始化部分的值为0,因此我们利用这一特点对数组
中的元素清零
1.3.2 全部初始化
int a[5] = {1,2,3,4,5};
在进行全部初始化的时候,数组元素的个数可以省略
int a[] = {1,2,3};//数组的元素个数由后面赋值的具体个数来决定
1.4 数组的访问
数组名[下标]
注意:下标必须从0开始
1.5 输入 输出
案例:
1、int a[5];
a[5]={1,2,3,4,5};//error
2、int a[] = {0};//表示数组中只有一个元素,但是这样没有意义
3、int a[5];
a = {1,2,3,4,5};//error 数组名代表的是数组首元素的地址
1.6 冒泡排序
思想:从左至右两两依次比较,如果前一个数比后一个数大的话就交换位置,否则不变
2. 字符数组
字符数组的本质:字符串(以\0作为结束符)
存储类型 数据类型 数组名[元素个数]
char str[5] = {0};//最多存放4个元素,留一个位置给’\0’
char str[6] = {‘h’,‘e’,‘l’,‘l’,‘o’,‘\0’};
char str[6] = “hello”;
2.1 字符数组的输入输出
2.1.1 字符数组的输出
格式化符:%s
puts(数组名);
功能:将数组中的字符串打印到终端上,会自动添加一个换行符
注意:遇到’\0’就结束了
2.1.2 字符串的输入
gets(数组名);
功能:将键盘输入的字符串保存到数组中,会自动在末尾添加’\0’
注意:gets不会进行越界检查,输入的时候注意不要越界
总结:
1、scanf和gets的区别:
scanf是以空格、回车、Tab键作为结束符,而gets是以回车做为结束符
缓冲区:
gets输入完之后会自动清空缓冲区
scanf输入完成之后,缓冲区会遗留空格、回车、Tab键
gets输入之前,先会查看缓冲区是否有内容,有的话直接拿过来使用
scanf是标准输入函数,每次一输入都要从键盘获取
2、puts和printf的区别
puts会自动添加换行符,printf不会
作业:
1、 求一组数据中的最大值( 不能使用冒泡排序)
2、 求一组数据中的次大值(不能使用冒泡排序)
Day7
1. 字符串的处理函数
strlen、strcpy、strcat、strcmp
头文件:#include <string.h>
1.1 strlen
strlen(数组名)
功能:求字符串的实际长度
返回值:返回字符串的实际长度,不包含’\0’
sizeof和strlen的区别:
1、sizeof是运算符,strlen是函数
2、sizeof求得的是内存空间的大小,strlen求得的是字符串的实际长度(不包含’\0’)
案例:求字符串的实际长度(不使用库函数)
1.2 字符串的拷贝函数
strcpy(数组1,数组2/字符串)
功能:将数组2或字符串2拷贝到数组1中
注意:(1)数组1足够大
(2)是完全拷贝,会将数组2/字符串2的’\0’也拷贝过去
strncpy(数组1,数组2/字符串2,n)
功能:将数组2/字符 串2的前n个字符拷贝到数组1中
注意:不包含\0
1.3 字符串的连接函数
strcat(数组1,数组2/字符串2)
功能:将数组2/字符串2连接到数组1之后
注意:(1)数组1的容量足够大
(2)数组1中的’\0’会被覆盖
strncat(数组1,数组2/字符串2,n)
功能:将数组2/字符串2的前n个字符连接到数组1之后
1.4 字符串的比较函数
strcmp(数组1/字符串1,数组2/字符串2)
功能:比较两个字符串的大小
返回值:
大于0:字符串1 > 字符串2
等于0:字符串1 == 字符串2
小于0:字符串1 < 字符串2
比较规则:从左至右,依次比较每个字符的ASCII码值,直到遇到不同的ASCII或者遇到’\0’
strncmp(数组1/字符串1,数组2/字符串2,n)
功能:比较字符串的前n个字符的大小
2. 二维数组
2.1 概念
元素为一维数组的数组(数组的数组)
(1)数据类型相同 (2)地址连续
2.2 定义
存储类型 数据类型 数组名[元素个数];
存储类型 数据类型 数组名[行数] [列数];
行数:有几个一维数组
列数:一维数组中有几个元素
int a[2] [3]
2.3 初始化
2.3.1 部分初始化
int a[2] [3] ={1,2,3};
2.3.2 全部初始化
int a[2] [3] = {{1,2,3},{4,5,6}};
int a[2] [3] = {1,2,3,4,5,6};
int a[2] [] = {1,2,3,4,5,6}//error 列数不能省
int a[] [3]={1,2,3,4,5,6};//有2个一维数组
注意:二维数组的行数可以省略,列数不能省略
2.4 访问
数组名[下标];
注意:下标必须从0开始
2.5 输入输出
#include <stdio.h>
#define M 2
#define N 3
int main()
{
//int a[2][3]={1,2,3};
//int a[2][3]={0};
int a[M][N]={0};
printf("Please input nums:");
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
printf("a[%d][%d]=%d ",i,j,a[i][j]);
}
printf("\n");
}
return 0;
}
案例:打印杨辉三角(8*8)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
#include <stdio.h>
#define N 10
int main()
{
int a[N][N]={0};
for(int i=0;i<N;i++) //赋值
{
for(int j=0;j<=i;j++)
{
if(0==j||j==i)
{
a[i][j] = 1;
}
else
{
a[i][j]=a[i-1][j-1]+a[i-1][j];
}
}
}
for(int i=0;i<N;i++) //打印
{
for(int k=0;k<N-1-i;k++)
{
printf(" ");
}
for(int j=0;j<=i;j++)
{
printf("%3d ",a[i][j]);
}
printf("\n");
}
return 0;
}
3. 二维字符数组
作业:
1、 实现字符串的拷贝(不使用库函数)
2、 实现字符串的连接(不使用库函数)
3、 对字符串进行排序
int a[2] [3] = {{1,2,3},{4,5,6}};
int a[2] [3] = {1,2,3,4,5,6};
int a[2] [] = {1,2,3,4,5,6}//error 列数不能省
int a[] [3]={1,2,3,4,5,6};//有2个一维数组
注意:二维数组的行数可以省略,列数不能省略
2.4 访问
数组名[下标];
注意:下标必须从0开始
[外链图片转存中…(img-P3WxrzbX-1667029836830)]
2.5 输入输出
#include <stdio.h>
#define M 2
#define N 3
int main()
{
//int a[2][3]={1,2,3};
//int a[2][3]={0};
int a[M][N]={0};
printf("Please input nums:");
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
printf("a[%d][%d]=%d ",i,j,a[i][j]);
}
printf("\n");
}
return 0;
}
[外链图片转存中…(img-PnX62B3y-1667029836830)]
案例:打印杨辉三角(8*8)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
[外链图片转存中…(img-JUhJyFAE-1667029836830)]
#include <stdio.h>
#define N 10
int main()
{
int a[N][N]={0};
for(int i=0;i<N;i++) //赋值
{
for(int j=0;j<=i;j++)
{
if(0==j||j==i)
{
a[i][j] = 1;
}
else
{
a[i][j]=a[i-1][j-1]+a[i-1][j];
}
}
}
for(int i=0;i<N;i++) //打印
{
for(int k=0;k<N-1-i;k++)
{
printf(" ");
}
for(int j=0;j<=i;j++)
{
printf("%3d ",a[i][j]);
}
printf("\n");
}
return 0;
}
3. 二维字符数组
作业:
1、 实现字符串的拷贝(不使用库函数)
2、 实现字符串的连接(不使用库函数)
3、 对字符串进行排序