C++程序设计基础(上)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第1章 基本数据与表达式

程序设计语言是人指挥计算机工作的工具。C++语言功能强大,使用灵活,是目前工程中应用比较广泛的一种高级程序设计语言。本章介绍高级程序设计语言的基本概念、C++语言的基本语法单位及表达式运算。

1.1 概述

C++语言源于C语言。C语言诞生于20世纪70年代,最初设计的目的是编写操作系统。因为C语言规则简单,不但具有高级语言的数据表示、运算功能,还可以直接对内存操作,程序运行效率高。基于以上优点,C语言很快成为世界流行的程序设计语言。

然而,人们要求计算机解决的问题越来越多,C语言在处理大问题、复杂问题时表现出来的弱点也越来越明显,例如,缺乏数据类型检查机制,代码重用性差等。

20世纪80年代,美国AT&T贝尔实验室对C语言进行扩充改版,成为C++语言。C++语言保持了C语言原有的高效、简洁的特点,强化了数据的类型检查和语句的结构性,增加了面向对象程序设计的支持。由于C++语言的灵活性、良好的继承性和前瞻性,许多软件公司都为C++语言设计编译系统,提供不同级别的应用类库以及方便实用的开发环境,使C++语言得到广泛应用。

1.1.1 程序设计与程序设计语言

在人类社会生活中,“语言”是人与人之间用来表达意思、交流思想的工具,是由语音、词汇和语法构成的一定系统。人类的思维、感情相当丰富,所以,人类的语言系统非常复杂。甚至同一个词、同一个句子,在不同的环境下、以不同的语气表达,都可能解释成完全不同的意思。

“程序设计语言”是人指挥计算机工作的工具。它是一种工程语言,由字、词和语法规则构成的指令系统。一种高级程序设计语言往往只有一百多条词汇、若干条规则。

高级语言提供了常用的数据描述和对数据操作的规则描述。这些规则是“脱机”的,程序员只需要专注于问题的求解,不必关心机器内部结构和实现。我们说的“程序设计语言”一般是指高级语言。

计算机对问题的求解方式通常可以用数学模型抽象。随着社会科学的发展,人们要求计算机处理的问题越来越复杂,计算机工作者不断寻求简洁可靠的软件开发方法。从过程化、结构化到近代出现的面向对象程序设计,体现了程序设计理论、方法的不断发展。

用高级语言编写的程序称为“源程序”。计算机不能直接识别源程序,必须翻译成二进制代码才能在机器上运行。一旦编译成功,目标程序就可以反复高速执行。

程序设计就是根据特定的问题,使用某种程序设计语言,设计出计算机执行的指令序列。程序设计是一项创造性的工作,根据任务主要完成以下两方面工作。

(1)数据描述

数据描述是指把被处理的信息描述成计算机可以接受的数据形式,如整数、实数、字符、数组等。

信息可以用人工或自动化装置进行记录、解释和处理。使用计算机进行信息处理时,这些信息必须转换成可以被机器识别的“数据”,如:数字、文字、图形、声音等。不管什么数据,计算机都以二进制数的形式进行存储和加工处理。数据是信息的载体,信息依靠数据来表达。

有一些数据,可以直接用程序设计语言的“数据类型”描述,如:数值、字符。另外一些数据,虽然一般的程序设计语言没有提供直接定义,但许多开发商都会提供相应的处理工具。例如,Visual Studio .NET Framework类库提供了丰富的多媒体数据处理方法,可以在界面或程序代码中使用或处理图形、声音等数据。

(2)数据的处理

数据处理是指对数据进行输入、输出、整理、计算、存储、维护等一系列活动。数据处理的目的是为了提取所需的数据成分,获得有用的资料。

程序设计语言的规则都是围绕描述数据、操作数据而设计的。在结构化程序设计中,数据的描述和处理是分离的。用面向对象方法,程序对数据和处理进行封装。按照人们习惯的思维模式和软件重用原则,对象还具有继承、多态等特性。每种程序设计方法都有自己的一套理论框架,相应的设计、分析、建模方法,都有各自的优缺点。采用什么方法设计程序,应该依据问题的性质、规模、特点进行选择。世界上没有一种能解决所有问题的最优方法。

学习C++语言,不仅为了掌握一种实用的计算机软件设计工具,更重要的是,通过该课程学习,掌握计算机程序设计语言的基本语法规则,掌握结构化程序设计和面向对象程序设计的基本方法,为进一步学习和应用打下良好基础。

1.1.2 一个简单的C++程序

问题:输入圆的半径,求圆的周长和面积。

【例1-1】方法一,用结构化方法编程。

