C++笔记——函数

C++笔记——函数

一个函数就是一个功能

定义函数的格式

1.定义无参函数
类型名 函数名 (void)
{
声明部分
执行语句
}
2.定义有参函数
类型名 函数名 (形参列表)
{
声明部分
执行语句
返回值!!!
}

参数与函数的值

形参:定义函数时写的,被称为形式参数或虚拟参数,在未调用之前不占内存,在发生函数调用之后才有内存分配。,来接受实参的值。函数调用结束后内存单元被释放。
实参:可以为常量,变量或表达式,与形参的类型应相同或赋值兼容。
实参变量对形参变量的数据传递是“值传递”(等于复制了一份给形参,被函数处理后,原值不变,只是副本变了。)
函数
函数的返回值:通过函数调用使主调函数获得一个确定的函数值
1.使用return语句
2.返回值有类型,是用定义函数时设的类型决定的
3.若函数值类型与return中表达式的值不同,则由函数值类型决定,这有自动类型转换!

函数的调用

1.一般形式:函数名(参数列表)
2.调用方式
(1)函数语句
把函数调用单独作为一个语句,并不要求返回一个值,只是要求执行一个功能
printstar();
(2) 函数表达式
带回一个确定值参与表达式运算
c = 2*man(a,b);
(3)函数参数
函数调用作为一个函数的参数
m = max(a,sqrt(b));

(4) 对被调用函数的声明和函数原型
函数声明
函数原型

(5) 函数的嵌套调用(*)
在一个函数中使用另一个函数

(6)函数的递归调用(*算法!!!)
递归调用(recursive)
在调用一个函数的过程中又出现直接或间接地调用该函数本身就好像是自己调自己

用递归方法求n!

 #include<iostream>
using namespace std;
long factorial(int);


int main()
{
	int n;
	long y;
	cout << "Please enter an integer";
	cin >> n;
	y = factorial(n);
	cout << n << "!=" << y << endl;
	return 0;
}
long factorial(int n)
{
	long f = 0;
	if (f < 0)
	{
		cout << "n<0,data error!";
		f = -1;
	}
	else if (n == 0 || n == 1)
	{
		f = 1;
	}
	else f = factorial(n - 1) * n;
	return f;
}

内置函数

在编译时将所调用函数的代码直接嵌入到主调函数中,而不是将流程转出去。这种嵌入到主调函数中的函数称为内联函数(inline function),又称内嵌函数 (优点:加快函数运行)
设定语法:在函数左端加一个inline(这不是命令,而是建议,编译系统会决定是不是采用)

#include<iostream>
using namespace std;
inline int max(int,int,int);
int main()
{
int i = 10,j = 20,k = 30,m;
m - max(i,j k);
cout<<"max="<<m<<endl;
return 0;
}
inline int max(int a,int b,int c)
{
if(b>a) a = b;
if(b>a) a = c;
return a;
}

一般只把使用频率高而且不含复杂语句(switch,循环)的函数设为内联函数,因为这会增加main函数长度。

函数的重载

其实就是”一物多用“,同一个函数名,但参数顺序或个数或类型不同即可
函数的返回值类型不影响!
同名函数的功能最好相似!

函数模板(Function template)

实质:建立一个通用函数,其函数类型和形参类型都不具体指定,用一个虚拟的类型来代表
凡是函数体相同的函数都可以用一个模板代替,而不必定义多个函数,在模板中定义一次即可。调用时根据实参的类型来取代模板中的虚拟类型,从而实现不同的函数功能。
通用定义:
template // T为虚拟参数
通用函数定义


template
通用函数定义

适用于函数体相同,参数个数相同,但类型不同的情况。

局部变量和全局变量

局部变量(local variable)

在一个函数内部定义的变量叫局部变量,只在本函数范围内有效。

注:
1.主函数main中定义的变量也只在主函数中有用,也不能在整个文件和其他函数中有用
2.不同函数中可以使用同名变量,它们代表不同对象
3.在函数内的复合语句中设的变量只在复合语句中有效
4.形式参数也只是局部变量
5.在函数原型声明中出现的参数名,只在原型声明中的括号范围内有效,而非实际存在的变量。故而不能引用

全局变量(global variable)

在函数之外定义的变量是外部变量,称为全局变量

作用:增加了函数间数据联系的渠道。
但是,能不用就不用,这会降低函数的可移植性与可读性

变量的有效范围是变量的作用域()从空间角度分析变量,有四种:
1.文件作用域(file scope)—全局
2.函数作用域(function scope)–局部
3.块作用域(block scope)–局部
4.函数原型作用域(function prototype scope)–局部

变量的存储类别

动态存储方式与静态存储方式

存储期(storage duration 也叫生命期):变量在在内存中的存在周期(从时间角度来分析变量)
存储期可以分为静态存储期和动态存储期,这是由变量的静态or动态存储方式决定的
静态存储:程序运行中,分配固定的内存
动态存储:程序运行中,对变量动态地分配内存

