#10159. 2026/9/6/LBY笔记(函数+进制转换)

2026/9/6/LBY笔记(函数+进制转换)

函数与进制转换课堂笔记

一、函数是什么

函数就是把一段有用的代码单独取一个名字。

以后需要完成同样的任务时,直接使用函数名,不用把整段代码重新写一遍。

例如,昨天“五边形面积”中需要计算3次三角形面积:

x(a,b,c)
x(c,d,e)
x(e,f,g)

只写一次求三角形面积的函数,就可以调用3次。这就是函数最重要的作用:相同工作只写一次,多次使用。


二、函数的基本格式

返回类型 函数名(参数列表){
	//完成任务
	return 返回值;
}

例如:

int add(int a,int b){
	return a+b;
}

调用函数:

int ans=add(3,5);

执行过程:

把3交给a,把5交给b
函数算出a+b
return把8送回来
ans得到8

认识函数的4个部分

观察:

double get(int x){
	return x*0.1;
}
部分 本例 意思
返回类型 double 函数送回来的是小数
函数名 get 调用函数时使用的名字
参数 int x 调用函数时交给它的数据
返回值 return x*0.1 函数计算完成后送回的答案

调用函数时要注意

定义是:

int add(int a,int b)

调用时就要给两个整数:

add(3,5);       //正确
add(3);         //错误:少给了一个数

参数按照位置接收:

add(3,5)

表示a=3,b=5


三、什么时候适合写函数

遇到下面三种情况,可以考虑写函数。

1. 同一个计算要做很多次

例如昨天的“五边形面积”,三角形面积要计算3次。

2. 一段代码有一个清楚的小任务

例如:

  • 判断一个数是不是完全数;
  • 求三个数的最大值;
  • 把十进制数转成八进制;
  • 判断某个数字能不能用于一种进制。

3. 主函数太长,读起来不清楚

可以把某个独立步骤放进函数,让main只负责输入、调用和输出。

int main(){
	cin>>a;
	cout<<work(a);
	return 0;
}

四、昨天写过的函数例子

例1:求三个数的最大值

“最大数max”中写了:

int x(int a,int b,int c){
	if(a>=b&&a>=c) return a;
	if(b>=a&&b>=c) return b;
	if(c>=a&&c>=b) return c;
}

这个函数:

  • 输入3个整数;
  • 返回其中最大的数;
  • 返回类型是int

调用时还可以把算式作为参数:

x(a+b,b,c)

它比较的是a+b、b、c三个数,并不是比较原来的a、b、c

更简洁的写法

int max3(int a,int b,int c){
	return max(max(a,b),c);
}

知识点

  • max(a,b)返回a、b中较大的数。
  • max(max(a,b),c)先比较a、b,再和c比较。
  • 使用if写有返回值的函数时,要保证每一种情况都有return

易错点

第一次提交时,printf这一行少了一个右括号,导致编译失败。函数嵌套较多时,建议从里面向外配括号:

x(a,b,c)
x(a+b,b,c)*x(a,b,b+c)
1.0*x(a,b,c)/(x(a+b,b,c)*x(a,b,b+c))

例2:计算一条短信的费用

“短信计费”中写了:

double get(int x){
	if(x%70==0) return x/70*0.1;
	else return x/70*0.1+0.1;
}

这个函数:

  • 参数x是一条短信的字数;
  • 每70个字收费0.1元;
  • 不满70个字的部分也按一段收费;
  • 返回值是费用,所以类型用double

例如:

x=140:正好2段,费用0.2元
x=141:需要3段,费用0.3元

完整使用方法

double get(int x){
	if(x%70==0) return x/70*0.1;
	else return x/70*0.1+0.1;
}
int main(){
	int n,x;
	double sum=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x;
		sum+=get(x);              //调用函数计算本条短信费用
	}
	printf("%.1lf",sum);        //按照题目要求保留1位小数
	return 0;
}

知识点

  • 函数可以放在循环中调用。
  • 每读入一条短信,就调用一次get(x)
  • 返回值可以直接参与累加:sum+=get(x)

昨天的易错点

第一次提交得了91分,主要差别在输出格式。小数题要认真看题目要求:

cout<<sum;              //不一定显示1位小数
printf("%.1lf",sum);   //固定保留1位小数

例3:求三角形面积

“五边形面积”中写了:

double x(int a,int b,int c){
	double p=(a+b+c)/2.0;
	return sqrt(p*(p-a)*(p-b)*(p-c));
}

