#include<iostream>
#include<string>
#include<array>
using namespace std;
typedef const double* (*p_fun)(const double*, int);//利用typedef声明对函数指针创建别名————简化代码————注意该函数返回一个double指针
//其中*p_fun为其类型别名,——可以直接用其取得函数地址————p_fun p1=f1
struct travel_time//travel_time是简单类型名
{
int hours;
int mins;
};
struct rect
{
double x;
double y;
};
//要使用c++函数,要先完成三步:函数定义;提供原型;调用函数——————编译好的函数被包含在标准库头文件中
void cheers(int n);//注意原型是以分号结束!!!并不像函数创建一样
int bigger(int a, int b);//原型确保了正确处理函数返回值、参数数目是否正确、类型是否正确
int sum(int, int);//可省略函数声明时的变量名
int sum_arr(const int arr[], int n);//arr实际上并不是数组,而是一个指针
int sum_vrr(const int* begin, const int* end);
int sum_arr1(int arr1[][4]);
unsigned int c_in_str(const char* str, char ch);
char* buildstr(char c, int n);
travel_time sum_day(travel_time day1, travel_time day2);
void show_rect( const rect* pda);
void display(const string sa[], int n);//string类和函数相结合
void fill(array<string, 3>* acc);//使用类指针进行函数的值传递
void countdown(int n);
double pam(int);//函数原型中可以省略标识符
//上面几行进行了函数原型声明————原型描述了函数到编译器的接口,将函数的返回类型和参数告诉了编译器
int main()
{
using namespace std;
int n;
cin >> n;
cheers(n);//调用cheers函数
int a, b;
cin >> a;
cin >> b;//这里还要再说一下cin.get()函数读取所有的输入字符,包括空格和换行符
cout << bigger(a, b);
cout << sum(a, b);//使用函数中的变量是一对一进行传递的,这里是实参
//函数和数组
int arr[10];
for (int i = 0; i < 10; i++)
cin >> arr[i];
cout << sum_arr(arr, 10);//c++和c一样,将数组名视为指针当且仅当用于函数头和函数原型时————这里其实是传递数组第一个元素的地址
//当且仅当用于函数头和函数原型时,int* arr和int arr[]才相同
//使用数组区间的函数(range)————通过两个指针来完成——初始指针——末尾指针
cout << sum_vrr(arr + 2, arr + 8);
//由于数组名是地址,可对其进行加减运算,移动内存单位————arr+size-1为最后一个元素——arr+size为最后一个元素后面一个位置
int age = 39;
const int* pt = &age;
//pt指向const int,因此不能使用pt来修改这个值,但可以使用age来修改,但可以修改pt的值
//c++禁止将const的地址赋值给非const指针!!!--非要这样做就要用强制转化
int arr1[3][3] = { {1,2,1},{2,3,2},{3,4,5} };//对于二维数组,数组名为其地址(指针)
cout << sum_arr1(arr1, 4);//arr1是由4个指向int的指针组成的数组!!!
//字符串作为参数时意味着传递的是地址————是字符串的第一个字符的地址————注意字符串是以空值字符结尾(NULL符)
char mmm[15] = "msdfmsdfma";//这里的mmm只是数组,并不是字符串
const char* wail = "sdjfgrse";
cout << c_in_str(mmm, 'm');//参数不一定是数组名
cout << c_in_str(wail, 's');
char ch;
int num;
cin >> ch;
cin >> num;
char* ps = buildstr(ch, num);//该函数返回一个字符指针
cout << ps << endl;
travel_time day1 = { 5,45 };
travel_time day2 = { 4,55 };//结构体相较于数组更好和函数进行操作
travel_time sum_day1 = sum_day(day1, day2);//可以像变量一样赋值
cout << sum_day1.hours << sum_day1.mins << endl;
rect rplace;
while (cin >> rplace.x >> rplace.y)//这里还是要提一下cin的相关知识
{//cin是istream类的一个对象。抽取运算符>>被设计使得cin>>rplace.x也是一个istream对象,其中类运算符是使用函数实现的
cout << rplace.x << " " << rplace.y << endl;
}
const string s = "sdfasdfdfsa";//可以将一个对象赋值给另一个对象,可将对象作为一个完整的实体进行传递
display(s, s.size());//注意类方法要加括号
//这里要说的实是将对象按值将对象传递给函数,这种请况下只是一个副本,只有使用指针时才可修改原始对象
array<string, 3>acc = { "sdfas","sdfsfwee","ijlkjon" };//模板array不仅能存储基本数据结构,还可存储类对象————对象包含对象
for (int i = 0; i < 3; i++)
cout << acc[i];
//函数可以自己调用自己——递归————c++不允许mian()调用自己
//代码中要包含终止调用链的内容————通常放在if语句中
double(*pf)(int);//声明了一个函数指针,指向一个函数————函数名即为函数的地址
//函数指针必须指定返回类型以及参数列表————注意要加括号————不加就是返回double类型的指针!
//其中(*pf)就相当于原来函数,可以直接调用
pf = pam;//pf指向函数pam
cout << (*pf)(5);
cout << pf(5);
//以上两种输出其实是相同的————因为存在着历史与逻辑和看法不同
}
void cheers(int n)//———没有返回值
{//这里int n是传递的一个形参,可以使用
using namespace std;
for (int i = 0; i < n; i++)
{
cout << "cheers";//该函数没有返回值,只是进行显示
cout << endl;
}
}
int bigger(int a, int b)//这里有两个形参————函数返回int型
{
using namespace std;
if (a > b)
return a;//有返回值的函数必须使用返回语句return
else
return b;
}
int sum(int a, int b)//这里传过来的是形参————但对应的变量值是相同的
{
using namespace std;
int c = 520;//在函数内声明的变量称为(局部变量)!!!
cout << c;
return a + b;
}
int sum_arr(const int arr[], int n)//为防止函数无意间修改数组的内容使用const修饰符
{
int total = 0;
for (int i = 0; i < n; i++)
total = total + arr[i];//这里可以使用复合赋值运算符total+=arr[i]
return total;
}
int sum_vrr(const int* begin, const int* end)
{
const int* pt;
int total = 0;
for (pt = begin; pt != end; pt++)//这里巧妙的利用for循环和指针加1的特性达到区间遍历数组
total += *pt;
return total;
}
int sum_arr1(int arr1[][3], int size)//这里的size传递的是数组的行数,列数是3
{
int total = 0;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < 4; j++)
total += arr1[i][j];//这里也可以使用双重解引用:total+=*(*(arr+i)+j)
}//注意解引用运算符的有衔接比算术高
return total;
}
unsigned int c_in_str(const char* str, char ch)
{
unsigned int count = 0;
while (*str)
{
if (*str == ch)
count++;
str++;
}
return count;
}
char* buildstr(char c, int n)
{
char* pstr = new char[n + 1];//使用new创建一个动态字符数组
pstr[n] = '\0';//注意字符串以空字符结尾
while (n--)
{
pstr[n] = c;
}
return pstr;
}
travel_time sum_day(travel_time day1, travel_time day2)//返回结构
{
travel_time sum_day;
sum_day.hours = day1.hours + day2.hours+(day1.mins+day2.mins)/60;
sum_day.mins = (day1.mins + day2.mins) % 60;//利用句号来访问操作
return sum_day;
}
void show_rect(const rect* pda)//这里传递的形参是一结构指针,并且使用了const,不允许修改原结构
{
using namespace std;
cout << pda->x;
cout << pda->y;
}
void display(const string sa, int n)
{
for (int i = 0; i < n; i++)
cout << i + 1 << ": " << sa[i] << endl;
}
void fill(array<string, 3>* acc)
{
using namespace std;
for (int i; i < 3; i++)
{
cin >> (*acc)[i];//注意要先解引用为原本的array对象本体,再用下标运算修改各个string类
}
}
void countdown(int n)
{
using namespace std;//利用栈的思想可以很好的梳理递归
cout << n << endl;//多条件递归时,更能体现————二叉数的遍历!!!书197页
if (n > 0)//递归条件
countdown(n - 1);
cout << n << endl;//执行晚递归后程序将沿着进入的路径返回————像!栈!一样:先进后出
}
double pam(int a)
{
return a * 0.02 * 0.03 * 0.24;
}
c++学习6、函数
于 2024-08-31 00:08:51 首次发布