存储空间:
1.程序区
2.静态存储区:存放全局变量
3.动态存储区:存放:(1)函数形参.(2)函数中定义的变量
(3)函数调用时的现场保护和返回地址等

存储类别:
自动的
静态的
寄存器的
外部的

自动变量

函数中的局部变量,如果不用static,就可以用auto,系统自动进行动态的内存分配(不写auto则默认为自动变量)

用static声明静态局部变量

用处:
1.使函数中的局部变量在函数调用结束后保存原值,不释放其存储空间

#include<iostream>
using namespace std;
int fac(int );
int main()
{
int i ;
for(i = 1;i <=5;i++)
cout<<i<<"!="<<fac(i)<<endl;
return 0;
}
int fac(int n)
{
static int f = 1;
f = f*n;
return f; 
}

2.初始化后,变量只被引用而不改变其值。

用register声明寄存器变量

直接放在CPU的寄存器中,不用去内存里取了,更快
加一个关键字register即可

用extern声明外部变量

一般的全局变量的作用域是从声明处一直到程序末尾。用extern来扩展全局变量的作用域
1.在一个文件内声明全局变量:
但是如果想在之前使用全局变量,则在引用之前加extern做外部变量声明,此声明可以从声明的地方开始合法的使用此变量

int main()
{
extern int a,b;//提前引用申明
...
}
int a = 15,b = 17;
...

2.在多文件中声明外部变量

file1.cpp                   file2.cpp
extern int a,b;            int a=3,b=4;
int main()
{cout<<a<<b;}

extern的使用应该慎重!

用static声明静态外部变量

使静态外部变量只在本文件被使用,这使同变量名在不同文件中互不干扰

file1.cpp                   file2.cpp
extern int a,b;           static int a=3,b=4; //如此则无法在file1中使用该变量
int main()                
{cout<<a<<b;}

关于变量的声明和定义

定义:建立存储空间,全称为定义性声明
声明:并不建立存储空间,全称为引用性声明,可用来扩大作用域。典型的是extern声明外部变量。
使用static,auto,regieter时,这些都只是关键字,不是类型名!

内部函数和外部函数

内部函数

顾名思义,内部函数只能在本文件内被调用。
函数首部的一般格式:
static 类型标识符 函数名 (参数表)
不同文件有同名函数时,这么干可以互不干扰。
通常规范:把只能由同一个文件使用的函数和外部变量放在同一个文件中,在前面加static使其局部化。

外部函数

(1)函数首部最左加了extern
(2)在需要调用此函数的文件中,用extern声明所用的函数是外部函数。

不过其实,这个extern是可以省略的,用函数原型一样可以扩展作用域!!!

头文件

在文件头部被包含的文件