这是海伦公式:

p=(a+b+c)÷2
面积=sqrt(p×(p-a)×(p-b)×(p-c))

五边形被分成3个三角形后,可以写:

printf("%.2lf",x(a,b,c)+x(c,d,e)+x(e,f,g));

这个例子为什么特别适合使用函数

如果不写函数,海伦公式要重复写3次,代码会很长,也更容易写错。写成函数后:

  • 公式只写一次;
  • 每次换一组三条边;
  • 三个返回值可以直接相加。

知识点

  • 面积可能是小数,所以函数返回类型是double
  • (a+b+c)/2.0中的2.0可以得到正确的小数。
  • sqrt(x)返回x的平方根。

例4:判断完全数

“求正整数2和n之间的完全数”中写了:

bool x(int a){
	int sum=0;
	for(int i=1;i<a;i++){
		if(a%i==0) sum+=i;
	}
	if(sum==a) return 1;
	else return 0;
}

这个函数不是求一个数字,而是回答“是”或“不是”,所以返回类型使用bool

返回1:a是完全数
返回0:a不是完全数

调用:

for(int i=2;i<=n;i++){
	if(x(i)==1) cout<<i<<"\n";
}

更直接的返回写法

bool check(int a){
	int sum=0;
	for(int i=1;i<a;i++){
		if(a%i==0) sum+=i;
	}
	return sum==a;
}

sum==a本身就是一个判断结果,成立是1,不成立是0,因此可以直接返回。

知识点

  • bool函数适合判断“是不是、能不能、存不存在”。
  • 函数名写成checkisPerfect会比只写x更容易看懂。
  • 主函数不需要知道函数怎样判断,只需要使用返回结果。

例5:十进制转二、八、十六进制

昨天依次完成了二进制、八进制和十六进制转换。这三题的做法其实是同一个模板,只是进制不同。

八进制函数:

string s(long long a){
	if(a==0){
		return "0";
	}
	string x;
	while(a>0){
		int y=a%8;
		x=char(y+'0')+x;
		a/=8;
	}
	return x;
}

函数执行过程

假设把十进制10转成八进制:

10÷8,余2,x="2"
1÷8,余1,x="12"
答案是12

余数最先得到的是最低位,所以每次要加在字符串前面:

x=char(y+'0')+x;

昨天从二进制到十六进制的进步

开始时零的处理写成了:

if(a==0) cout<<'0';

这里函数的任务是“返回转换结果”,不应该在函数里面偷偷输出。后来正确改成:

if(a==0) return "0";

这个修改非常关键:函数负责计算和返回,main负责输出。

开始时参数使用int,后来改成long long,也能处理更大的输入。

十六进制为什么多一步判断

二进制和八进制的每一位都不超过9,可以直接写:

char(y+'0')

十六进制的余数可能是10~15,要使用A~F

if(y<=9) x=char(y+'0')+x;
else x=char(y-10+'A')+x;

例6:判断一个数可以属于哪些进制

昨天“进制判断”中写了一个函数,找字符串中最大的数字:

int x(string a){
	int t=0;
	for(int i=0;i<a.size();i++){
		int num;
		if(a[i]>='0'&&a[i]<='9') num=a[i]-'0';
		else num=a[i]-'A'+10;
		if(num>t) t=num;
	}
	return t;
}

例如字符串"19A"

'1'变成1
'9'变成9
'A'变成10
最大数字是10

如果一个数中最大的数字是t,那么它所在的进制必须大于t

例如数字中出现了8

  • 不能是二进制;
  • 不能是八进制;
  • 可以是十进制或十六进制。

知识点

  • 函数的参数不只能是整数,也可以是字符串:int x(string a)
  • 字符数字转整数:a[i]-'0'
  • 大写字母转数值:a[i]-'A'+10
  • 函数可以把一段较复杂的扫描工作单独完成,让主函数只负责判断和输出。

五、函数的返回类型怎么选

函数要送回什么 返回类型 昨天的例子
整数 intlong long 三数最大值、最大数字
小数 double 短信费用、三角形面积
是或不是 bool 判断完全数
一串字符 string 十进制转其他进制
不需要送回答案 void 只负责输出或修改数据的函数

返回类型要和return后面的结果一致:

double get(int x){
	return 0.3;        //正确:返回小数
}

string change(int x){
	return "101";     //正确:返回字符串
}

六、参数、全局变量和局部变量

