C++学习笔记2


1 函数

函数是一组执行某个任务的语句。每个 C++ 程序都至少有一个函数,即主函数 main()。其中:

  • 函数声明告诉编译器函数的名称、返回类型和参数。
  • 函数定义提供了函数的实际主体。

1.1 定义函数

函数还可以称为方法或程序等。函数定义的一般形式为:

return_type function_name(parameter list){
	body of the function
}

函数由一个函数头和一个函数体组成。下面列出一个函数的所有组成部分:

  • 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
  • 函数名称:这是函数的实际名称。
  • 参数:当函数被调用时,需要向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,即函数可以不包含任何参数。
  • 函数主体:函数主体包含一组定义函数执行任务的语句。

如下是一个 max() 函数的示例代码,该函数有两个参数 num1 和 num2,会返回这两个数中较大的那个数:

int max{ int num1,int num2 }{
	int result;
	if (num1 > num2)
		result = num1;
	else
		result = num2;
	return result;
}

1.2 函数声明

函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。函数声明包括以下几个部分:

return_type function_name(parameter list);

针对上面定义的函数 max(),以下是函数声明:

int max{ int num1,int num2 };

在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:

int max{ int,int};

在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的,而且应该在调用函数的文件顶部声明函数。

1.3 调用函数

当程序调用函数时,程序控制权会转移给被调用的函数。被调用的函数执行已定义的任务,当函数的返回语句被执行时,或到达函数的结束括号时,会把程序控制权交还给主程序。

示例代码如下:

#include<iostream>
using namespace std;

int max(int, int); //函数声明

int main() {
	int a = 100, b = 200, return_value;
	return_value = max(a, b);
	cout << "最大值为" << return_value << endl;
	return 0;
}

int max(int num1, int num2) {
	int result;
	if (num1 > num2)
		result = num1;
	else
		result = num2;
	return result;
}

输出如下:

最大值为200

如果函数要使用参数,则必须声明接受参数值的变量,这些变量称为函数的形式参数——形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。

1.4 函数参数

当调用函数时,有三种向函数传递参数的方式:

1、传值调用。向函数传递参数的传值调用方法,把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数不会影响实际参数。默认情况下,C++ 使用传值调用方法来传递参数。示例代码如下:

#include<iostream>
using namespace std;

void swap(int x, int y);

int main() {
	int a = 100, b = 200;
	cout << "交换前a为:" << a << endl;
	cout << "交换前b为:" << b << endl;

	swap(a, b);

	cout << "交换换a为:" << a << endl;
	cout << "交换换b为:" << b << endl;

	return 0;
}

void swap(int x, int y) {
	int temp;
	temp = x;
	x = y;
	y = temp;
	return;
}

输出如下:

交换前a为:100
交换前b为:200
交换换a为:100
交换换b为:200

上面的实例表明,虽然在函数内改变了 a 和 b 的值,但是实际上 a 和 b 的值没有发生变化。

2、指针调用。向函数传递参数的指针调用方法,把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。相应地,在函数中需要声明函数参数为指针类型。示例代码如下,该函数用于交换参数所指向的两个整数变量的值:

#include<iostream>
using namespace std;

void swap(int *x, int *y);

int main() {
	int a = 100, b = 200;
	cout << "交换前a为:" << a << endl;
	cout << "交换前b为:" << b << endl;

	swap(&a, &b);

	cout << "交换换a为:" << a << endl;
	cout << "交换换b为:" << b << endl;

	return 0;
}

void swap(int *x, int *y) {
	int temp;
	temp = *x;
	*x = *y;
	*y = temp;
	return;
}

输出如下:

交换前a为:100
交换前b为:200
交换换a为:200
交换换b为:100

3、引用调用。向函数传递参数的引用调用方法,把引用的地址复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。相应地,在函数中需要声明函数参数为引用类型。示例代码如下:

#include<iostream>
using namespace std;

void swap(int &x, int &y);