数据描述:半径、周长、面积均用浮点型数据表示。

数据处理:

            输入半径r;
            计算周长 =2*π*r;
            计算面积 =π*r*r;
            输出半径,周长,面积。

可以编写如下程序:

            #include<iostream>
            using namespace std;
            int main()
            {  double r,girth,area;          //说明数据
              const double PI = 3.1415;
              cout << "Please input radius:\n";
              cin>>r;                        //输入半径
              girth=2*PI*r;                  //计算周长
              area=PI*r*r;                   //计算面积
              cout<<"radius="<<r<<endl;      //输出数据
              cout << "girth = " << girth << endl;
              cout << "area = " << area << endl;
            }

上述程序运行后,屏幕显示:

            Please input radius:

用户输入:

            6.23

程序继续执行,计算并输出结果:

            radius = 6.23
            girth = 39.1431
            area = 121.931

若再次运行程序,可以输入不同的半径值,求得不同圆的周长和面积。

这个程序很容易读懂。第1行称为预编译指令,说明该程序要使用的外部文件。C++语言标准头文件iostream包含了程序常用的输入cin和输出cout的定义。

第2行是使用名空间的声明。using和namespace都是关键字,std是系统提供的标准命名空间。详细说明见3.8节。

C++语言以函数为程序运行的基本单位,函数的一般形式为:

            类型  函数名  (参数表)
            {
                  语句序列
            }

“函数名”是标识符,用于识别和调用函数。用户自定义函数由程序员命名。一个程序可以由多个文件组成,一个文件可以包含多个函数。每个程序必须有一个,而且只有一个主函数,因为主函数是由系统启动的。最简单的程序只由主函数构成。main是系统规定的主函数名。

“函数名”之前的“类型”表示函数运行返回表达式值的数据类型。C++主函数返回类型一般为int或void。

“函数名”之后一对圆括号相括的是函数参数。如果没有参数,圆括号也不能省略,它是C++函数的标识。函数名、函数返回类型和参数表组成C++的函数头(或称为函数首部)。

函数头之后以一对花括号相括的“语句序列”构成函数体。C++语句以分号结束,一行可以写多条语句,一条语句可以分多行写。程序按语句序列执行。

花括号也可以出现在语句序列中。这时,花括号相括的语句称为复合语句或语句块。根据语句的功能不同,有说明语句、执行语句、流程控制语句等。

以双斜杠“//”开始的文本为程序注释,放置在行末。以“/*…*/”相括的注释文本可以放置在程序的任何位置。注释内容不是执行代码,用于增加程序的可读性。系统只显示注释内容,不予编译。

有关函数定义和使用,参见第3章的相关内容。

【例1-2】方法二,用面向对象方法编程。

当我们用对象思维考虑问题时,可以对问题进一步抽象。所有称为“圆”的这种类型的几何图形,最基本的要素是半径。它决定了圆的大小,也是区分具体圆A、圆B、圆C等的基本数据。一旦定义了具体的有半径值的圆,就有它特定的周长和面积了。

“圆”是一种类型。在面向对象方法中,称为“类类型”或“类”。“圆”类型的基本数据是“半径”。类的数据称为“属性”或“数据成员”。

数据成员有了具体的值之后,就可以计算周长和面积了。这种“计算”由程序代码实现,并且“封装”在类中,称为类的“方法”或“成员函数”。

下面是用这种方法编写的C++程序:

            #include<iostream>
            using namespace std;
            class Circle             //说明类
            {    double radius;      //类的数据成员
              public :
                  //类的成员函数
                  void Set_Radius( double r )
                  { radius = r; }
                  double Get_Radius()
                  {return  radius;}
                  double Get_Girth()
                  {return  2*3.14*radius;}
                  double Get_Area()
                  {return  3.14*radius*radius;}
            };
            int main()
            {  Circle A,B;         //说明对象
              A.Set_Radius( 6.23 );
              cout << "A.Radius = " << A.Get_Radius() << endl;
              cout << "A.Girth = " << A.Get_Girth() << endl;
              cout << "A.Area = " << A.Get_Area() << endl;
              B.Set_Radius( 10.5 );
              cout << "B.radius = " << B.Get_Radius() << endl;
              cout << "B.Girth=" << B.Get_Girth() << endl;
              cout << "B.Area = " << B.Get_Area() << endl;
            }

程序运行结果:

            A.Radius = 6.23
            A.Girth = 39.1244
            A.Area = 121.873
            B.Radius = 10.5
            B.Girth = 65.94
            B.Area = 346.185

