嵌入式学习 2022.1.23
一、(编译)创建随机数组(5*5为例)
#include <stdio.h>
#include <time>
#define N 5
int main()
{
int i,j;
int arr[][]
srand((unsigned)time(NULL))
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
arr[i][j]=rand()%100;
printf("%4d",arr[i][j]);
}
printf("\n");
}
return 0;
}
二、(编译)对一个二维数组中的数据排序,要求如下:
- 将整个数组中值最小的元素所在行调整为数组第一行,
- 将除第一行外的行中最小元素所在行调整为第2行,
- 将除第1,2行外的行中最小值元素所在行调整为第3行,以此类推
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW_LENGTH 3
#define COL_LENGTH 3
int main() {
int arr[ROW_LENGTH][COL_LENGTH];
int min_row, min_num;
srand((unsigned)time(NULL));
for (int i = 0; i < ROW_LENGTH; i++) {
for (int j = 0; j < COL_LENGTH; j++) {
arr[i][j] = rand() % 100;
}
}
for (int i = 0; i < ROW_LENGTH; i++) {
for (int j = 0; j < COL_LENGTH; j++) {
printf("arr[%d][%d]:%d ", i, j, arr[i][j]);
}
printf("\n");
}
printf("\n");
for (int k = 0; k < COL_LENGTH; k++) {
min_num = arr[k][0];
min_row = k;
//find the minimum value
for (int i = k; i < COL_LENGTH; i++) {
for (int j = 0; j < ROW_LENGTH; j++) {
if (arr[i][j] < min_num) {
min_row = i;
min_num = arr[i][j];
}
}
}
//swap
/*for (int i = 0; i < ROW_LENGTH; i++) {
int t = arr[min_row][i];
arr[min_row][i] = arr[k][i];
arr[k][i] = t;
}*/
//this method of swap cannot handle the same address, use it with caution
if (k != min_row) {
for (int i = 0; i < ROW_LENGTH; i++) {
arr[min_row][i] = arr[min_row][i] + arr[k][i];
arr[k][i] = arr[min_row][i] - arr[k][i];
arr[min_row][i] = arr[min_row][i] - arr[k][i];
}
}
}
for (int i = 0; i < ROW_LENGTH; i++) {
for (int j = 0; j < COL_LENGTH; j++) {
printf("arr[%d][%d]:%d ", i, j, arr[i][j]);
}
printf("\n");
}
printf("\n");
return 0;
}
三、编程规范
见文件
四、函数调用
1、函数参数顺序点
定义:
函数调用过程中,变量值发生变化的位置(点),称为函数参数“顺序点”。
位置:
①语句结束时,值改变
k=2;
k=k++ + k++;
②&& || , ?:等运算符
③函数参数传递是的求值顺序
int k = 1;
func(k,k++);
↓ ↓
2 1
求值顺序:从右往左
1 #include <stdio.h>
2 int main()
3 {
4 int i = 0;
5 int j=0;
6 {
7 printf("%d,%d,%d\n",i++,i++,i++);
8 }
9
10 {
11 printf("%d,%d,%d,%d,%d\n", ++j, ++j,j++,++j,j++);
12 }
13 return 0;
14 }
~

2、带参数的main函数和命令行参数
原理:
当系统调用主函数时,系统也可将参数 (命令行) 传给主函数。
格式:
main(int argc, char *argv[ ])
举例:
当main(int argc, char *argv[ ]) 编译后,文件名为filename时,
filename as we fi 23
argc的值为5,argv的值为
argv[0] filename argv[1] as
argv[2] we argv[3] fi
argv[4] 23

