C++ 教程(五)
C++ 教程(五)
上一节的练习题
上一节中,第 1 题相对简单,那么第 2 题要怎么做呢?
题目如下:
对于给定的一个大写字母,输出如下图的金字塔。
先分析一下这个金字塔由什么构成。
- 行首的空格。
- 正向输出字母。
- 反向输出字母。
- 换行。
我们首先使用一个大的循环,来输出换行符。可以看到,行数等于字母在字母表中的位置pos
。所以输出的换行符个数为 line = pos - 1
。
然后观察输出空格的个数与行数之间的关系。
空格的个数为 line - i + 1
,其中 i
为行数。
接着我们正向输出字母,在反向输出字母,就解决了。
所以我们要用到 4 个循环,其中 3 个循环嵌套在 1 个循环中。
代码如下:
1 |
|
数组
数组是一种用于存储有限元素的集合。
在 C++
中,一种数组只能存储同一类型的数据。数组的声明方式如下:
1 | int arr[100]; |
其中,arr
是数组名,中括号 []
中的常量指定该数组包含多少元素。前面的 int
指明了该数组的类型为 int
。
数组除了声明之外,数组的下标也是至关重要的。
元素存储在数组中时,每个元素都对应一个下标,我们可以通过下标访问某个元素。
数组的下标从 0
开始,对于 int arr[100]
这个数组来说,它的下标是 0~99
,即不存在 100
下标。
所以,数组的最后一个元素的下标是定义的元素个数减 1 。
对于数组的初始化,我们可以使用赋值的方式。
1 |
|
数组使用 a[pos]
(pos
为数组下标) 的形式表达数组中的第 pos
个元素。
这个时候,可以将 a[pos]
看作一个 int
类型的变量。并像普通的 int
类型数据一样进行操作。
比如进行运算或者赋值等。
回到初始化,如果像上面那样一个一个赋值,那效率会十分低下。
我们可以使用大括号 {}
在数组声明时进行初始化赋值。
1 |
|
其中,20、30、40 分别对应下标 0、1、2 。每两个值之间用逗号 ,
隔开。
之后的元素都被自动初始化为 0 。
如果要将数组全部初始化为 0 。那么可以写成 int a[ArSize] = {0};
的形式。
当然,您也可以使用循环进行赋值。
1 |
|
通过这种方式,您也可以将数组初始化成别的值。
这里提供一个函数 memset()
,它是定义在 <cstring>
中的一个函数。
我们也可以使用这个函数来将数组清零。
1 |
|
为什么要对数组进行初始化?
无论是什么数据类型,我们都应尽量将其初始化。
对于数组,在不初始化的情况下,访问任意元素的结果是不确定的。
数组不会自动初始化为 0 ,这一点读者可以自己试验一下。
在能初始化的情况下,我们因尽量将每个变量进行初始化,防止不必要的意外发生。
再谈字符串
数组是一个相同元素的集合,如果一个数组的元素是字符的话,那么它就是一个字符串。
示例程序 5.1
1 |
|
可以看到,字符数组可以直接用 cout
进行输出,并且可以直接用字符串进行赋值初始化。
当然,您也可以采用上述的初始化方法,但那样会非常麻烦。
1 | char str[StrSize] = {'T', 'h', 'i', 's' ......}; |
这就是之前提到的 C 风格 的字符串。关于 C- 风格字符串的相关操作,我们可以使用 <cstring>
中的函数进行。
对于 C++
而言,我们应尽量使用 string
而不是 C- 风格的字符串。
但是,string
的实现还是有依靠 <cstring>
中的函数实现的。
感兴趣的读者可以自行研究 <cstring>
头文件中的函数。
C- 风格的字符串和 string
类都可以通过中括号 []
访问其中元素。
地址与指针初探
地址和指针是 C++
中比较难懂的部分。能够熟练地使用指针,可以让程序更易于管理。
当然,如果使用不当,也会引发十分严重的后果。
地址
地址是什么?
地址是变量存储在内存中的位置。我们可以通过 &
符号查看某一变量的地址。
示例程序 5.2
1 |
|
输出结果如下:
因为电脑不同,所以输出的结果会有差别。
注意看这些地址,它们是以十六进制显示的。
仔细观察 a
和 b
的地址的差为 4,b
与 c
的地址的差也为 4 。
这里的 4 是有意义的,之前我们就介绍过,int
所占的字节数为 4 。
我们可以看出变量在内存中存储的大致样子。
现在考虑一个问题,如果我们需要写一个函数来实现两个变量的交换,那么要怎么实现?
也许您会这么想:
1 | void MySwap1(int x,int y) |
这看起来是可行的,我们用下列程序测试一下:
1 |
|
程序运行结果如下:
可以看到,两个变量的值并没有互换。这是为什么呢?
这里我们就需要补充一下 形式参数 和 实际参数 的区别了。
所谓 形式参数 (简称 形参)只是一个形式上的参数,就好比只传递了一层外壳,而不是整个整体。
而 实际参数(简称 实参)是将整个变量传入函数。是将整个整体传入函数。
而 MySwap1()
函数中传递的就是两个形参,所以只有在函数中,x
和 y
实现了互换。
那么要怎么实现交换两个变量的操作呢?
这里我们传值就不能传一个简单的变量了,就需要传递地址。
传递地址是 C- 的说法,在 C++
中,我们把它称为 引用。
具体的实现如下:
示例程序 5.3
1 |
|
这里传递的参数为 实参,达到了交换两个变量的目的。
指针
在了解完地址之后,我们来介绍指针。
指针是一个很形象的称呼,它用来指向一个地址。指针的声明如下:
1 | int *ptr; |
这样子我们就声明了一个指针。
指针应当直接初始化,让它指向一个变量。如下:
1 | int a = 10; |
此时,*ptr
和 a
是一样的。因此我们可以直接输出 *ptr
。
示例程序 5.4
1 |
|
那么指针有什么用呢?
之后我们会介绍使用指针来实现动态数组的作用。由于这篇只是开个头,所以暂不探讨。
练习
- 对于给定的
n
,输出斐波那契数列的1~n
项。什么是斐波那契数列? - 写一个函数,包含两个参数,第一个参数是要进行操作的数字,第二个参数是一个整数,函数的功能是让第一个参数加上第二个参数,并且返回值为
void
。 - 定义不同类型的指针,复习指针的用法。
——END——