C++ 初学者指南 第四篇(1)

    本章我们将讨论数组,字符串和指针。这三者看起来是相互独立的,其实不然。在C++中,在C++中它们是相关关联的。对其中一个得了解会帮助我们对另外两个的认识。
     数组就是一组有着相同类型的变量的集合,它们共有一个名称。数组可以使一维的或者是多维的,但一维数组是最常用的。数组提供了一种创建一组相关变量的便捷方式。
     最常用的数组可能就是字符数组了,因为我们可以用它来存储字符串。C++语言中没有内置的字符串类型。因此,字符串是用过使用字符数组来实现的。这种字符串的实现方式比起语言自身明确定义字符串类型的方式显得更加自由和灵活。
     指针是一种取值为内存地址的对象。通常,指针被用来访问另外一个对象的值,而另外的那个对象往往就是一个数组。实际上,指针和数组直接的联系比我们想象的还要紧密。

必备技能4.1:一维数组
     一维数组就是一组相关的变量的列表。这种列表在编程中会经常用到。例如,我们可以使用一维数组来存储网络上被激活的用户的账号;可以使用数组来存储一个棒球队的击球得分率。当我们需要计算一组数值的平均值的时候,通常也是使用数组来存储这些数值。数组是现代编程的基础。
     声明一个一维数组的通用形式如下:
类型 名称[大小];
其中的类型表示数组的基本类型。数组的基本类型决定了构成数组的每个元素的类型。大小指明了数组中可以存储的元素的数量。例如,下面的语句声明了一个名称为sample的可以存储10个整型数的数组:
int sample[10];
 我们可以通过索引来访问数组中单独的一个元素。索引描述了一个元素在数组中的位置。在C++中,所有数组的第一个元素的索引都是0。在前面的例子中,sample数组有10个元素,那么索引的取值就是0到9。我们就是通过这种索引的方式来访问数组中的元素的。书写的方式为:我们在数组名称后面的方括号中写上要访问元素的索引值。所以,数组中的第一个元素可以表示为sample[0],最后一个元素可以表示为sample[9]。例如,下面的程序为数组sample装载数值0到9。
#include <iostream>
using namespace std;

int main()
{
     int sample[10]; //数组可以存储个元素
     int t;

     //为数组装载数据
     for ( t = 0; t < 10; ++t)
      sample[t]=t;

     //输出数组的值
     for( t= 0; t < 10; ++t)
      cout << "This is sample[" << t << "]" << sample[t] << "\n";

     return 0;
    }
程序的输出如下:
This is sample[0]0
This is sample[1]1
This is sample[2]2
This is sample[3]3
This is sample[4]4
This is sample[5]5
This is sample[6]6
This is sample[7]7
This is sample[8]8
This is sample[9]9
     在C++中,所有数组都是有连续的内存空间构成。(也就说,所有数组中的元素在内存位置上是紧密相连的。)其中最低的地址对应的就是第一个元素,最高的地址对应的就是最后一个元素。例如,下面的代码段运行后:
int num[5];
int i;
for ( i = 0; i < 5; i++) nums[i]=i;
数组nums的存储形式如下:

num[0]

num[1]

num[2]

num[3]

num[4]

0

1

2

3

4


     数组之所以在编程中会被经常用到就是因为它允许我们方便地对一组相关的变量进行处理。下面的示例程序中,我们创建了一个含有10个元素的数组,并给每个元素赋值。程序然后计算这些数值的平均值,找出其中的最大值和最小值。
/*
    计算一组数值的平均值;找出其中的最大值和最小值
*/

#include <iostream>
using namespace std;

int main()
{
     int i,avg, min_val,max_val;

     int nums[10];

     nums[0]=10;
     nums[1]=18;
     nums[2]=75;
     nums[3]=0;
     nums[4]=1;
     nums[5]=56;
     nums[6]=100;
     nums[7]=12;
     nums[8]=-19;
     nums[9]=88;

     //计算平均值
     avg = 0;
     for ( i = 0; i < 10; i++ )
        avg += nums[i];

     avg /= 10;

     cout << "Average is " << avg << '\n';

 

     //找出最大值和最小值
     min_val = max_val = nums[0];
     for ( i = 1; i < 10; i++ )
     {
          if ( nums[i] < min_val )
              min_val = nums[i];

          if ( nums[i] > max_val )
              max_val = nums[i];
     }

     cout << "Minimum value: " << min_val << "\n";
     cout << "Maximum value: " << max_val << "\n";

     return 0;
}
程序输出如下:
Average is 34
Minimum value: -19
Maximum value: 100
请注意程序中是如何通过循环来访问数组中的元素的。正如程序所展示的那样,for循环的控制变量被用来作为数组的索引。当我们使用数组的时候,类似这样的循环是非常普遍的。
    我们应该注意一点:在C++中我们不能把一个数组赋值给另外的一个数组。例如,下面的代码片段是错误的:
int a[10], b[10];
//...
a = b; //错误
 为了把一个数组中的值赋值给另外一个数组,我们必须对数组中的元素逐个进行赋值。如下:
for ( i = 0 ; i < 10 ; i++) a[i]=b[i];
不进行边界检测
 C++不对数组的边界进行检测。这就是说C++不会阻止我们对数组的越界访问。换句话说,我们可以对大小为N的数组通过大于N值的索引来进行访问,而不会引起任何的编译或者运行错误信息。但是这样做通常都会给程序带来灾难性的后果。例如,尽管在下面的代码片段中,我们越界访问了数组crash,但是编译器依然可以编译并运行这段程序,而不产生任何的错误报告信息。
int crash[10], i; 

for(i=0; i<100; i++) 

    crash[i]=i; 

此时,尽管数组crash中只有10个元素,但是循环会进行100次。这将导致本不属crash数组的内存也被改写。

专家答疑:
问:既然对数组的越界访问可能带来灾难性的后果,为什么C++在进行数组操作的时候不进行边界检测呢?
答:当初设计C++的目的是为了专业的程序员能够创建快速的,最高效的的代码。因此,运行时只进行少许的检测。因为这种检查会降低程序的执行速度。实际上,C++期望我们自己,也就是程序员首先来对数组越界访问的问题负责。如果需要,我们自己可以增加相应的检查代码。另外,如果有必要的话,我们还可以自己定义数组类型,来完成对数组越界的检测。
 
 如果程序中对数组进行了越界的访问,被用于其它目的的内存空间,比如用来存储其它变量可能会被改写。如果是对数组进行了越界的读取,那么读取到的无效数据可能会使程序崩溃。换句话说,我们程序员应该确保数组有足够大的空间以便存储我们的数据,也要在必要的时候对数组的边界进行检测。

练习
1. 什么是一维数组?
2. 数组中第一个元素的索引时0,正确吗?
3. C++中提供了对数组边界的检查吗?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值