
,# 函数基础
函数定义
函数定义包含以下几个部分:返回类型、函数名字、形参列表和函数体。
int fact(int val)
{
}
列举一个简单的空函数,fact是函数名,fact前面的int是返回类型,val是形参,val前的int是接受的实参类型,花括号中的是函数体。
形参列表可以是空的,但是不能被省略,如果是省略形参可以用void或者直接为空
int fact(void)
{
}
或者
int fact()
{
}
多个形参可以使用逗号隔开,每个形参前都必须标有类型,任意两个形参不能同名。
实参是形参的初始值,与形参一一对应,无论是类型还是数量都必须对应。
6.3 用户输入一个数,计算这个数的阶乘
#include
#include
using namespace std;
int fact(int a);
int main()
{
int i;
cin>>i;
int j=fact(i);
cout<<"j"<<"的阶乘为"<<j<<endl;
}
int fact(int a)
{
int ret=1;
while(a>0)
{
ret*=a--;
}
return ret;
}
局部对象
每一个对象都有生命周期,定义在函数体外的变量,存在于整个程序执行的过程中,在函数开始时被创建,函数结束时消失。每个变量的生命周期的长短取决于它们的定义方式。对于普通局部变量对象来说,当函数路径经过定义语句时创建,当到达定义语句所在块末尾时销毁。某些时候需要局部变量的生命周期贯穿始末的时候需要使用static将普通的局部变量,变成局部静态变量。
6.6、6.7编写一个函数,使用到形参、局部变量和局部静态变量,函数的内容是第一次返回0,之后每一次返回变量加一
#include
#include
using namespace std;
int add()
{
static int a=1;
int b=1;
a=a+1;
b=b+1;
cout<<"a"<<a<<" ";
cout<<"b"<<b<<" ";
return 0;
}
main()
{
int b,i;
for(i=0;i<10;i++)
{
cout<<"这是第"<<i<<"次调用的结果"<<" ";
add();
cout<<endl;
}
}
结果如图
函数声明与分离式编译
函数只能定义一次,但是可以声明很多次。函数的声明和定义几乎一样,只是函数声明没有实体,用一个封号代替就可以了,也可以不写形参的名字。一般把函数声明放在头文件中。
6.8、6.9 编写一个项目 fact.cc,factmain.cc和fact.h
fact.h
#ifndef CHAPTER_H_INCLUDE
#define CHAPTER_H_INCLUDE
int fact(int );
#endif
fact.cpp
#include "chapter.h"
using namespace std;
int fact(int a)
{
int ret=1;
while(a>0)
{
ret*=a--;
}
return ret;
}
factmain.cpp
#include
#include "Chapter.h"
using namespace std;
int main()
{
int i;
cin>>i;
int j=fact(i);
cout<<i<<"的阶乘为"<<j<<endl;
}
参数传递
参数的传递有两种,引用或者拷贝。
引用传递:形参是引用类型,将形参绑定到对应的实参上,可以直接改变绑定实参的值,当对象不支持拷贝 的时候可以直接引用。如下
#include
using namespace std;
void reset(int &p)
{
p = 0;
}
int main()
{
int n=42;
reset(n);
return 0;
}
值传递:将实参的值拷贝给形参,对形参的 *** 作不会影响到实参。
指针形参:指针形参可以间接改变所指对象的值。如下面这段程序,实参n的值从42变为了0。
void reset(int *p)
{
*p = 0;
}
int main()
{
int n=42;
reset(&n);
return 0;
}
6.15 输入一个字符串输出o第一次出现的索引和出现的次数
#include
using namespace std;
int find_char(const string &s,char c,int &occurs)
{
auto ret=s.size();
occurs=0;
for(int i=0;i!=s.size();i++)
{
if(s[i]==c){
if(ret==s.size())
ret=i;
occurs++;
}
}
return ret;
}
int main()
{
int n,index;
char c='o';
string s;
cout<<"请输入小写字符串"<<endl;
cin>>s;
index=find_char(s,c,n);
cout<<index<<" "<<n;
return 0;
}
const的形参与实参
形参的顶层const会被忽略掉,对于形参来说本身就无法改变实参,只能读取实参。
void f(int i)
void f(const int i)
这两个编译器认为是一样的。
如果子函数不会改变实参的值,尽量用常量引用,一方面可以给其他使用函数的人提示子函数不会改变常量的值,另一方面是常量引用不会造成一些错误,比如常量引用既可以引用常量,也可以引用非常量,而普通的引用只能引用非常量。
6.17 输入一个字符串判断是否有大写字母,如果有询问用户是否需要将字符串中的大写字母改成小写
#include
using namespace std;
int panduan(const string &a);
string gaixie(string &a);
int main()
{
int adjuest,a;
string change;
string s;
cin>>s;
adjuest=panduan(s);
if(adjuest)
{
cout<<"有大写字母存在,是否把小写字母改写成大写?(yes=1)"<<endl;
cin>>a;
if(a=1)
{
change= gaixie(s);
cout<<change;
}
}
else
cout<<"没有大写字母存在"<<endl;
}
int panduan(const string &a)
{
int ret=0;
for(const char &c:a)
{
ret=isupper(c);
if(ret!=0)
return ret;
}
return ret;
}
string gaixie(string &a)
{
for(char &c:a)
{
c=tolower(c);
}
return a;
}
数组形参
数组有两个特殊的性质:1.数组不可以被拷贝;2.使用数组时通常会将其转化成指针。因为这两个性质无法使用值传递的方式将数组传入形参,并且传递时传递的是指向数组首地址的指针。
void f(const int*)
void f(const int a[])
void f(const int a[n])
这三种方式形参是等价的,数组的大小对调用没有影响。
数组的引用形参
f(int (&a)[10])
括号不可以少!
如何判断数组的长度
1.使用标记指定数组的长度,比如在定义一个数组时,以 /n 结尾,在子函数中检测到 /n 就认为数组结束了。
2.使用标准库,使用数组的首地址指针和尾地址指针进行传递。
int j[2]
f(begin(j),end(j))
3.显式的传递一个形参大小
void f(const int j[],const int size )
传递多维数组
多维数组就是指向数组的数组,含义就是指向首元素的指针本身就是一个数组
void ((*f)[10],int row Size)
f 指向数组的首元素,这个元素是由10个整数构成的数组。
上面问题的6.17 使用数组进行查找和存储
#include
#include
using namespace std;
int find_char(const string &s,char c,int* a)
{
a[0]=s.size();
for(int i=0;i!=s.size();i++)
{
if(s[i]==c){
if(a[0]==s.size())
a[0]=i;
a[1]++;
}
}
}
int main()
{
int n,save[2]={0,0};//第一个元素存索引 第二个元素存个数
char c='o';
string s;
cout<<"请输入小写字符串"<<endl;
cin>>s;
find_char(s,c,save);
cout<<save[0]<<" "<<save[1];
return 0;
}
因为数组传入的是指针,因此不需要特别的去返回数组,指针可以直接间接改变数组的值。
实参不确定的情况
无法确定实参的数量但是类型为同一类型时,可以传递一个名为initializar_list的标准库类型,如果实参的类型也无法确定,可以编写可变参数模板。
initializer_list是一种标准库类型,用于表示某种特定类型的值的数组,用法和vector类似,但是里面的值都是常量值,无法改变其对象。
void f(initializer_list<string> il)
计算未知个数元素的和
#include
#include
using namespace std;
int add(initializer_list<int> li)
{
int sum=0;
for(int val:li)
{
sum+=val;
}
return sum;
}
省略形参
void f(parm-list,……)
void f(……)
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)