该例程首先说明一个类Circle。类中数据成员radius用于定义半径。成员函数Set_Radius用于设置半径的值,Get_Radius获取半径,Get_Girth计算并返回圆周长,Get_Area计算并返回圆面积。

主函数中说明了圆类Circle的两个圆:A和B。A和B称为Circle类的实例或对象。main函数中由对象调用成员函数输出两个圆的半径、周长和面积。

这个程序比例1-1看起来要烦琐一些。但是,以Circle类为基础,可以很方便地派生新的类。新的类对原有类的特性不需要重定义,可以自己定义新的数据,例如,指定圆心坐标,填充圆的颜色;派生出球体、圆柱体等新的几何体。每个新类都可以拥有自己的成员函数,实现自己特有的功能,这是结构化程序设计方法所做不到的。面向对象技术提供了软件重用、解决大问题和复杂问题的有效途径。

1.1.3 程序的编译执行

用高级语言编写的程序称为“源程序”。源程序是文本文件,便于阅读修改。C++的.cpp文件是文本文件,可以用各种字处理工具打开和编辑。计算机不能直接识别源程序,必须翻译成二进制代码才能在机器上运行。翻译方式有两种:一种称为解释方式,另一种称为编译方式。解释方式是指由“解释程序”对源程序逐条语句地一边翻译,一边执行。这种方式执行速度慢,便于观察调试程序。编译方式是指由“编译程序”把源程序全部翻译成二进制代码。编译后的程序称为“目标程序”,可以反复高速运行。每一种高级语言都配有解释或编译系统。

C++提供编译执行方式。实现一个C++语言源程序主要经过以下3个步骤。

1.编辑

使用C++语言编辑器或其他文字编辑器录入源程序。若使用C++语言编辑器,则系统自动生成.cpp文件扩展名;若使用其他文字编辑器,则只有以.cpp为扩展名的文件才能被C++语言识别。.cpp文件是文本文件。

2.编译

把一个.cpp文件编译成.exe目标文件,要经过预处理、编译和连接3个步骤:预处理的作用是执行程序编译之前的准备,例如执行包含指令、宏替换命令;然后编译器对程序进行语法检查,如果发现语法错误,则显示错误信息,让程序员修改,直至正确,生成目标代码;最后把目标代码进行连接处理,往往还会加入一些系统提供的库文件代码。

这些步骤在集成开发环境中会自动完成。

3.运行

VC.NET用文件夹管理应用程序。经过编译后,应用程序文件夹中有一个扩展名为.sln的解决方案文件,需要在C++环境下执行。还生成一个debug文件夹,里面有一个.exe文件,可以直接在操作系统(如DOS,Windows)环境下执行。为了便于测试程序,C++提供了强有力的跟踪调试和错误处理功能。源程序和目标程序都能够作为文件永久保存。

编写源程序难免存在一些错误,这些错误可以分成以下4类。

① 编译错误:在编译源程序时发现的语法错误。例如,表达式(a+b*(c-d)缺少了右括号。

② 连接错误:在程序编译之后,进行连接时出现的错误。例如,找不到连接库文件。

③ 运行错误:执行目标程序时发现的错误。例如,执行标准函数sqrt(x),求x的平方根,而x的值为负数。

④ 逻辑错误:编译和运行时均不能发现的错误。例如,执行表达式2/4,期望值是0.5,但C++作整除运算,结果为0。

一个程序经常要经过反复的调试、验证会才能完善,投入使用。因此,编写的程序应该力求达到以下目标。

① 正确性:这要求程序员熟悉所使用的程序设计语言,避免语法、语义上的错误;设计简单易行的算法达到预期目的;对复杂的问题,则应考虑使用有效的程序设计方法。

② 易读性:一个程序结构清晰易读,才能便于查错,便于修改。一个程序模块耦合度低、接口清晰,才便于代码的重用。

③ 健壮性:当输入或运行出现数据错误时,程序能够做出适当的反应或进行处理,而不会产生莫名其妙的结果。

④ 运行高效率:程序运行时间较短,而且占用的存储空间较小。

为达到以上目标,需要我们在不断学习和实践中提高程序设计水平。“程序”是人的智力产品。从理论上说,程序是永远不会损坏的。实际上,程序在整个生存周期都会根据需要进行修改、维护,都可能产生错误。所有的硬件产品都允许有误差,但程序错误是不允许的,它有时甚至会产生悲剧性的后果。程序的生产和维护比硬件产品复杂得多。所以,计算机科学界期望有一套工程化的方法进行程序的开发维护。为了体现这种工程思想,程序就要伴随着一套开发、维护、使用的文档。程序加上这些相关文档称为软件。