3、可变参数列表
- c语言提供了函数的不定长参数使用
- 如:
- void func(int a, …)
- 三个省略号,表示了不定长参数。
- 注意:c标准规定函数必须至少有一个明确定义的参数,则省略号前面必须有至少一个参数。
va_list宏定义了一个指针类型,这个指针类型指向参数列表中的参数。
#include <stdarg.h>中定义了相关方法:
typedef struct
{
char*ao;
int offset;
}
va list;
-
头文件:#include <stdarg.h>
-
函数系列介绍(//ap可以改成自己的文件名)
- 1、va_start函数
- 原型:void va_start(va_list ap, last);
- ap:va_list 类型的变量,指向参数的指针
- last:最后一个显式声明的参数,以用来获取第一个变长参数的位置
- 2、va_arg函数
- 原型:type va_arg(va_list ap, type);
- ap:va_list 类型的变量,指向参数的指针
- type:指要获取的参数的类型
- 3、va_end函数
- 原型:void va_end(va_list ap);
- ap:va_list 类型的变量,指向参数的指针
- 4、va_copy函数
- 原型:void va_copy(va_list dest, va_list src);
过程:
- 调用参数表以前,定义一个va_list类型变量,对ap进行初始化,
- 初始化完成后,ap指向可变参数表中的第一个参数(由va_start函数实现),获取参数,
- 调用va_arg函数,第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回这个指定类型的值,并且把ap的位置指向列表的下一个变量位置,
- 获取了所有的参数后,要关闭ap,调用va_end函数即可。
#include <stdio.h>
#include <stdarg.h>
float avg(int n,…)
{
va_list args;
int i;
float ret=0.0;
va_start(args,n);
for(i=0;i<n;i++)
{
ret+=va_arg(args,int);
}
va_end(args);
return ret/n;
}
int main()
{
printf("%f\n",avg(5,1,2,3,4,5));
printf("%f\n",avg(3,2,4,6));
return 0;
}
gcc var_pare.c -0
4、递归函数
定义:
在函数调用时,直接或间接地自己调用自己的函数
形式:
直接调用→直接递归
间接调用→间接递归

过程:
- ①第一阶段称为“递推”阶段:
- 将原有的问题分解为新的子问题,逐渐以未知的向已知的方向推测,最终达到已知的条件,即递归结束条件,这时递归阶段结束;
- ②第二阶段称为“回归”阶段:
- 该阶段从已知的条件出发,按照“递推”的逆过程,逐一求值返回,最后到达递推的开始处,结束回归阶段,完成递归调用。
条件:
- ①须有完成函数任务的语句
- ②一个确定是否能避免递归调用的测试
- ③一个递归调用语句——该语句的参数应该逐渐逼近结束条件,以至最后断绝递归。
- ④必须先测试,后递归调用——递归调用是有条件的,满足了条件后,才可以递归。
特点:
- ①递归调用不是重新复制该函数,每次调用它 时,新的局部变量和形参会在内存中重新分配内存单元,并以新的变量重新开始执行;每次递归返回时,当前调用层的局部变量和形参被释放,并返回上次调用自身的地方继续执行;
- ②递归调用一般并不节省内存空间,因为每次调用都要产生一组新的局部变量,从而不破坏上层的局部变量;
- ③递归调用一般并不能加快程序的执行速度,因为每次调用都要保护上层局部量(现场),而返回时又要恢复上层局部量,占用执行时间;
- ④递归函数中,必须有结束递归的条件;
- ⑤递归调用的优点是能实现一些迭代算法难以解决的问题。
5、返回指针值的函数
格式
类型 *函数名(形参列表)
举例
int *a(int x, int y)
*函数名两侧不能加括号,由于括号的 优先级比*高。首先 a 与其后参数结合, 表明 a 是函数名,然后与*结合,表明是 一个指针形函数。
6、函数的指针
定义
函数指针是函数的物理入口地址。即是在编译时,分配的物理入口地址。
引用
不带括号和参数的函数名代表函数的入口地址。
对指向函数的指 针变量,像p+n p++,p- -等运 算是无意义的。 函数指针不能指 向函数中的某条 指令。

[ ]的作用
①找到对应元素的位置,由起始地址开始偏移 a+i*l(l:元素字节长度)
②取内容
行地址,列地址
两个方法:
下标法:
指针法:

五、(编译)将字符串中的第一个数字字符串转换成整数输出
1 #include <stdio.h>
2 #define N 100
3 int main()
4
5 {
6 char str[N];
7 int num=0; //输出结果
8 int i=0; //循环变量
9 int flag=0; //标志
10
11 printf("请输入一串包含数字的字符串:");
12 scanf("%s\n",str); //不带空格输入
13 //scanf("%[^\N]",str);(可带空格)
14 //fgets(str,100,stdin);(可带空格)
15
16 while(str[i]!='\0')
17 {
18 if(str[i]<'0'||str[i]>'9')
19 {
20 if(1==flag)
21 {
22 break;
23 }
24 }
25 else
26 {
27 if(0==flag)
28 {
29 flag=1;
30 }
31 num=num*10+(str[i]-'0');
32 }
33 i++;
34 }
35 printf("num=%d\n",num);
36 return 0;
37 }
浙公网安备 33010602011771号