循环:
通过反复执行一段来达到解决问题的目的。
for([1]; [2]; [3])
{
[4];
}
1、先执行,只执行一次
2、判断条件,为真时执行4,为假则退出
4、循环体,被反复执行的代码
3、改变循环条件,防止出现死循环
for是一种非常灵活的循环,但也容易出错,因此建议使用一个变量来引导for的运行过程,这样可以精确控制循环的次数,index->i,j
1、初始化循环变量,只在C99标准中才能定义循环变量,此处定义的变量只能在大括号内使用。 (gcc -std=gnu99 code.c)
2、判断循环变量是否到达边界
3、循环变量自增或自减1。
循环嵌套:
循环语句中包含循环语句。
外层循环执行一次,内层循环从头到尾执行一遍。
while(表达式)
{
表达式结果为真执行循环体。
}
while 类似 for 循环的精简版,for 负责循环次数明确的情况,while 循环负责条件而不确定循环次数的情况。
for(;[];)
{
}
do
{
循环体;
}while(表达式条件判断);
do while 是一种先执行循环体,在判断循环条件的一种循环,循环体至少执行一次,而 for 和 while 的循环体可能一次都不执行
练习1:输入一个整数,倒序显示。(1234 4321)
#include <stdio.h>
int main()
{
int num = 0;
printf("请输入一个数:\n");
scanf("%d",&num);
if(num < 0)
printf("-");
while(num)
{
printf("%d",num%10);
num /= 10;
}
}
练习2:密码验证,输入密码进行判断(132456),密码正确显示登录成功,错误显示重新输入并告知剩余次数,如果三次错误则提示账号锁定,请联系管理员
#include <stdio.h>
int main()
{
int pass = 0;
int count = 0;
do{
if(0 == count)
{
printf("请输入密码:");
}
else
{
printf("密码错误,请重新输入(还有%d次):",3-count);
}
scanf("%d",&pass);
}while(132456 != pass && ++count < 3);
if(132456 == pass)
{
printf("登录成功");
}
else
{
printf("账号锁定,请联系管理员");
}
}
跳转语句:
goto 标签:
可以跳转导函数内的任意位置,既可以向前,也可以向后。
goto 是一种非常灵活,强大但也非常危险的语句,因为 goto 可能会破坏已经设计好的分支和循环,很多公司都禁止使用 goto。
在驱动编程中,goto 有它无代码代替的作用,当驱动程序出现异常时,goto 语句非常适合用来释放资源。
break
1、在 switch 语句中可以关闭执行开关
2、在循环语句可以跳出一层循环
continue
结束本次循环(循环体中 continue 后的语句不再执行),进入下一次循环(循环并没有结束)。
注意:break 与 continue 可以提高程序的运行效果。
return
1、把一个数据返回给函数的调用者
2、终止函数的执行
练习3:不使用循环计算前n项斐波那契数列。
#include <stdio.h>
int main()
{
int prev = 1,curr = 0, next;
int n = 0 ;
printf("enter n:");
scanf("%d",&n);
loop:
next = prev + curr;
printf("%d ",next);
prev = curr;
curr = next;
if(--n) goto loop;
}
数组:
定义:
数组就是变量的集合,是一种批量定义变量的方法
类型 数组[数量];//[]里的整数表示变量的数量
int arr[5] <=> int n1,n2,n3,n4,n5;
数组的变量值也是不确定的,为了安全需要初始化
使用:
数组名[编号];//[]里的整数表示的是编号
arr[0],arr[1],arr[2],arr[3],arr[4];
编号也叫下标,范围: 0~数量-1
遍历:
配合循环语句,使用循环变量当做数组的编号。
for(int i=0;i<10;i++)
{
printf("%d\n",arr[i]);
}
初始化:
类型 数组[数量] = {v0,v1,…};
1、如果初始化数据不够,编译器会自动补0
2、如果初始化数据过多,编译器会丢弃多余的数据并给出警告
3、对数组初始化时,数组的长度可以省略,编译器会统计出初始化数据的个数然后再告诉数组。
sizeof(arr) 计算出数组的总字节数
sizeof(arr[0]) 计算出其中一个变量的max字节数
练习4:定义一个长度为10的int型数组并初始化,找出第二个大的数。
#include <stdio.h>
int main()
{
int arr[10] = {1,23,5,6,74,37,68,85,4,9};//arr[]初始化
int i,max = arr[0],max_two = arr[1];//max,max_two初始化
printf("%d %d\n",max,max_two);
for(i = 1;i < 10;i++)
{
if(arr[i] == max) continue;
if(arr[i] > max)
{
max_two = max;
max = arr[i];
}
else if(arr[i] > max_two)
{
max_two = arr[i];
}
}
printf("%d %d\n",max,max_two);
}
练习5:定义一个数组,然后把数组中数据逆序并显示。
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int len=sizeof(arr)/sizeof(arr[0]);
for(int i=0;i<len/2;i++)
{
int temp = arr[i];
arr[i] = arr[len-1-i];
arr[len-1-i] = temp;
}
for(int i=0;i<10;i++)
{
printf("%d ",arr[i]);
}
}
数组的越界:
1、c语言中数组是可以越界的,没有语法错误
2、数组越界使用时访问的是它之后的内存(可能是其他变量,也可能是其他数组,也有可能无主的,也有可能属于操作系统)
数组越界的后果:
1、产生脏数据
2、一切正常
3、段错误(核心已转储)
二维数组:
把变量排成一个方阵
定义: 类型 数组名[行数][列数];
int arr[3][2]
[ ][ ]
[ ][ ]
[ ][ ]
使用:
数组名[行编号][列编号] , 编号从零开始
arr[0][0] arr[0][1]
arr[1][0] arr[1][1]
arr[2][0] arr[2][1]
遍历:
配合双层 for 循环,内层循环负责遍历行,外层循环负责遍历列
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
printf("%d “,arr[i][j]);
}
printf(”\n");
}
初始化:
数组名[行编号][列编号] = {{v0,v1},{v0,v1},{v0,v1}};
练习6:定义一个5*5的二维数组并初始化,找出最大值下标
#include <stdio.h>
int main()
{
int arr[5][5]={
{2,3,5,6,4},
{3,4,6,8,7},
{1,4,5,8,9},
{4,7,10,2,5},
{4,6,8,3,6}
};
//初始化数组
int max = arr[0][0],x = 0,y = 0;//初始化max,x,y
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
if(max<arr[i][j])
{
x=i;
y=j;
max = arr[i][j];
}
}
}
printf("%d %d %d",max,x,y);
}
练习7:输入一个整数,分解显示 1234 1 2 3 4
#include <stdio.h>
int main()
{
int num = 0, arr[10],cnt=0;
printf("请输入一个整数:");
scanf("%d",&num);
while(num)
{
arr[cnt++] = num % 10;
num /= 10;
}
for(int i = cnt-1;i >= 0;i--)
{
printf("%d ",arr[i]);
}
}
变长数组:
数组的长度在编译时可以先不确定,在运行期间根据实际情况进行计算,当执行到数组定义语句时,就必须确定下来,再不能改变。
*优点:*可根据实际情况确定数组的长度,达到节约内存的目的
*缺点:*不能初始化
练习8:显示n层杨辉三角形
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
#include <stdio.h>
int main()
{
int n;
printf("请输入n的值:");
scanf("%d",&n);
int i,j;
int arr[n][n];
for(i = 0;i < n;i++)
{
if(i == 0)
{
arr[0][0]=1;
printf("%d\n",arr[0][0]);
continue;
}
for(j = 0;j <= i;j++)
{
if(j == 0)
{
arr[i][j]=1 ;
printf("%d ",arr[i][j]);
}
else if(j == i)
{
arr[i][j]=1 ;
printf("%d ",arr[i][j]);
}
else
{
arr[i][j]=arr[i-1][j-1]+arr[i-1][j];
printf("%d ",arr[i][j]);
}
}
printf("\n");
}
}
函数:
函数是C语言中管理代码的最小单位(若干行代码集合在一起形成一个整体),一个函数就相当于一段具有某项功能的代码
函数的分类:
标准库函数:
C语言标准委员会为C语言提供一些基本功能,把这些基础功能分别封装成函数,包赚成一个库(libc.so);
输入输出:
scanf、printf、getchar、putchar、gets、puts
字符串:
strlen、stract、strcpy、strcmp、strstr
数学:
sqrt、pow 注意:编译时需要 参数-lm
时间:
time(time.h)(NULL)获取到自1970年1月1日00:00:00到现在一共过了多少秒
内存:
malloc、free
other:
rand(头文件:stdlib)、srand、system
伪随机:把所有符号整数打乱顺序储存到计算机中,rand可以获取到一个无符号整数,rand默认从第一个位置获取
srand设置获取随机数的位置
练习9:显示出10个[100,1000)的随机数
[a.b)
rand()%(b-a)+a;
#include <stdio.h>
#include <stdlib.h>
int main()
{
for(int i=0;i<10;i++)
{
int num =rand()%900+100;
printf("%d\n",num);
}
}
- 系统函数:
操作系统提供的一些功能,以函数形式使用(但不是函数),系统API(接口)
- 第三方库函数:
JDON、MD5、XML、openCV、openGLrand、Qt、MFC
- 自定义函数:
1、方便管理代码,编写程序时思路更清晰
2、代码复用,同一段代码可以不同位置多次执行
函数声明:
返回值类型 函数名(类型 变量名,类型 变量名,…)
1、一般根据函数的功能来取函数名,全部小写单词之间用下划线分隔
2、参数的个数、类型由函数的功能所需要的数据决定,被调用时由调用者提供,如果不需要则写void
3、返回值类型根据函数的结果类型决定,如果没有返回值则写void
函数定义:
返回值 函数名(类型 变量名,类型 变量名,…)
{
函数体;
return 数据;
}
函数的调用:
函数(数据1,数据2,…);
返回值会在函数执行完成后放置在调用位置,处理方法;
1、存储到变量中,长期使用
2、立即使用,可以显示或参与运算
函数之间参数的传递:
1、调用者向被调用者传递,由实参向形参传递
函数中的命名空间都相互独立,函数中的变量可以重名
函数在调用时,其实是把实参给形参赋值
函数之间不能通过传递共享变量。
数组当作函数的参数时,长度会丢失,需要额外添加一个参数来传递它的长度
2、被调用者向调用者传递,使用return返回数据
不写return语句也会有返回值
调用者和被调用者之间会约定一个空间用于存储返回值,return语句的功能就把一个数据存储到这个空间,如果不写return语句,调用者就会得到一个默认值(不确定)。
练习10:定义一个函数,判断一个整数是否为素数,调用它显示出100~1000所有的素数。
#include <stdio.h>
#include <stdbool.h>
//函数声明
bool is_prime(int num);
int main()
{
for(int i = 100; i<=1000;i++)
{
if(is_prime(i))
{
printf(" %d",i);
}
}
}
//函数的定义
bool is_prime(int num)
{
for(int i=2; i<num;i++)
{
if(num % i == 0)
{
return false;
}
}
return true;
}