参数

int max3(int a,int b,int c)

a、b、c是函数收到的数据。每次调用可以交给它不同的数。

局部变量

double area(int a,int b,int c){
	double p=(a+b+c)/2.0;
	return sqrt(p*(p-a)*(p-b)*(p-c));
}

p只在area函数内部使用,离开函数后就不能使用。

全局变量

写在所有函数外面的变量是全局变量,所有函数都能使用。但是函数只需要一两个数据时,最好通过参数传进去,函数会更清楚。

推荐:

int check(int a){
	//直接使用参数a
}

不推荐让函数依赖很多外面的变量,否则以后很难知道函数正在处理谁。


七、进制转换完整模板

1. 十进制转其他进制

方法:除进制取余,把余数加在答案前面。

string tento(long long x,int jz){
	if(x==0) return "0";             //0必须单独处理
	string ans;
	while(x>0){
		int r=x%jz;
		if(r<=9) ans=char(r+'0')+ans;
		else ans=char(r-10+'A')+ans;
		x/=jz;
	}
	return ans;
}

调用:

cout<<tento(10,2)<<"\n";    //1010
cout<<tento(10,8)<<"\n";    //12
cout<<tento(26,16)<<"\n";   //1A

2. 其他进制转十进制

方法:从右向左计算“数字乘位权”。

long long toten(string s,int jz){
	long long ans=0,w=1;
	for(int i=s.size()-1;i>=0;i--){
		int num;
		if(s[i]>='0'&&s[i]<='9') num=s[i]-'0';
		else num=s[i]-'A'+10;
		ans+=num*w;
		w*=jz;                         //下一位的位权变大
	}
	return ans;
}

例如二进制1011

从右向左:1×1+1×2+0×4+1×8=11

3. 任意进制转任意进制

先转成十进制,再从十进制转成目标进制:

string change(string s,int a,int b){
	long long x=toten(s,a);    //a进制转十进制
	return tento(x,b);         //十进制转b进制
}

八、函数最常见的错误

1. 有返回类型,却没有返回值

int f(int a){
	if(a>0) return 1;
	//a<=0时没有return,错误
}

应改成:

int f(int a){
	if(a>0) return 1;
	else return 0;
}

2. 该返回时却在函数中输出

string change(int x){
	if(x==0) cout<<"0";       //不推荐
}

应写:

if(x==0) return "0";

3. 返回类型选错

面积和费用可能是小数,不能使用int返回。

4. 整数除法丢掉小数

(a+b+c)/2       //可能丢掉0.5
(a+b+c)/2.0     //正确得到小数

5. 调用时参数数量或顺序错误

定义3个参数,调用时也要给3个数据,并按正确顺序传入。

6. 函数名看不出用途

昨天使用xs可以完成题目,但复习时不容易马上看懂。建议逐渐使用更清楚的名字:

x(a,b,c)       -> max3(a,b,c)
x(a)           -> check(a)
s(a)           -> tento(a,jz)
x(string a)    -> maxdigit(a)

短名字没有错,但函数名能说明任务,检查代码会更快。


九、昨天代码的关键建议

做得好的地方

  • 已经会根据答案类型选择int、double、bool、string
  • 会在循环中多次调用函数。
  • 会把海伦公式单独写成函数,并把3次结果相加。
  • 八进制题第二次提交能主动修正0long long问题。
  • 十六进制转换正确处理了A~F
  • 能把“找字符串中最大数字”的过程放进函数,让主函数更短。

下一步重点改进

  1. 写完函数后,先检查每一种情况有没有return
  2. 函数只负责计算时,不要在函数里cout,把结果return给主函数。
  3. 小数题先圈出“保留几位小数”,最后再检查printf格式。
  4. 输入可能很大时,参数和变量统一使用long long
  5. 函数调用嵌套较多时,从内向外检查括号。
  6. 尽量给函数取一个能看懂用途的名字。

十、复习自查表

写完一个函数后,按顺序检查:

□ 函数要完成什么任务?
□ 返回类型选对了吗?
□ 参数数量和类型对吗?
□ 每一种情况都有return吗?
□ 调用函数时,参数顺序对吗?
□ 整数除法需要写2.0或1.0吗?
□ 输入0时会得到正确结果吗?
□ 小数输出位数符合题目要求吗?
□ 函数名能不能看出它的作用?

最重要的一句话:

main负责输入和输出,函数负责完成一个清楚的小任务并返回结果。