数组:
什么是数组: 变量的组合,是一种批量定义变量的方式
定义: 类型 数组名[数量];
int num1,num2,num3,num4,num5;
int arr[5];
使用:数组名[下标];
下标:从零开始 范围:0~数量-1
遍历:与for循环配合使用,使用循环变量i作为数组的下标
初始化: 类型 数组名[数量] = {1,2,3,4,5,…};
1、数组与普通变量一样默认值是随机的,为了安全要对数组进行初始化
2、这种初始化语法只能在定义语句时使用,而且只能逐个赋值,不能整体赋值
3、初始化数据过多,编译器会产生警告并丢弃多余的数据
4、初始化数据不够,编译器会自动补0
5、初始化时数据可以省略,只写大括号,相当于给所有成员初始化为0
6、初始化时数组的长度可以省略,编译器会自动统计数组元素的个数并告诉数组
sizeof(arr)/sizeof(arr[0]) = 数组的元素个数
数组的总字节数/数组元素的字节数 = 数组的元素个数

练习1:定义一个长度10的数组并初始化,计算出该数组中的最大值、最小值、平均值
练习2:定义一个长度10的数组并初始化,进行升序排序
for(int i=0;i<l-1;i++)
{
for(int j=i+1;j<l;j++)
{
if
}
}

数组的越界:C语言为了程序的运行效率是不会检查数组的下标是否越界
数组越界的后果:
1、一切正常
2、段错误
3、脏数据

练习3: 定义一个长度10的数组并初始化,找出数组中的第二大的值,不允许排序

二维数组
一维数组相当于把变量排成一排,通过编号来访问
二维数组相当于把变量排成矩阵,通过行号和列号来访问