头文件中有啥嘞?

  1. 对类的声明(class)

  2. 函数声明(比如著名的cmath库)

  3. 内置(inline)函数的定义:内置函数是要插入用户程序中的,故要与需要调用它的语句在同一文件内!

  4. 宏定义(#define 或 const 声明的常变量)

  5. 全局变量定义

  6. 外部变量声明

  7. 还可以根据需要包含其他头文件(头里套头,娃里套娃)

    题1在这里插入图片描述

 include<iostream>
#include<cmath>

using namespace std;
/*
double f(double x,double a,double b,double c,double d)
{
	return a*pow(x, 3)+b*pow(x,2)+c*pow(x,1)+d;
}
double f_(double x, double a, double b, double c)
{
	return 3 * a * pow(x, 2) + 2 * b * pow(x, 1) + c;
}
double solve(double x0, double a, double b, double c, double d)
{
	//double f(double x, double a, double b, double c, double d);
	double x = 0;
	double dx = f(x, a, b, c, d) / f_(x, a, b, c);
	//double x1 = x0; //- f(x0, a, b, c, d) / f_(x0, a, b, c);
	x = x0;
	double m = 0;
	double n = 0;
	while (dx > 1E-10)
	{
	    m = f(x, a, b, c, d);
		n = f_(x, a, b, c);
		dx = f(x, a, b, c, d) / f_(x, a, b, c);
		x = x - dx;

	}
	return x;
}
int main()
{
	double x0 = 1.0, a = 0, b = 0, c = 0, d = 0;
	double answer = 0;
	cin  >> a >> b >> c >> d;
	answer = solve(x0, a, b, c, d);
	cout << answer;
	return 0;
}*/
int main()
{
	double solut(double, double, double, double);
	double a, b, c, d;
	cout << "input a,b,c,d:" << endl;
	cin >> a>> b>> c>> d;
	cout << solut(a, b, c, d) << endl;
	return 0;
}
double solut(double a, double b, double c, double d)
{
	double x = 1, x0, f, f1;
	do
	{
		x0 = x;
		f = ((a * x0 + b) * x0 + c) * x0 + d;
		f1 = (3 * a * x0 + b * 2) * x0 + c;
		x = x0 - f / f1;
	} while (fabs(x - x0) >= 1e-5);
	return x;
}
//我好好反思:之前尽管思路一样,但各种函数调来调去,有些混乱。对于这种较简单的题,直接放进循环即可

题2
在这里插入图片描述

#include<iostream>

using namespace std;

void move(char x, char y)
{
   cout << x << "-->" << y << endl;
}

void Hanoi(int n,char one,char two,char three)
{
// void	move(char x,char y);//如果把上面的move函数放到下面,可以用这一句话来拓展作用域
   if (n == 1)
   {
   	move(one, three);//这其实是最终我想要的,只有一个盘,直接放到C柱上
   }
   else
   {
   	Hanoi(n - 1, one, three, two);//这一句和下一句都是递归,作用是调用函数,进一步往下分,这里是把n-1个借助three柱放到two柱上
   	move(one, three);             //这一句是把第n个放到three柱上
   	Hanoi(n - 1, two, one, three);//这一句是把n-1个借助one柱放到three柱上
   	//然后上面的两个分别调用自己,直到每一个都变成了最简单的情况
   }
}

int main()
{
   void Hanoi(int n, char one, char two, char three);
   int m;
   cout << "输入的盘子的总数:";
   cin >> m;
   cout << "移动" << m << "个盘子的步骤" << endl;
   Hanoi(m, 'A', 'B', 'C');
   return 0;
}

题3:用递归法将一个整数n转换成字符串。例:输入483,输出字符串“483”。n的位数不确定,可以是任意位数的整数。

#include<iostream>

using namespace std;

int main()
{ 
   void trans(int n);
   int number = 0;
   cout << "input an integer:";
   cin >> number;
   cout << "output:";
   if (number < 0)
   {
   	cout << "-";
   	number = -number;
   }
   trans(number);
   cout << endl;
   return 0;
}
void trans(int n)
{ 
   int i = 0;
   char c;
   if ((i= n / 10) != 0)
   {
   	trans(i);
   }
   c = n % 10 + '0';
   cout << "" << c;
}

题4
用递归方法求
在这里插入图片描述
n的值由主函数输入

#include<iostream>

using namespace std;

int fac(int n)
{
	int f = 1;
	
	
	if (n == 1)//如果递归边界不设好,你栈就没了hiahiahia
	{
		 f = 1;
	}
	else
	{
		f = n*n+ fac(n - 1);
	}
	return f;

}
int main()
{
	int n = 0;
	cin >> n;
	int A = 0;
	A = fac(n);
	cout << "Answer is :" << A << endl;
}

下面是错误示例

int fac(int n)
{
	int f = 1;
	
	f = n * n + fac(n - 1);
	//如果递归边界不设好,你栈就没了hiahiahia,这里下面的这个边界就是假的
	if (n == 1)        
	{
		 f = 1;
	}
	
	return f;

}

题5(较容易,关键是熟悉宏定义)在这里插入图片描述

#include<iostream>
#include<cmath>

#define S(a,b,c) (a+b+c)/2
#define AREA(a,b,c) sqrt(S(a,b,c)*(S(a,b,c)-a)*(S(a,b,c)-b)*(S(a,b,c)-c))
using namespace std;

int main()
{
	float a, b, c;
	cout << "input a,b,c:";
	cin >> a >> b >> c;
	if (a + b > c && a + c > b && b + c > a)
	{
		cout << "area=" << AREA(a, b, c) << endl;
	}
	else
	{
		cout << "It's not a triangle";
	}
}

题6在这里插入图片描述

include<iostream>
#include<cmath>
using namespace std;
//用cmath里的函数,较为简洁
double e(double x)
{
	return exp(x);
}
//下面的是一个利用泰勒展开求e^x的函数
double E(double x)
{
	double e = 1;
	int i = 1;
	double j = x;
	do
	{
		
		e = e + j;
		i = i + 1;
		j = (j * x) / (i);
		
	
	} while (j > 0.0000001);
	return e;

}
int main()
{
	double x, sinh;
	cout << "Enter x:"<<endl;
	cin >> x;
	sinh = (e(x) + e(-x)) / 2;
	cout << "sinh(" << x << ")=" << sinh << endl;
	double a = E(x);
	cout << a;
	return 0;
}

题7
在这里插入图片描述

//一个不小于6的偶数可以表示为两个素数之和

#include<iostream>
#include<cmath>

using namespace std;
//justice whether the number is a prime number
int prime(int n)
{
	int i;
	int k = sqrt(n);
	for (i = 2; i <= k; i++)
	{
		if (n % i == 0)
		{
			return -1;
		}		 
	}
}
void godbaha(int n)
{
	int prime(int);
	int a, b;
	for (a = 3; a <= n / 2; a = a + 2)
	{
		if (prime(a)!=-1)
		{
			b = n - a;
			if (prime(b)!=-1)
			{
				cout << n << "=" << a << "+" << b << endl;
			}
		}
	}
}
int main()
{
	int n = 0;
	cin >> n;
    godbaha(n);
	return 0;
}

本文参考了《C++ Primer Plus》和谭浩强老师的C++程序设计

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值