循环控制、数组、函数定义、二维数组
循环控制
break VS continue
- break:跳出循环
- continue:跳过循环这一轮剩下的语句进入下一轮循环
【注】两者跳出循环指的是跳出本层循环,如果有多重循环的嵌套,break和continue会跳出当前本层的循环,不会跳出所以的循环
goto
for(...)
{
for(...)
{
for(...)
{
goto out;
}
}
}
out:
return 0;
goto可以直接跳出多重循环,但是平常不建议大家使用,因为goto跳来跳去容易出现问题,并且goto打乱了程序的结构
数组
数据可以存放在变量里,每一个变量有一个名字,有一个类型,还有它的生存空间。如果我们需要保存一些相同类型、相似含义、相同生存空间的数据,我们可以用数组来保存这些数据,而不是用很多个独立的变量。数组是长度固定的数据结构,用来存放指定的类型的数据。一个数组里可以有很多个数据,所有的数据的类型都是相同的。
数组的定义
<数据类型> 变量名称[元素数量];
int count[10];
double count[100];
- 元素数量必须是整数
数组的特点
- 数组中所有的元素具有相同的数据类型
- 数据一旦创建,不能去改变它的大小
- 数组中的元素在内存中是连续依次排列的
数组的单元
- 数组的每个单元就是数组类型的一个变量
- 使用数组时放在[]中的数组叫做下表或者索引,下标从0开始计数;例如 a[0]表示数组中的第一个元素
【注】
- 编译器和运行环境都不会检查数组下标是否越界,无论是对数组单元的读还是写
- 一旦越界访问数组可能会造成问题,导致程序崩溃
- 所以我们要确保有效的数组下标:[0,数组的大小-1]
函数
函数的定义
int sum(int a, int b)
{
...
}
+ int表示返回值类型,也就是函数头
+ sum表示函数名
+ (int a, int b)表示参数表
+ {}中的表示函数体
函数的调用
- 函数名(参数值)
- ()起到了表示函数调用的重要作用
- 即使没有参数也需要()
- 如果有参数,则需要给出正确的数量和顺序
- 这些值会被按照顺序依次用来初始化函数中的参数
- 函数知道每一次是那里调用它,会返回到正确的地方
int a,b,c;
a = 1;
b = 2;
c = max(5,6);
c = max(a,b);
c = max(c,7);
c = max(max(c,a),8);
printf("%d\n", max(b,c));
max(9,10);
- 如果函数有参数,调用函数时必须传递给它数量、类型正确的值
- 可以传递给函数的值是表达式的结果,这包括
- 字面量
- 变量
- 函数的返回值
- 计算的结果
函数的返回值
int sum(int a, int b)
{
int c;
c = a + b;
return c;
}
- return停止函数的执行,并返回一个值
- return;
- return 表达式;
int a,b,c;
a = 1;
b = 2;
c = max(5,6);
c = max(a,b);
c = max(c,7);
c = max(max(c,a),8);
printf("%d\n", max(b,c));
max(9,10);
- 可以赋值给变量
- 可以再传递给函数
- 甚至可以丢弃
没有返回值的函数
- void函数名(参数表)
- 不能使用带值的return
- 可以没有return
- 调用的时候不能做返回值的赋值
函数的先后关系
void sum(int a, int b)
{
int c;
c = a + b;
printf("%d\n",c);
}
int main()
{
sum(1,2);
sum(3,4);
sum(5,6);
return 0;
}
- sum函数写在void上面是因为C语言的编译器是自上而下分析你的代码
- 在看到sum(1,2)的时候就知道sum()的样子,包括几个参数,每个参数的类型,返回值什么类型
函数的声明和定义
void sum(int a,int b); //声明
int main()
{
sum(1,2);
return 0;
}
void sum(int a, int b) //定义
{
int c;
c = a + b;
printf("%d\n",c);
}
- 函数头,以分号;结尾,就构成了函数的原型
- 函数原型的目的就是告述编译器这个函数长什么样子
- 名称
- 参数(数据和类型)
- 返回类型
变量的生存期和作用域
- 生存期:什么时候变量定义了,到什么时候消亡
- 作用域:在代码的什么返回可以访问这个变量(这个变量可以起作用)
- 对于局部变量,两个问题的答案就是:大括号{}------块
二维数组
int a[3][5]; //通常可以理解为a是一个3行5列的矩阵
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]
a[2][0] a[2][1] a[2][2] a[3][3] a[2][4]
二维数组的初始化
int a[][4] = {
{0,1,2,3},
{1,2,3,4},
}
- 列数是必须给出的,行数可以由编译器来数
- 每行一个{},逗号分隔
- 如果省略,表示补0
- 也可以定位去初始化
二维数组的遍历
#include <stdio.h>
int main() {
const int size = 3;
int a[size][size]; //定义二维数组
/*给每行每列赋值*/
for(int i = 0; i<size; i++){
for(int j = 0; j < size ; j++){
scanf("%d",&a[i][j]);
}
}
//行遍历
for(int i = 0 ; i < size; i++){
for(int j = 0 ; j < size ; j++){
printf("%d\n",a[i][j]);
}
}
//列遍历
for(int j = 0 ; j < size ; j++){
for(int i = 0 ; i < size; i++){
printf("%d\n",a[j][i]);
}
}
//正对角线,反对角线遍历
for(int i = 0 ; i < size; i++){
for(int j = 0 ; j < size ; j++){
if(i == j)//正
{
printf("%d\n",a[i][j]);
}
if(i = size-j-1)//反
{
printf("%d\n",a[i][j]);
}
}
}
return 0;
}
FAQ
Q:字符可以做数组的下标吗?
可以,因为C语言中的字符就是对应的ascll码值,用字符串下标其实就是用字符对应的ascll码做下标,但这样不方便阅读,容易造成越界了
例如:
int a[255];
a[‘A’] = 1;
Q:为什么要用函数?
方便修改和维护
避免重复操作
节省空间,代码可读性强