定义: 类型 数组名[行数][列数];
int arr[3][5];
[0,0][0,1][0,2][0,3][0,4]
[1,0][1,1][1,2][1,3][1,4]
[2,0][2,1][2,2][2,3][2,4]
使用:数组名[行下标][列下标]; arr[1][2]
行下标: 0~行数-1
列下标: 0~列数-1
遍历:需要与双层for循环配合,外层一般负责遍历行,内层一般负责遍历列
for(int i=0; i<行数; i++)
{
for(int j=0; j<列数; j++)
{
printf("%d “,arr[i][j]);
}
printf(”\n");
}
初始化:
类型 数组名[行数][列数] = {{第一行},{第二行},{第三行},…};

练习4:定义一个5*5的二维数组并初始化,找出数组中最大值的坐标

练习5:定义一个5*5的二维数组并初始化,找出最小值的坐标,计算该位置周围的数的和是多少?

变长数组:
定义数组时使用变量来作为它的长度,在代码编译期间数组的长度是不确定,当执行到数组定义语句时它的长度才确定下来,一旦确定就无法改变
优点:可以根据实际情况来确定数组的长度,达到节约内存的目的
缺点:因为初始化在编译时完成,而此时变长数组的长度并不确定,因此不能初始化

练习6:输入两个整数m,n(1<=m<=6,1<=n<=6),输入数组arr[m][n]的各个元素的值,然后计算各个元素之和,统计数组中非零元素的个数,计算所有元素的平均值,计算大于平均值元素的个数

作业7:
显示N层的杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

进制转换:
为什么使用二进制、八进制、十六进制?
由于现在的CPU只能识别高低两种电平,只能使用二进制数据进行计算
二进制虽然能够被计算机直接计算,但是不方便书写、记录,因此将数据以八进制方式为了更方便记录在文件中
随着CPU位数不断增加,八进制不能满足需求,所以发展出了十六进制来表示数据,
由于历史原因八进制还不能退出历史舞台

十进制转二进制:(十进制转其他进制)
求余法: 用2对数据求余,然后再继续对商求余,知道商为0结束,过程中产生的余数就是该数据的二进制(逆序)
n %2 余数
商%2

127 %2 1
63 %2 1
31 %2 1
15 %2 1
7 %2 1
3 %2 1
1 %2 1
0 0
二进制:01111111
求权法: 数据- 2^(n-1) 如果可以减,则第n位为1,否则为0
137
128 64 32 16 8 4 2 1
1 0 0 0 1 0 0 1

手算: 79 28 63 119
练习1:输入一个正整数m,显示该数据的n进制(n>=2),如果n>=10,超出10的数字用字母表示
10 A 11 B

二进制转十进制:(其他进制转十进制)
二进制数据每位 乘2^(n-1) 结果求和
10011101 128+16+8+4+1 157

二进制转八进制:
三个二进制位转为一位八进制位
二进制 10 011 001 101 110
八进制 2 3 1 5 6

二进制转十六进制:
四个二进制位转为一位十六进制位
二进制 10 0110 0110 1110
十六进制: 2 6 6 E

在C代码中,以0开头的数据是八进制数据,以0x开头的是十六进制数据
%o 以八进制形式显示数据
%x 以十六进制显示数据
%#o %#x 以对应的进制显示数据

原码、反码、补码:
原码: 数据的二进制
反码:
正数的原码就是它的反码
负数的反码是它的原码符号位不变,其它位按位求反
补码: 数据在内存中是以补码形式存储的
正数的原码就是它的补码
负数的补码是它的反码+1
负数的补码:
1、数据转换为二进制
2、二进制符号位不变,其余按位求反得到反码
3、反码+1得到补码
-127
1111 1111
1000 0000
1000 0001 补码
0000000000000000000000001000 0001 %d --127->129

补码转数据:
无符号的补码直接转成十进制数据
有符号看最高位是0,说明是正数,也直接转成十进制数据
有符号且最高位是1,说明是负数
1、补码-1得到反码
2、反码符号位不变,按位求反得到原码
3、原码转换成十进制

11111111 补码
11111110 反码
10000001 原码 -1

最大值+1 = 最小值
最小值-1 = 最大值

位运算符:& | ~ ^ << >>
A & B 按位相与
01101010 0x6A
01110110 0x76
01100010 0x62
A | B 按位相或
01101010 0x6A
01110110 0x76
01111110 0x7E
~A 按位求反
01101010 0x6A
10010101 0x95
A^B 按位异或 相同为0,相异为1
01101010 0x6A
01110110 0x76
00011100 0x1C
A<<n 把A的补码向左移动n位,左边丢弃,右边补0
01101010 0x6A << 4
10100000 0xA0
A>>n 把A的补码向右移动n位,右边丢弃,左边补符号位
11101010 0xEA >> 3
11111101 0xFD

练习2:
输入一个整数n,把它的4~7位设置为1010,其它位保持不变
4位先与0 ,再或1010

printf("%d\n",n & ~(0xf<<4) | (0xA << 4));
00000000 00001111
00000000 11110000
11111111 00001111
xxxxxxxx 0000xxxx
0xA << 4
00000000 10100000
xxxxxxxx 1010xxxx

函数:
是一段具有某项功能的代码,是C语言中管理代码的最小单位
把代码封装成一个个的函数,可以方便管理和调用代码
函数的分类:
标准库函数
C语言标准委员会为C语言以函数形式提供一些基础的功能,被封装在libc.so库,默认添加的,所以使用时需要包含头文件,以函数名(参数) 来调用函数
int isalnum(int c);
int isalpha(int c);
int isdigit(int c);
int islower(int c);
int isupper(int c);
int isxdigit(int c);
int toupper(int c);
int tolower(int c);
int abs(int j);

以下函数被封装在libm.so 数学库中,使用时需要在编译时加参数-lm
double sqrt(double x);
double pow(double x, double y);
double ceil(double x);
double floor(double x);
double fabs(double x);

time_t time(time_t *t);
功能:返回自1970-1-1 0:0:0 到运行时过了多少秒
int system(const char *command);
功能:调用系统命令 system(“clear”);

int rand(void);
功能:返回一个随机数
void srand(unsigned int seed);
功能:种随机种子,设置取随机数的位置

练习3:获取10个[100,1000]范围内的随机数
num = rand()%901+100
[a,b) rand()%(b-a)+a

练习4:随机出一注双色球中奖号码
红球6个:1-33,不能重复 rand()%33+1
蓝球1个:1-16 rand()%16+1

系统函数
系统函数不是函数,只是操作系统以函数接口的形式提供的一些功能
内存管理、信号处理、文件IO、文件管理、进程管理、进程通信、线程管理、线程同步、网络通信

第三方库函数
由第三方提供的收费、开源的库函数
github
MD5
XML
JSON

自定义函数:
为了更方便地管理代码、减少冗余把代码封装成函数
注意:一个函数尽量控制在50行左右,一个函数一个功能

**函数声明:**函数声明目的是为了告诉其他代码该函数的调用格式
返回值类型 函数名(类型1 变量名1,类型2 变量名2…);
1、C语言中函数名一般全部小写,用下划线分隔
2、如果不需要参数建议写void,不要空着
3、如果不需要返回值写void
4、如果在调用前有函数的定义,那么函数声明可以省略

隐式声明:
当调用函数时没有函数声明或定义,编译器会猜测函数的格式,参数列表会根据调用时的提供数据来猜测,返回值猜测为int类型
如何避免:在调用前,提供函数的声明或定义

函数定义:
返回值类型 函数名(类型1 变量名1,类型2 变量名2…)
{
函数体;
return val;
}
注意:return语句的作用:1、返回值给调用者 2、结束函数的执行

函数调用:
函数名(实参);
返回值会放在调用的位置,可以用变量记录下来,也可以直接显示,如果不记录就会丢失

函数传参:
1、实参与形参之间是以赋值的形式传递数据的(单向值传递)
2、在函数内定义的参数,只属于它所在的函数,出了该函数就不能在使用了
3、return语句其实是把数据放置到一个公共区域(函数和调用者共用),如果不写return语句,调用者从该区域中获取的是一个随机的垃圾数据
4、当数组作为函数的参数时,长度会丢失,需要额外多加长度的参数来把长度传递过去
5、数组的传递是"址传递",函数和函数的调用者可以共享数组

练习5:实现一个函数,找出数组中的最大值
练习6:实现一个函数,对数组进行排序
练习7:实现一个函数,查找数组中是否存在某个值,如果存在则返回该数据在数组中的下标
int find_arr(int arr[],int len,int val);

作业:
1、实现一个函数,判断一个整数是否是素数,调用它显示出100~10000之间所有的素数
2、输入两个日期(yyyy-mm-dd),计算两个日期之间间隔了多少天
3、实现一个函数,判断整数是否是回文数,调用它显示1亿-10亿以内的所有回文数
4、计算出100的阶乘
123*4…*100

设计函数的准则
1、一个函数最好只解决一个问题,从而可以降低出错率
2、最好不要过分依赖其他函数,降低耦合度
3、数据由调用者提供,结果返回给调用者,以此提高函数的通用性
4、对于调用者提供的非法参数,可以通过返回值、注释等方式来告诉调用者数据非法,以此提高函数的健壮性
5、一个函数最多不要超过50行

进程映像:
程序:储存在磁盘中的可执行的文件(二进制文件、脚本文件)
进程:在系统中运行的程序
进程映像:进程的内存的分布情况

text 代码段: 存储的是二进制的指令、常量数据,权限是只读的,如果强行修改会产生段错误
data 数据段: 存储的是初始化过的全局变量、被初始化过的静态局部变量
bss 静态数据段:存储的是未初始化过的全局变量、未初始化过的静态局部变量,程序运行前会清零
stack 栈: 局部变量、块变量,会随着进程运行而申请、释放,由系统管理的,缺点:小
heap 堆: 由程序员手动管理的,手动申请、释放的,使用比较麻烦,特点是:足够大,理论上无限大

局部变量和全局变量:
全局变量: 定义在函数外的
存储位置: data(初始化过的)或者bss(未初始化过的)
生命周期: main函数运行开始前到程序结束才释放
作用范围: 程序中的任何位置
局部变量: 定义在函数内的
存储位置: stack栈内存
生命周期: 函数的定义语句开始,直到函数执行结束
作用范围:只能在本函数内使用
块变量: 定义在if\for\while等语句块内的变量
存储位置: stack栈内存
生命周期: 函数的定义语句开始,直到函数执行结束
作用范围:只能在语句块内使用

注意:局部变量和全局变量可以同名,但是会屏蔽同名的全局变量,同名块变量会屏蔽同名的局部变量和全局变量
建议:全局变量首字母大写

类型限定符
auto
用于定义自动申请、自动释放的变量(局部变量),不加代表了加
不能用于修饰全局变量
const
显示地"保护"变量不被修改
但是,如果要强制修改还是可以修改的
如果对初始化过的全局变量,用const修饰后,存储位置从data变成了text
extern
声明外部的全局变量,声明的变量已在别处定义过,请放心使用
但是只能临时通过编译,如果没有定义,链接时依然会报错
只是声明变量,不能赋值

static
被static修饰过的变量称为静态局部变量,局部全局变量
改变存储位置:
改变局部变量的存储位置,由stack改data或者bss(由是否初始化决定)
延长生命周期:
延长局部变量的生命周期
限制作用范围:
限制全局变量、函数只能在本文件内使用
可以防止函数、全局变量重名、防止被别人调用

存储介质:
硬盘->内存->高速缓存->寄存器->CPU
register
申请把变量的存储介质由内存转移到寄存器存储,如果能成功,数据的读取速度会大幅提升,寄存器数量有限,申请可能失败
volatile
编译器的取值优化:
变量的值没有发生改变时,后续的取值会进行优化,不再去内存中读取,而是使用第一次读取的结果,可以节约时间
使用volatile修饰的变量不做取值优化
volatile int num = 10;
if(num == num)
{
//可能为假
}
一般硬件编程和驱动编程时使用

typedef
类型重定义,注意不是替换关系,定义变量时如果前面加上typedef,则变量名就变成了类型
typedef int num;
#define num int;
num num2;
uint8_t size_t time_t
typedef unsigned char uint8_t

函数递归
分治:分而治之 循环、递归
函数自己调用自己的行为叫做递归,会产生死循环

递归可以实现分治算法,其实就是把一个大而复杂的问题,分解成若干个相同的小问题,解决小问题,直到全部问题解决

1、出口
2、分解成一个小问题
3、自己调用自己

斐波那契数列
1 0|1 1 2 3 5 8 13 21 …
练习1:求前N项斐波那契数列
5
递归函数好处是容易理解,思路清晰
递归函数每次调用都会在栈内存产生一份自己的内存拷贝,直到到达出口,才会一层层地返回,因此递归非常地耗费内存资源,与循环相比,速度非常慢
递归的优缺点:
1、耗费内存、速度慢
2、好理解、思路清晰
3、能使用循环就用循环

作业1:
使用递归模拟N层汉诺塔的移动过程
作业2:
全排列 0~9

五子棋:
数据分析:
1、定义棋盘数组 空位置=’*’
2、定义变量用于记录棋子的位置
3、定义角色变量 黑棋=’@’ 白棋=’$’ 建议一个棋子角色,落子后交换角色
业务逻辑:(要求每个功能封装成函数)
是否需要初始化
for( ; ; )
{
1、清理屏幕、打印棋盘
2、落子
坐标合法、该位置不能有棋子
3、检查是否五子连珠
4、交换角色
}

【c语言】复习无止境,day2--数组函数篇相关推荐

  1. C语言中常用的字符数组函数

    所有的字符数组处理函数都包括在 <string.h>这个头文件中 一.strlen 函数 原型:size_t strlen(char const* string); 在C语言中如何计算一个 ...

  2. 求矩形的最小值c语言,C语言复习---矩形法求定积分函数

    #include #include using namespace std; int main(){ float fun(float x); float a, b; cout << &qu ...

  3. c语言中如何返回一个数组函数

    在C语言中,无法直接返回一个数组,但是可以通过返回对应类型指针的方式,返回数组. 在大多数情况下,一维数组和一维指针是可以通用的. 比如,定义一个函数,申请一定长度的整型动态数组,其长度用参数传入,并 ...

  4. C语言复习:(四)函数指针

    问题: 1.函数指针是什么?如何定义? 2.函数指针有什么作用? 解决问题: 1.函数指针:即指向特定类型函数的指针 (指针和函数的类型必须相同:1.包括返回类型,2.参数类型) 定义函数指针: vo ...

  5. C语言复习笔记7----二维数组

    数组考点 排序 冒泡排序 O(n^2) 选择排序 O(n^2) (插入排序) 分离每一位 正序 字符串 栈(递归) 逆序 哈希(hash) → 用值直接作为下标 数组的基本操作 插入和删除 逆序(移位 ...

  6. C语言复习---矩形法求定积分函数

    一:分析: 大一学习积分的时候,我们学习过,可以通过矩形法来求定积分. 思路就是将积分区间划分成n等份,然后将这n等份近似看成矩形(或梯形),然后对所有的矩形(或梯形)的面积进行求和. 二:简单的例子 ...

  7. c语言中比较两个数组函数,输入两个数组,调用large函数比较,计数,输出统计结果...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include void main() { int large(int x,int y); int a[10], b[10], i, n=0, m=0, ...

  8. c语言stand(time(0)),C语言复习0_准备工作

    前言: 第一次接触C语言是大一下学期的时候,2013年上半年,那个时候的开发工具还是VS C++,今天了解了一下,常用的开发工具变成了CodeBlocks.决定趁着毕业到入职这一段CD时间,拾起这门语 ...

  9. c语言字符串二维数组的动态分配应,C语言中动态分配二维数组复习过程.doc

    C语言中动态分配二维数组复习过程.doc C语言中动态分配二维数组在C中动态分配内存的,对于单个变量,字符串,一维数组等,都是很容易的.C中动态分配二维数组的方法,很少有C语言书中描述,我查找了有的C ...

最新文章

  1. 二分 + 模拟 - Carries
  2. 乐鑫esp8266模块MicroPython开发板MQTT物联网人工智能最小系统
  3. MATLAB学习笔记(一)
  4. UVA10236 斐波那契素数
  5. 执行 redis-dump 报错:Error connecting to Redis on localhost:6379 (Redis::TimeoutError)
  6. c++ amp vs2017 报错_opencv4教程-1 opencv的安装与调试Windows10+vs2017
  7. stat函数_使用Python的stat函数有效地获得所有者,组和其他权限
  8. 简易售货机JAVA sql_自动售货机 - 笨拙的小Q的个人空间 - OSCHINA - 中文开源技术交流社区...
  9. Linux Shell基础 Shell的输入重定向和输出重定向
  10. mysql子查询的语法,MySQL语法------13-----子查询(三)
  11. 洛谷1363——幻想迷宫(搜索)
  12. 复盘:windows ubuntu 双系统引导恢复、分区表恢复
  13. 致敬逆行者网页设计作品 抗疫感动专题网页设计模板 疫情感动人物静态HTML网页模板下载
  14. Xilinx平台SRIO介绍(汇总篇)
  15. programmer-common-word-pronunciation 程序员常用单词发音
  16. 2020电工(初级)证考试及电工(初级)考试软件
  17. android序列号怎么修改,修改Android序列号(Serial Number)
  18. 2021金三银四,你准备好挑战这份最新腾讯、字节跳动、阿里巴巴Android面试题集了吗?
  19. uniapp安卓app里拦截webview下载apk,显示下载进度
  20. java主机哪儿好_java虚拟主机哪个好,香港java虚拟主机哪里有!

热门文章

  1. Oracle数据库的乘号是什么,(Oracle数据库设计实验指导书yk.doc
  2. 微服务与监控(monitor)
  3. ClickHouse在京东流量分析的应用实践
  4. 6848. 【2020.11.03提高组模拟】融入社会的计划
  5. 阿里云查看服务器 外网ip地址 命令
  6. 服务器虚拟化技术笔试题,(虚拟化技术试题.docx
  7. BTC/ETH历史行情数据/期权/合约成交数据分析工具
  8. 影响NETGEAR路由器的0-Day:KCodes NetUSB两个安全漏洞披露(CVE-2019-5016/5017)
  9. 【Redis】使用 Java 客户端连接 Redis
  10. 移动端常见的开发布局方式