int main() {
	int a = 100, b = 200;
	cout << "交换前a为:" << a << endl;
	cout << "交换前b为:" << b << endl;

	swap(a, b);

	cout << "交换换a为:" << a << endl;
	cout << "交换换b为:" << b << endl;

	return 0;
}

void swap(int &x, int &y) {
	int temp;
	temp = x;
	x = y;
	y = temp;
	return;
}

输出如下:

交换前a为:100
交换前b为:200
交换换a为:200
交换换b为:100

默认情况下,C++ 使用传值调用来传递参数。一般来说,这意味着函数内的代码不能改变用于调用函数的参数。

1.5 参数的默认值

在定义一个函数后可以为参数列表中后边的每一个参数指定默认值。调用函数时,如果未传递参数的值,则会使用默认值,如果指定了值,则会忽略默认值,使用传递的值。示例代码如下:

#include<iostream>
using namespace std;

int sum(int a, int b = 20) {
	int result;
	result = a + b;
	return(result);
}

int main() {
	int a = 100, b = 200, reuslt;
	
	int result;

	result = sum(a, b);
	cout << "和为:" << result << endl;

	result = sum(a);
	cout << "和为:" << result << endl;

	return 0;
}

输出如下:

和为:300
和为:120

2 数字

C++数字类型包括 int、short、long、float 和 double 等等。

2.1 定义数字

下面是一个 C++ 中定义各种类型数字的综合实例:

#include<iostream>
using namespace std;

int main() {
	short s;
	int i;
	long l;
	float f;
	double d;

	s = 10;
	i = 1000;
	l = 100000;
	f = 230.48;
	d = 2342.234;

	cout << "short s:" << s << endl;
	cout << "int i:" << i << endl;
	cout << "long l:" << l << endl;
	cout << "float f:" << f << endl;
	cout << "double d:" << d << endl;

	return 0;
}

输出如下:

short s:10
int i:1000
long l:100000
float f:230.48
double d:2342.23

2.2 数学运算

