#include #include #define N 5 int main() { int i,j; int arr[][] srand((unsigned)time(NULL)) for(i=0;i 二、(编译)对一个二维数组中的数据排序,要求如下: 将整个数组中值最小的元素所在行调整为数组第一行,将除第一行外的行中最小元素所在行调整为第2行,将除第1,2行外的行中最小值元素所在行调整为第3行,以此类推 #include #include #include #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 //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 2 int main() 3 { 4 int i = 0; 5 int j=0; 6 { 7 printf("%d,%d,%dn",i++,i++,i++); 8 } 9 10 { 11 printf("%d,%d,%d,%d,%dn", ++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 中定义了相关方法: typedef struct { char*ao; int offset; } va list; 头文件:#include 函数系列介绍(//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 #include float avg(int n,…) { va_list args; int i; float ret=0.0; va_start(args,n); for(i=0;i 4、递归函数 定义: 在函数调用时,直接或间接地自己调用自己的函数 形式: 直接调用→直接递归 间接调用→间接递归 过程: ①第一阶段称为“递推”阶段: 将原有的问题分解为新的子问题,逐渐以未知的向已知的方向推测,最终达到已知的条件,即递归结束条件,这时递归阶段结束;②第二阶段称为“回归”阶段: 该阶段从已知的条件出发,按照“递推”的逆过程,逐一求值返回,最后到达递推的开始处,结束回归阶段,完成递归调用。 条件: ①须有完成函数任务的语句②一个确定是否能避免递归调用的测试③一个递归调用语句——该语句的参数应该逐渐逼近结束条件,以至最后断绝递归。④必须先测试,后递归调用——递归调用是有条件的,满足了条件后,才可以递归。 特点: ①递归调用不是重新复制该函数,每次调用它 时,新的局部变量和形参会在内存中重新分配内存单元,并以新的变量重新开始执行;每次递归返回时,当前调用层的局部变量和形参被释放,并返回上次调用自身的地方继续执行;②递归调用一般并不节省内存空间,因为每次调用都要产生一组新的局部变量,从而不破坏上层的局部变量;③递归调用一般并不能加快程序的执行速度,因为每次调用都要保护上层局部量(现场),而返回时又要恢复上层局部量,占用执行时间;④递归函数中,必须有结束递归的条件;⑤递归调用的优点是能实现一些迭代算法难以解决的问题。 5、返回指针值的函数 格式 类型 *函数名(形参列表) 举例 int *a(int x, int y) *函数名两侧不能加括号,由于括号的 优先级比*高。首先 a 与其后参数结合, 表明 a 是函数名,然后与*结合,表明是 一个指针形函数。 6、函数的指针 定义 函数指针是函数的物理入口地址。即是在编译时,分配的物理入口地址。 引用 不带括号和参数的函数名代表函数的入口地址。 对指向函数的指 针变量,像p+n p++,p- -等运 算是无意义的。 函数指针不能指 向函数中的某条 指令。 [ ]的作用 ①找到对应元素的位置,由起始地址开始偏移 a+i*l(l:元素字节长度) ②取内容 行地址,列地址 两个方法: 下标法: 指针法: 五、(编译)将字符串中的第一个数字字符串转换成整数输出 1 #include 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("%sn",str); //不带空格输入 13 //scanf("%[^N]",str);(可带空格) 14 //fgets(str,100,stdin);(可带空格) 15 16 while(str[i]!=' ') 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=%dn",num); 36 return 0; 37 }
将整个数组中值最小的元素所在行调整为数组第一行,将除第一行外的行中最小元素所在行调整为第2行,将除第1,2行外的行中最小值元素所在行调整为第3行,以此类推
#include #include #include #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 //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; }
见文件
函数调用过程中,变量值发生变化的位置(点),称为函数参数“顺序点”。
①语句结束时,值改变
k=2; k=k++ + k++;
k=2;
k=k++ + k++;
②&& || , ?:等运算符
③函数参数传递是的求值顺序
int k = 1; func(k,k++); ↓ ↓ 2 1
int k = 1;
func(k,k++);
↓ ↓
2 1
1 #include 2 int main() 3 { 4 int i = 0; 5 int j=0; 6 { 7 printf("%d,%d,%dn",i++,i++,i++); 8 } 9 10 { 11 printf("%d,%d,%d,%d,%dn", ++j, ++j,j++,++j,j++); 12 } 13 return 0; 14 } ~
当系统调用主函数时,系统也可将参数 (命令行) 传给主函数。
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
举例:
当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
c语言提供了函数的不定长参数使用如: void func(int a, …) 三个省略号,表示了不定长参数。注意:c标准规定函数必须至少有一个明确定义的参数,则省略号前面必须有至少一个参数。 va_list宏定义了一个指针类型,这个指针类型指向参数列表中的参数。
#include 中定义了相关方法: typedef struct { char*ao; int offset; } va list;
#include 中定义了相关方法:
typedef struct
{
char*ao;
int offset;
}
va list;
头文件:#include 函数系列介绍(//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 #include float avg(int n,…) { va_list args; int i; float ret=0.0; va_start(args,n); for(i=0;i 4、递归函数 定义: 在函数调用时,直接或间接地自己调用自己的函数 形式: 直接调用→直接递归 间接调用→间接递归 过程: ①第一阶段称为“递推”阶段: 将原有的问题分解为新的子问题,逐渐以未知的向已知的方向推测,最终达到已知的条件,即递归结束条件,这时递归阶段结束;②第二阶段称为“回归”阶段: 该阶段从已知的条件出发,按照“递推”的逆过程,逐一求值返回,最后到达递推的开始处,结束回归阶段,完成递归调用。 条件: ①须有完成函数任务的语句②一个确定是否能避免递归调用的测试③一个递归调用语句——该语句的参数应该逐渐逼近结束条件,以至最后断绝递归。④必须先测试,后递归调用——递归调用是有条件的,满足了条件后,才可以递归。 特点: ①递归调用不是重新复制该函数,每次调用它 时,新的局部变量和形参会在内存中重新分配内存单元,并以新的变量重新开始执行;每次递归返回时,当前调用层的局部变量和形参被释放,并返回上次调用自身的地方继续执行;②递归调用一般并不节省内存空间,因为每次调用都要产生一组新的局部变量,从而不破坏上层的局部变量;③递归调用一般并不能加快程序的执行速度,因为每次调用都要保护上层局部量(现场),而返回时又要恢复上层局部量,占用执行时间;④递归函数中,必须有结束递归的条件;⑤递归调用的优点是能实现一些迭代算法难以解决的问题。 5、返回指针值的函数 格式 类型 *函数名(形参列表) 举例 int *a(int x, int y) *函数名两侧不能加括号,由于括号的 优先级比*高。首先 a 与其后参数结合, 表明 a 是函数名,然后与*结合,表明是 一个指针形函数。 6、函数的指针 定义 函数指针是函数的物理入口地址。即是在编译时,分配的物理入口地址。 引用 不带括号和参数的函数名代表函数的入口地址。 对指向函数的指 针变量,像p+n p++,p- -等运 算是无意义的。 函数指针不能指 向函数中的某条 指令。 [ ]的作用 ①找到对应元素的位置,由起始地址开始偏移 a+i*l(l:元素字节长度) ②取内容 行地址,列地址 两个方法: 下标法: 指针法: 五、(编译)将字符串中的第一个数字字符串转换成整数输出 1 #include 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("%sn",str); //不带空格输入 13 //scanf("%[^N]",str);(可带空格) 14 //fgets(str,100,stdin);(可带空格) 15 16 while(str[i]!=' ') 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=%dn",num); 36 return 0; 37 }
调用参数表以前,定义一个va_list类型变量,对ap进行初始化,初始化完成后,ap指向可变参数表中的第一个参数(由va_start函数实现),获取参数,调用va_arg函数,第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回这个指定类型的值,并且把ap的位置指向列表的下一个变量位置,获取了所有的参数后,要关闭ap,调用va_end函数即可。
#include #include float avg(int n,…) { va_list args; int i; float ret=0.0; va_start(args,n); for(i=0;i 4、递归函数 定义: 在函数调用时,直接或间接地自己调用自己的函数 形式: 直接调用→直接递归 间接调用→间接递归 过程: ①第一阶段称为“递推”阶段: 将原有的问题分解为新的子问题,逐渐以未知的向已知的方向推测,最终达到已知的条件,即递归结束条件,这时递归阶段结束;②第二阶段称为“回归”阶段: 该阶段从已知的条件出发,按照“递推”的逆过程,逐一求值返回,最后到达递推的开始处,结束回归阶段,完成递归调用。 条件: ①须有完成函数任务的语句②一个确定是否能避免递归调用的测试③一个递归调用语句——该语句的参数应该逐渐逼近结束条件,以至最后断绝递归。④必须先测试,后递归调用——递归调用是有条件的,满足了条件后,才可以递归。 特点: ①递归调用不是重新复制该函数,每次调用它 时,新的局部变量和形参会在内存中重新分配内存单元,并以新的变量重新开始执行;每次递归返回时,当前调用层的局部变量和形参被释放,并返回上次调用自身的地方继续执行;②递归调用一般并不节省内存空间,因为每次调用都要产生一组新的局部变量,从而不破坏上层的局部变量;③递归调用一般并不能加快程序的执行速度,因为每次调用都要保护上层局部量(现场),而返回时又要恢复上层局部量,占用执行时间;④递归函数中,必须有结束递归的条件;⑤递归调用的优点是能实现一些迭代算法难以解决的问题。 5、返回指针值的函数 格式 类型 *函数名(形参列表) 举例 int *a(int x, int y) *函数名两侧不能加括号,由于括号的 优先级比*高。首先 a 与其后参数结合, 表明 a 是函数名,然后与*结合,表明是 一个指针形函数。 6、函数的指针 定义 函数指针是函数的物理入口地址。即是在编译时,分配的物理入口地址。 引用 不带括号和参数的函数名代表函数的入口地址。 对指向函数的指 针变量,像p+n p++,p- -等运 算是无意义的。 函数指针不能指 向函数中的某条 指令。 [ ]的作用 ①找到对应元素的位置,由起始地址开始偏移 a+i*l(l:元素字节长度) ②取内容 行地址,列地址 两个方法: 下标法: 指针法: 五、(编译)将字符串中的第一个数字字符串转换成整数输出 1 #include 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("%sn",str); //不带空格输入 13 //scanf("%[^N]",str);(可带空格) 14 //fgets(str,100,stdin);(可带空格) 15 16 while(str[i]!=' ') 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=%dn",num); 36 return 0; 37 }
在函数调用时,直接或间接地自己调用自己的函数
直接调用→直接递归
间接调用→间接递归
①第一阶段称为“递推”阶段: 将原有的问题分解为新的子问题,逐渐以未知的向已知的方向推测,最终达到已知的条件,即递归结束条件,这时递归阶段结束;②第二阶段称为“回归”阶段: 该阶段从已知的条件出发,按照“递推”的逆过程,逐一求值返回,最后到达递推的开始处,结束回归阶段,完成递归调用。 条件:
①须有完成函数任务的语句②一个确定是否能避免递归调用的测试③一个递归调用语句——该语句的参数应该逐渐逼近结束条件,以至最后断绝递归。④必须先测试,后递归调用——递归调用是有条件的,满足了条件后,才可以递归。 特点:
①递归调用不是重新复制该函数,每次调用它 时,新的局部变量和形参会在内存中重新分配内存单元,并以新的变量重新开始执行;每次递归返回时,当前调用层的局部变量和形参被释放,并返回上次调用自身的地方继续执行;②递归调用一般并不节省内存空间,因为每次调用都要产生一组新的局部变量,从而不破坏上层的局部变量;③递归调用一般并不能加快程序的执行速度,因为每次调用都要保护上层局部量(现场),而返回时又要恢复上层局部量,占用执行时间;④递归函数中,必须有结束递归的条件;⑤递归调用的优点是能实现一些迭代算法难以解决的问题。 5、返回指针值的函数 格式
类型 *函数名(形参列表)
int *a(int x, int y)
*函数名两侧不能加括号,由于括号的 优先级比*高。首先 a 与其后参数结合, 表明 a 是函数名,然后与*结合,表明是 一个指针形函数。
函数指针是函数的物理入口地址。即是在编译时,分配的物理入口地址。
不带括号和参数的函数名代表函数的入口地址。
对指向函数的指 针变量,像p+n p++,p- -等运 算是无意义的。 函数指针不能指 向函数中的某条 指令。
①找到对应元素的位置,由起始地址开始偏移 a+i*l(l:元素字节长度)
②取内容
行地址,列地址
两个方法:
下标法:
指针法:
1 #include 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("%sn",str); //不带空格输入 13 //scanf("%[^N]",str);(可带空格) 14 //fgets(str,100,stdin);(可带空格) 15 16 while(str[i]!=' ') 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=%dn",num); 36 return 0; 37 }
上一篇 【笔记】C语言基础 循环
下一篇 C语言常用字符串、内存函数的实现
版权所有 (c)2021-2022 MSHXW.COM
ICP备案号:晋ICP备2021003244-6号