赞
踩
函数封装的优点:
代码可读性好(程序功能逻辑更加直观)、美观性好、调试性好(按函数模块debug)
写代码的习惯
①把不同的功能模块封装成为独立的函数
②主函数中只写整个程序开发的架构(功能逻辑的框架),即多个模块之间逻辑上的内容,每个功能逻辑再进行单独封装
C/C++程序执行入口?
没有特殊情况下(宏),程序执行入口是主函数(main函数)
函数
①返回值类型,无返回值时void
②函数名,表述函数功能需求的语义信息,is_prime()是否素数
③参数列表,()中的内容:包括参数个数、类型、顺序,作用是将各种类型的值进行传递(传入传出)
④函数体
return向函数调用处返回值,函数体中可以有多个return,但生效的只有1个
向外传出值的2种方式:return,传出参数(通过指针变量实现,它的功能表现为传出参数)
函数声明
①②③就完成了函数声明
函数声明的目的是知道怎么使用即可,不需要知道怎么实现,就像我们使用scanf和printf函数一样
函数定义
函数声明+函数体就是函数定义
数学中:y = f(x)
C语言中:函数传入值,通过功能逻辑返回值,是一种映射;
数组下标对值也是一种映射;
故而,函数是压缩的数组,数组是展开的函数,是一种时间换空间的思想。
K&R 风格的函数定义(不建议,因为太老了)
函数参数的类型声明放在下面
#include <stdio.h>
int fac(int n) {
if (n == 1) return 1;
return n * fac(n - 1);
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
printf("fac(%d) = %d\n", n, fac(n));
}
return 0;
}
链接:函数指针
函数的参数列表的功能:将各种类型的值进行传递(传进传出)
函数指针的功能:把函数当做参数传递
函数指针
如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。
既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。
函数指针变量的定义:
函数返回值类型 (* 指针变量名) (函数参数列表);
使用传入的函数:直接通过函数名调用,如g函数中直接调用f1函数,return f1(x);
函数指针的应用:定义分段函数,如上图
#include<stdio.h> typedef long long ll; ll Triangle(ll n) { return n * (n + 1) / 2; } ll Pentagonal(ll n) { return n * (3 * n - 1) / 2; } ll Hexagonal(ll n) { return n * (2 * n - 1); } ll binary_search(ll (*arr)(ll), ll n, ll x) { // 函数指针作为形参 ll head = 1, tail = n, mid; while (head <= tail) { mid = (head + tail) >> 1; if (arr(mid) == x) return mid; // 调用函数指针 if (arr(mid) < x) head = mid + 1; else tail = mid - 1; } return -1; } int main() { ll n = 143; //优化1 while(1) { n += 1; ll temp = Hexagonal(n); if (binary_search(Pentagonal, temp, temp) == -1) continue; //优化2 //if (binary_search(Triangle, temp, temp) == -1) continue; printf("%lld\n", temp); break; } return 0; }
// 基本的二分查找(传数组) int binary_search(int *arr, int n, int x) { //arr传数组变为(*arr)(int)传函数 int head = 0, tail = n - 1, mid; //边界head、tail由数组时0~n-1变为函数时1~n while (head <= tail) { mid = (head + tail) >> 1; if (arr[mid] == x) return mid; //arr[mid]对应改为arr(mid) if (arr[mid] < x) head = mid + 1; else tail = mid - 1; } return -1;//返回-1不固定,只是表示没有找到x的值 } int main() { ll n = 285;//n==285开始 while(1) { n += 1; ll temp = Triangle(n); // if (binary_search(Pentagonal, temp, temp) != -1) { //以当前三角形的值作为项数肯定存在,因为差了一个数量级 if (binary_search(Hexagonal, temp, temp) != -1) { printf("%d\n", temp); break; } } // //对偶原则减少if嵌套(缩进):!=变为==,加continue; if (binary_search(Pentagonal, temp, temp) == -1) continue; if (binary_search(Hexagonal, temp, temp) == -1) continue; printf("%lld\n", temp);//%d变为%lld break;//退出死循环 } return 0; }
证明欧几里得算法:gcd(a, b) = gcd(b, a%b)
设 gcd(a, b) = r,证明 r 是 b, a % b 的公约数
此时 a = xr, b = yr;
a % b = a - kb = (x - ky)r,其中 k = floor(a / b)即 k = a / b
证明 r 是 b, a%b 最大的公约数
#include<stdio.h>
int gcd(int a, int b) {
// if (!b) return a;// b == 0用 !b 表示
//return gcd(b, a % b);
return (b ? gcd(b, a % b) : a);//冒号表达式代替上述2行
}
int main() {
int a, b;
while(scanf("%d%d", &a, &b)) {//注意没有 != EOF也可以
printf("gcd(%d, %d) = %d\n", a, b, gcd(a, b));
}
return 0;
}
求ax+by=1(a,b,x,y都为整数)的整数解
[10.ex_gcd.c] #include <stdio.h> int ex_gcd(int a, int b, int *x, int *y) { if (!b) { *x = 1, *y =0; return a; } int xx, yy, ret = ex_gcd(b, a % b, &xx, &yy); *x = yy; *y = xx - a / b * yy; return ret; } int main() { int a, b, x, y; while (scanf("%d%d", &a, &b) != EOF) { printf("ex_gcd(%d, %d) = %d\n", a, b, ex_gcd(a, b, &x, &y)); printf("%d * %d + %d * %d = %d\n", a, x, b, y, a * x + b * y); } return 0; }
#include <stdio.h> #include <inttypes.h> #include <stdarg.h> int max_int(int n, ...) { int ans = INT32_MIN; va_list arg; va_start(arg, n); while (n--) { int temp = va_arg(arg, int); if (temp > ans) ans = temp; } va_end(arg); return ans; } int main() { printf("%d\n", max_int(3, 1, 5, 10)); printf("%d\n", max_int(2, 1, 3)); printf("%d\n", max_int(6, 1, 3, 5, 7, 13, 15, 17)); // 17不比较 return 0; }
#include <stdio.h> //const int my_printf(const char *frm, ...) { int cnt = 0; for (int i = 0; frm[i]; i++) {//i < strlen(frm) putchar(frm[i]), ++cnt; } return cnt; } int main() { printf("hello world\n"); my_printf("hello world\n"); return 0; }
#include <stdio.h> #include <stdarg.h> //输出frm后面的变参列表...用变参函数实现 int my_printf(const char *frm, ...) { int cnt = 0; va_list arg;//定义指针 va_start(arg, frm);//arg指向frm后面的...的起始地址 #define PUTC(a) putchar(a), ++cnt for (int i = 0; frm[i]; i++) { switch (frm[i]) { //根据格式控制占位符解读 case '%': { switch (frm[++i]) { case '%': PUTC(frm[i]); break; case 'd': { int x = va_arg(arg, int);//取当前arg位置的int数据 int temp = 0; //翻转a(123 -> 321) while (x) { temp = temp * 10 + x % 10; x /= 10; } //打印字符时倒着打印(321 -> '1''2''3') /*【问题】a == 0时while不打印,do while解决 while (temp) { PUTC(temp % 10 + '0'); temp /= 10; }*/ do { PUTC(temp % 10 + '0');//取temp最后一位的整数,加上'0'或48变成字符对应的ASC码 temp /= 10; } while (temp); } break; } } break; default : PUTC(frm[i]); break; } //PUTC(frm[i]); //putchar(frm[i]), ++cnt;封装成一个宏 } #undef PUTC return cnt; } int main() { printf("hello world\n"); my_printf("hello world\n"); int a = 123; my_printf("int (a) = %%\n", a); printf("int (a) = %d\n", a); my_printf("int (a) = %d\n", a); printf("int (a) = %d\n", 0); my_printf("int (a) = %d\n", 0); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。