C++ 内置了丰富的数学函数,可对各种数字进行运算。下面列出了 C++ 中一些有用的内置的数学函数(代码中需要引用头文件 <cmath>

1、double cos(double)。该函数返回弧度角(double 型)的余弦。

2、double sin(double)。该函数返回弧度角(double 型)的正弦。

3、double tan(double)。该函数返回弧度角(double 型)的正切。

4、double log(double)。该函数返回参数的自然对数。

5、double pow(double, double)。假设第一个参数为 x,第二个参数为 y,则该函数返回 x 的 y 次方。

6、double hypot(double, double)。该函数返回两个参数的平方总和的平方根,也就是说,参数为一个直角三角形的两个直角边,函数会返回斜边的长度。

7、double sqrt(double)。该函数返回参数的平方根。

8、int abs(int)。该函数返回整数的绝对值。

9、double fabs(double)。该函数返回任意一个浮点数的绝对值。

10、double floor(double)。该函数返回一个小于或等于传入参数的最大整数,即向下取整。

示例代码如下:

#include<iostream>
#include<cmath>
using namespace std;

int main() {
	short s;
	int i;
	long l;
	float f;
	double d;

	s = 10;
	i = -1000;
	l = 100000;
	f = 230.47;
	d = 200.374;

	cout << "sin(d):" << sin(d) << endl;
	cout << "abs(i):" << abs(i) << endl;
	cout << "floor(d):" << floor(d) << endl;
	cout << "sqrt(f):" << sqrt(f) << endl;
	cout << "pow(d,2):" << pow(d, 2) << endl;

	return 0;
}

输出如下:

sin(d)-0.634939
abs(i)1000
floor(d)200
sqrt(f)15.1812
pow(d,2)40149.7

2.3 随机数

关于随机数生成器,有两个相关的函数。一个是 rand(),该函数只返回一个伪随机数。另一个是srand() 函数,在生成随机数之前必须先调用 srand() 函数。

下面是一个关于生成随机数的简单实例。实例中使用了 time() 函数来获取系统时间的秒数,通过调用 rand() 函数来生成随机数:

#include<iostream>
#include<ctime>
#include<cstdlib>

using namespace std;

int main() {
	int i, j;

	srand((unsigned)time(NULL)); //设置种子

	//生成10个随机数
	for (i = 0; i < 10; i++) {
		j = rand(); //生成随机数
		cout << "随机数:" << j << endl;
	}

	return 0;
}

输出如下:

随机数:6480
随机数:15454
随机数:4897
随机数:12482
随机数:3346
随机数:18364
随机数:7009
随机数:32314
随机数:16963
随机数:24216

3 数组

数组是用于存储一个固定大小的相同类型元素的顺序集合。使用前需要声明一个数组变量,比如 numbers,然后使用 numbers[0]、numbers[1]、…、numbers[99] 来代表一个个单独的变量。数组中的特定元素可以通过索引访问。所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。

3.1 声明数组

声明一个数组需要指定元素的类型和元素的数量,如下所示:

type arrayName[arraySize];

上面是一维数组的形式,其中arraySize 必须是一个大于零的整数常量,type 可以是任意有效的 C++ 数据类型。示例代码如下:

double balance[10];

现在 balance 是一个可用的数组,可以容纳 10 个类型为 double 的数字。

3.2 初始化数组

可以逐个初始化数组,也可以使用一个初始化语句,如下所示:

double balance[5] = { 1000.0,2.0,3.4,7.0,50.0 };

大括号 { } 之间的值的数目不能大于在数组声明时在方括号 [ ] 中指定的元素数目。若省略掉了数组的大小,则数组大小为初始化时元素的个数。因此:

double balance[] = { 1000.0,2.0,3.4,7.0,50.0 };

将创建一个数组,它与前一个实例中所创建的数组是完全相同的。下面是一个为数组中某个元素赋值的实例:

balance[4]=50.0

上述的语句把数组中第五个元素的值赋为 50.0。所有的数组都是以 0 作为它们第一个元素的索引,也被称为基索引,数组的最后一个索引是数组的总大小减去 1。以下是上面所讨论的数组的的图形表示:
在这里插入图片描述

3.3 访问数组元素

数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。例如:

double salary = balance[9];

上面的语句将把数组中第 10 个元素的值赋给 salary 变量。

完整的一个示例C++代码如下:

#include<iostream>
using namespace std;

int main() {
	int i,n[10];

	for (i = 0; i < 10; i++) {
		n[i] = i + 10;
	}
	
	for (i = 0; i < 10; i++) {
		cout << "索引" << i << "对应的值为" << n[i] << endl;
	}
	return 0;
}

输出如下:

索引0对应的值为10
索引1对应的值为11
索引2对应的值为12
索引3对应的值为13
索引4对应的值为14
索引5对应的值为15
索引6对应的值为16
索引7对应的值为17
索引8对应的值为18
索引9对应的值为19

3.4 数组详解

3.4.1 多维数组

多维数组声明的一般形式如下:

type name[size1][size2]...[sizeN];

示例代码如下:

int threedim[3][4][5];

多维数组最简单的形式是二维数组。声明一个二维数组的形式如下:

type arrayName[x][y];

一个二维数组可以被认为是一个带有 x 行和 y 列的表格。下面是一个二维数组,包含 3 行和 4 列:
在这里插入图片描述
因此,数组中的每个元素是使用形式为 a[ i , j ] 的元素名称来标识的,其中 a 是数组名称,i 和 j 是唯一标识 a 中每个元素的下标。

多维数组可以通过在括号内为每行指定值来进行初始化。下面是一个带有 3 行 4 列的数组。

int a[3][4] = {
	{0,1,2,3}, //索引号为0的行
	{4,5,6,7}, //索引号为1的行
	{8,9,10,11} //索引号为2的行
};

内部嵌套的括号是可选的,下面的初始化与上面是等同的:

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

二维数组中的元素是通过使用下标(即数组的行索引和列索引)来访问的。例如:

int value=a[2][3];

上面的语句将获取数组中第 3 行第 4 个元素。

完整的一个示例C++代码如下:

#include<iostream>
using namespace std;

int main() {
	int a[5][2] = { {0,0},{1,2},{2,4},{3,6},{4,8} };

	//输出数组中每个元素的值
	for (int i = 0; i < 5; i++)
		for (int j = 0; j < 2; j++) {
			cout << "a[" << i << "][" << j << "];" << a[i][j] << endl;
		}
	return 0;
}

输出如下:

a[0][0];0
a[0][1];0
a[1][0];1
a[1][1];2
a[2][0];2
a[2][1];4
a[3][0];3
a[3][1];6
a[4][0];4
a[4][1];8

3.4.2 指向数组的指针

数组名是指向数组中第一个元素的常量指针。因此,在下面的声明中:

double runoobAarray[50];

runoobAarray 是一个指向 &runoobAarray[0] 的指针,即数组 runoobAarray 的第一个元素的地址。因此,下面的程序片段把 p 赋值为 runoobAarray 的第一个元素的地址:

double* p;
double runoobAarray[10];

p = runoobAarray;

而且*(runoobAarray + 4) 是一种访问 runoobAarray[4] 数据的合法方式。一旦把第一个元素的地址存储在 p 中,就可以使用 *p、*(p+1)、*(p+2)等来访问数组元素。

3.4.3 传递数组给函数

可以通过指定不带索引的数组名来传递一个指向数组的指针。当给一个函数传数组时,数组类型自动转换为指针类型,因而传的实际是地址。

如果想要在函数中传递一个一维数组作为参数,必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针。

1、形式参数是一个指针:

void myFunction(int* param) {

}

2、形式参数是一个已定义大小的数组:

void myFunction(int param[10]) {

}

3、形式参数是一个未定义大小的数组:

void myFunction(int param[]) {

}

示例C++代码如下:

#include<iostream>
using namespace std;

double getAverage(int arr[], int size) {
	int i, sum = 0;
	double avg;

	for (i = 0; i < size; ++i) {
		sum += arr[i];
	}

	avg = double(sum) / size;
	return avg;
}

int main() {
	int balance[5] = { 1000,2,3,17,50 };
	double avg;

	avg = getAverage(balance, 5); //传递一个指向数组的指针作为参数

	cout << "平均值为:" << avg << endl;
	return 0;
}

输出如下:

平均值为:214.4

3.4.4 从函数返回数组

C++ 不允许返回一个完整的数组作为函数的参数,但可以通过指定不带索引的数组名来返回一个指向数组的指针。若想要从函数返回一个一维数组,必须首先声明一个返回指针的函数,如下:

int* myFunction(){

}

C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。示例代码如下,函数会生成 10 个随机数,并使用数组来返回它们:

#include<iostream>
#include<cstdlib>
#include<ctime>

using namespace std;

int* getRandom() { //函数会生成并返回随机数
	static int r[10];

	srand((unsigned)time(NULL)); //设置种子

	for (int i = 0; i < 10; i++) {
		r[i] = rand();
		cout << r[i] << endl;
	}
	return r;
}

int main() {
	int* p;

	p = getRandom();
	for (int i = 0; i < 10; i++) {
		cout << "*(p+" << i << ")L" << *(p + i) << endl;
	}
	return 0;
}

输出如下:

3304
8270
24235
19857
2011
30013
1221
2513
28595
28458
*(p+0)L3304
*(p+1)L8270
*(p+2)L24235
*(p+3)L19857
*(p+4)L2011
*(p+5)L30013
*(p+6)L1221
*(p+7)L2513
*(p+8)L28595
*(p+9)L28458

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值