Pascal到C++.docx
- 文档编号:6766541
- 上传时间:2023-01-10
- 格式:DOCX
- 页数:61
- 大小:82.25KB
Pascal到C++.docx
《Pascal到C++.docx》由会员分享,可在线阅读,更多相关《Pascal到C++.docx(61页珍藏版)》请在冰豆网上搜索。
Pascal到C++
论C++语言在信息学竞赛中的应用
浙江省余姚中学韩文弢
摘要程序设计语言是信息学竞赛的一个重要组成部分,任何算法只有通过程序设计语言实现之后才能真正解决问题。
C++语言凭借其高度的灵活性和强大的功能在大学生竞赛中被非常广泛地使用,在中学生竞赛中的使用也越来越广泛。
本文分为三章,由浅入深地介绍了C++语言的基础知识、面向对象编程基础和常用标准库、标准模板库(STL)。
希望本文能够对想在信息学竞赛中使用C++语言的读者有所帮助。
关键字信息学竞赛C++程序设计语言标准模板库
目录
前言2
1从Pascal到C++3
1.1世界,你好!
3
1.2类型和定义4
1.3指针、数组和结构7
1.4表达式和语句11
1.5函数14
1.6常用的库函数16
1.7本章小结17
2深入C++语言20
2.1类20
2.2操作符重载24
2.3字符串26
2.4流27
2.5本章小结30
3STL简介33
3.1STL概述33
3.2迭代器34
3.3算法35
3.4容器42
3.5本章小结46
总结47
参考文献48
前言
信息学竞赛一般要求在一定的时间内,理解并分析题意,设计符合给定时间和空间复杂度要求的算法,并在计算机上使用一定的程序设计语言正确地实现算法。
由于整个竞赛存在时间限制(特别是ACM/ICPC类竞赛,在解决问题数目相等的情况下以做题累计时间的多少来决定名次),因此所使用的程序设计语言能否正确、快速地实现算法对竞赛的成绩影响颇大。
所以,编程复杂度越来越受到重视。
编程复杂度在很大程度上与所选用的程序设计语言有关。
一般信息学竞赛比较常用的程序设计语言有以下几种:
BASIC、Pascal、C/C++、Java,它们的特点如下表所示:
BASIC
Pascal
C++
Java
学习难度
容易
一般
较难
较难
语言特点
简单
严谨
灵活
高度面向对象
程序运行速度
慢
较快
快
慢
库函数功能
弱
一般
很强
强
在目前的中学生信息学竞赛中,Pascal语言使用较为广泛。
但是C++语言凭借其本身所具有的高度的灵活性,以及它所带的库的强大功能,被越来越多的选手所使用。
本文就是在这样一个背景下撰写的。
在本文中,Pascal语言以FreePascal为准;而C++语言则以标准的ANSI/ISOC++为准。
另外,需要注意的一点是,本文并不是参考资料。
因此,对于C++语言,本文不可能介绍得面面俱到,十分详细。
如果想更加深入的学习C++语言,可以阅读有关资料。
1从Pascal到C++
阅读本章的必要条件:
会使用Pascal语言、了解一定的算法知识
由于目前中学生信息学竞赛中使用Pascal语言的选手较多,本章的目的就是使读者在已经掌握Pascal语言的情况下,能够尽快地从Pascal语言转型到C++语言。
如果你已经对C++语言有一定的了解,可以跳过本章,直接阅读下一章。
1.1世界,你好!
首先,让我们通过一个非常简单的C++程序,来初步地了解C++语言。
//:
C01:
Hello.cpp
// Hello, world!
#include
using namespace std;
int main() {
cout << "Hello, world!
" << endl;
} ///:
~
这个程序的作用就是在屏幕上输出“Hello,world!
”的字样。
第一行、第二行以及最后一行中,从“//”开始到行末的部分都是注释。
在C++中,注释有两种写法。
一种是从C中继承的块注释,以“/*”开始,到“*/”结束。
另一种就是新增的行注释,从“//”开始,到行末为止。
第三行中以“#”开始的内容被称为预处理指令,这一行的作用是把一个叫做iostream的头文件包含到我们的程序中来,相当于Pascal中使用单元的uses语句。
不过Pascal中默认使用System单元,其中包含了我们常用的绝大多数过程和函数,而C++默认是不包含任何头文件的。
另外,C语言中的头文件都是以.h结尾的,而标准的C++提倡使用没有扩展名的头文件。
第四行让我们可以在程序中直接使用std名字空间内的标识符。
std名字空间包含了所有标准C++提供的类和函数,为了简便起见,一般总在包含头文件的预处理命令后写上这一行。
有关名字空间的详细内容可以参考有关资料。
第五行到第七行就是程序的主体。
在这个程序中,我们定义了一个名字为main的函数。
这个函数就相当于Pascal中的主程序。
任何一个能够独立执行的C++程序都需要有一个main函数。
我们还可以看出,在C++中,“{”和“}”就相当于Pascal中的“begin”和“end”。
第六行的作用就是向屏幕输出“Hello,world!
”,并换行。
其中,cout就代表标准输出(一般就是屏幕),相当于Pascal中的Output。
“<<”在C++中本来是位左移运算符,但是在这里被重新定义为插入符,作用是把一段内容插入到一个输出流中。
endl就是换行的意思。
另外,C++中的字符串是用双引号括起来的,每一个语句也用“;”表示结束。
1.2类型和定义
类型
与Pascal相似,C++也提供了基本类型以及程序员可以自定义的类型。
下表展示了C++中一些常用的基本类型以及与之对应的Pascal类型:
名称
C++类型
Pascal类型
范围
大小
布尔型
bool
Boolean
true/false
1
字符型
char
Char
所有单字节字符
1
8位有符号整型
char
ShortInt
-128..127
1
8位无符号整型
unsignedchar
Byte
0..255
1
16位有符号整型
short
SmallInt
-32768..32767
2
16位无符号整型
unsignedshort
Word
0..65535
2
32位有符号整型
int
LongInt
-2147483648..2147483647
4
32位无符号整型
unsignedint
LongWord
0..4294967295
4
64位有符号整型
longlong
Int64
-263..263-1
8
64位无符号整型
unsignedlonglong
QWord
0..264-1
8
单精度浮点型
float
Single
1.17e-38..3.40e38
4
双精度浮点型
double
Double
2.22e-308..1.79e308
8
扩展浮点型
longdouble
Extended
3.36e-4932..1.18e4932
10/12
布尔型
与Pascal相似,布尔型用来表示逻辑运算的结果。
一个布尔型量的值只可能是true或者false,true的数值是1,而false的数值是0。
与Pascal不同的是,在C++中,很多其他类型的量都可以隐式地转化为布尔型,这时,非零的值都被转化成true,而零被转化成false。
字符型
单个字符的常数要用单引号括起来,一些不能显示的字符可以通过转义符来表示(参见下表)。
另外,从上表中可以看出,在C++中,字符型和单字节的整型实际上是等价的。
举例来说,'A'的数值就是65。
名称
ASCII名称
C++名称
换行
NL(LF)
\n
水平制表符
HT
\t
竖直制表符
VT
\v
退格
BS
\b
回车
CR
\r
复位
FF
\f
铃声
BEL
\a
反斜杠
\
\\
问号
?
\?
单引号
'
\'
双引号
"
\"
八进制ASCII码
ooo
\ooo
十六进制ASCII码
hhh
\xhhh
整型
C++中的整型和Pascal差不多,值得注意的是C++中的各种整型的类型名实际上是由三部分组成的。
首先是signed或者unsigned,表示有符号或者无符号,默认为有符号;其次是长度的修饰词(char除外),有short、long、longlong,默认为long;最后就是int,在前面有修饰词的情况下可以省略。
在C++中,整型的常数是由前缀、数字序列以及后缀构成的。
前缀用来描述常数所使用的进制,默认是十进制,以“0”开头的是八进制,以“0x”开头的是十六进制。
后缀描述该常数的长度和有无符号,“l”表示32位整数,“ll”表示64位整数,“u”表示无符号整数,可以组合使用。
另外,前缀和后缀中的字母大小写不限。
浮点型
C++中的浮点型和Pascal也差不多。
浮点型的常数也有定点和浮点两种写法。
定点数的写法基本与Pascal一致,区别在于在C++中如果整数部分或者小数部分为零就可以省略,但是小数点必须保留。
例如,“39.”和“.142857”在C++中都是合法的。
浮点数的写法与Pascal相同,底数和阶码之间用“e”分隔。
另外,C++中的浮点数还可以带后缀,“f”表示单精度型,“l”表示扩展型,省略则表示双精度型。
枚举类型
与Pascal类似的,C++中也有枚举类型。
例如:
enumkeyword{ASM,AUTO,BREAK}
其中,该枚举类型的名称是keyword,值可以是ASM、AUTO或者BREAK。
C++语言没有提供内置的子界和集合类型。
另外也没有提供内置字符串类型,但是字符串处理的方式却有两套。
一套是从C语言中继承的字符指针的处理方式,比较麻烦,具体请参考有关资料;另一套则是C++标准库提供的string类,比较方便,将会在2.3中详细描述。
为了了解各种类型实际所占的字节数,我们来看下面这个程序:
//:
C01:
Types.cpp
// Built-in types
#include
using namespace std;
int main() {
cout << "Size of bool:
"
<< sizeof(bool) << endl;
cout << "Size of char:
"
<< sizeof(char) << endl;
cout << "Size of unsigned char:
"
<< sizeof(unsigned char) << endl;
cout << "Size of short:
"
<< sizeof(short) << endl;
cout << "Size of unsigned short:
"
<< sizeof(unsigned short) << endl;
cout << "Size of int:
"
<< sizeof(int) << endl;
cout << "Size of unsigned int:
"
<< sizeof(unsigned int) << endl;
cout << "Size of long long:
"
<< sizeof(long long) << endl;
cout << "Size of unsigned long long:
"
<< sizeof(unsigned long long) << endl;
cout << "Size of float:
"
<< sizeof(float) << endl;
cout << "Size of double:
"
<< sizeof(double) << endl;
cout << "Size of long double:
"
<< sizeof(long double) << endl;
} ///:
~
其中,sizeof的作用就是返回括号里的类型的大小(也可以是变量或者常量)。
定义
与Pascal不同,C++中的定义几乎可以出现在程序的任何地方。
定义由四部分构成:
修饰符(可选)、基本类型、主体以及初始值(可选),一般要以分号结尾。
修饰符一般用来指定一些与类型无关的内容。
主体由一个名字和一些修饰的操作符组成(各种修饰的操作符将在1.3中详细描述)。
例如:
intnumber;
charc=‘H’;
constdoublepi=3.141592653579893;
分别定义了一个整型变量number,一个被初始化为'H'的字符型变量c,以及一个被初始化为3.141592653579893的双精度浮点型常量pi。
另外,同一类型的变量的定义可以写成一个语句,例如:
inta=39,b,c=23;
定义了3个整型变量a、b、c,其中a、c分别被初始化为39和23。
对于没有给出初始值的变量,如果它是一个全局变量(定义在任何函数之外的地方),那么将被初始化为零(与类型有关);如果它是一个局部变量(定义在某个函数中),那么将不被初始化。
在C++中,名字(标识符)可以由字母和数字组成,但第一个字符必须为字母(下划线“_”也被认为是一个字母)。
记住,与Pascal不同,C++对于大小写是敏感的。
类型定义
如果在一个定义之前冠以“typedef”的话,那么这个定义就将变成一个类型定义。
例如:
typedefunsignedlonglongQWord;
这时,QWord将不再是一个变量的名字,而是一个类型的名字。
这就相当于Pascal中type子句中所做的事情。
接下来,你就可以用这个名字来定义新的变量。
这样往往能够简化后面的定义。
例如:
QWordx;
这个语句就定义了一个QWord类型(也就是unsignedlonglong)类型的变量x。
定义的生命周期
在C++中,名字一旦被定义之后就可以被使用。
但是,名字也有一定的生命周期(有效域)。
当超过这个周期时,名字就会失效。
同时,也就可以被重新定义了。
一般来说,全局变量的生命周期是整个程序。
而局部变量的生命周期从被定义之处开始,到定义所出现的程序块结束为止(程序块是一段由花括号括起来的程序)。
当局部变量和全局变量重名时,全局变量被隐藏起来,暂时不可用。
1.3指针、数组和结构
指针
虽然Pascal中也有指针,但是C++中的指针功能要比Pascal中的强大得多。
在C++中,对于任何一种类型T,类型T*就表示指向类型T的量的指针类型,这里*就是上一节所提到的类型的修饰操作符。
例如:
charc='a';
char*p=&c;
其中,变量p就是一个指向char类型的量的指针,并被初始化为指向变量c(这里,操作符“&”的作用就是求它后面所跟变量的内存地址)。
对一个指针而言,最基本的操作就是提取它所指向的内容。
在C++中,这个操作由操作符“*”完成。
例如:
charc2=*p;
这时,变量c2的值就是'a'。
指针变量还可以被赋值为0,这时,指针变量不指向任何有效的存储单元。
对一个值为0的指针变量进行取值运算会引起错误。
另外,C++中的指针还支持很多其他运算,将会在1.4中详细描述。
动态内存分配
与Pascal类似的,C++也可以动态地分配内存。
动态内存分配和回收是通过操作符new和delete来实现的,与Pascal中的New和Dispose类似,但用法不同,例如:
int*p=newint;
int*p2=newint[10];
deletep;
delete[]p2;
第一个语句分配了一个整型变量的空间,并把首地址存在指针p中。
而第二个语句则分配了连续10个整型变量的空间,并把第一个变量的首地址存在了指针p2中。
后面两个语句分别回收了前面两个语句所分配的空间,注意第四个语句的delete后面有一对空的方括号,表示回收一组变量的空间。
在分配连续多个变量时,个数可以用整型变量或者常量来描述。
指针常量和指向常量的指针
由于指针也是一种数据类型,因此有指针变量,也有指针常量。
不过这个问题稍微有些复杂,因为指针除了本身之外还带有一个所指向的基础类型。
因此,与指针有关的常量就分为指针常量和指向常量的指针。
所谓指针常量,就是说,指针本身是个常量,所指向的地址不能被改变,但是这个指针所指向的内容却可以被改变。
也就是说,p是常量,而*p不是常量。
指针常量的类型为T*const。
所谓指向常量的指针,就是说,指针本身不是常量,所指向的地址可以被改变,但是这个指针所指向的内容却是一个常量,不能被改变。
也就是说,p不是常量,而*p是常量。
指向常量的指针的类型为constT*或者Tconst*。
当然,这两样东西可以结合起来,结果就得到了指向常量的指针常量(听上去有点复杂)。
这时,p和*p都是常量,类型为constT*const或者Tconst*const。
数组
在C++中,对于任何一种类型T,T[n]就表示元素类型为T、有n个元素的数组类型。
其中,n必须是在编译时就能够确定的常量。
例如:
floatv[3];
char*a[32];
上面第一个语句定义了一个有3个单精度浮点型元素的数组v,第二个语句定义了一个有32个字符指针型元素的数组a。
记住,C++中的数组元素的编号都是从0开始的。
因此,数组v的3个元素分别为v[0]、v[1]和v[2],数组a也同样。
这可能会使熟悉Pascal的人感到很不习惯。
在C++中,多维数组是通过元素为数组的数组来实现的。
例如:
intd2[10][20];
就定义了一个二维数组,第一维的大小为10,第二维的大小为20。
同Pascal类似的,C++中多维数组也是按照行优先的方式存储的。
另外,值得引起注意的是,C++中多维数组无论是定义,还是使用其中的某个元素,各个维都要分别用方括号括起来,而不能使用逗号分隔,这与Pascal是不同的。
更有意思的是,逗号在C++中也是一种操作符,它的作用是依次对逗号分隔的各个表达式进行计算,并最终返回最后一个表达式的值。
因此,d2[1,2]并代表d2[1][2],而是等价于d2[2],表示一个大小为20的一维整型数组。
从Pascal转到C++的读者要避免出现这样的问题。
还有,绝大多数C++编译器生成的程序在运行过程中不检查数组下标是否越界,需要读者自己注意这个问题。
数组的初始化
数组的初始化和一般的变量类似,不过所有元素要用花括号括起来,元素之间用逗号分隔。
例如:
intv1[]={1,2,3,4};
charv2[3]={'a','b','c'};
intv3[8]={1,2,3,4};
这时,方括号内的数字可以省略。
如果省略,数组的大小将由后面花括号中元素的个数决定。
如果方括号内的数字比花括号中元素的个数大,则数组中最后缺少初始值的那些元素将被初始化为零。
如果方括号内的数字比花括号中元素的个数小,则编译器将会报错。
数组与指针的联系
在C++中,指针和数组有着密切的联系。
一个数组的名字可以被用作指向该数组中第一个元素(或者说是第零个)的指针。
例如:
intv[]={1,2,3,4};
int*p1=v;
int*p2=&v[0];
int*p3=&v[4];
同时,指针也可以被当作一个数组来使用。
例如:
intv[]={1,2,3,4};
int*p=v;
v[2]=1;
p[2]=1;
上面的最后两个语句是等价的。
引用
引用就是一个变量的别名。
引用主要用于函数的参数以及重载操作符的返回值。
对于任何一种类型T,T&就表示类型T的引用类型。
例如:
inti=1;
int&r=i;//r和i表示同一个整型变量
intx=r;//x=1
r=2;//i=2
另外,引用在定义时一定要被初始化,以保证它的确代表了一定的存储空间。
结构
C++中的结构类型就相当于Pascal中的记录类型。
例如:
structcharacter_type{
charname[20];
intlevel;
intlife;
intmana;
intexperience;
intmoney;
};
这就定义了一种名为character_type的类型。
与Pascal类似的,记录类型的变量可用通过“.”来访问其中的各个成员。
例如:
character_typenecromancer;
necromancer.level=99;
necromancer.money=123456789;
character_type*p=&necromancer;
(*p).life=1024;
p->mana=2048;
从中我们还可以看出,要使用一个指向结构类型的量的指针所指向的元素的各个成员时,除了采用(*ptr).field的方式外,我们还可以使用ptr->field的方式。
但不能写成*ptr.field,因为“.”的优先级要比“*”高,这样写的意思是:
ptr是一个结构类型的变量,其中有一个名为field的成员,其类型是一种指针,我要使用ptr.field所指向的内容。
另外,在C++中,链表的定义要比Pascal来得简便:
structnode_type{
data_typedata;
node_type*next;
};
不过,有些时候相互嵌套还是不能避免的。
例如:
structlist;//留到以后给出完整的定义
structlink{
list*data;
link*prev;
link*next;
};
structlist{
link*head;
};
这时候就必须先空地声明一次,把其中某一种类型的名字先提出来。
这种情况在函数相互递归调用时也会遇到。
1.4表达式和语句
表达式
和Pascal一样,C++中的表达式也是由操作符和操作数构成的。
操作数
与Pascal类似的,C++表达式中的操作数可以是常数、常量或者变量,也可以是函数的返回值。
但与Pascal不同的是,C++中的某些操作符具有副作用(换句话说,这些操作符会对操作数的值进行修改),这些操作符只能作用在左值上。
左值最初的意思是可以出现在赋值号左边的东西,它的特点就是代表内存中一定的存储空间,能够被修改。
操作符
首先,我们来看下表:
操作符名称
C++操作符
Pascal操作符
加法
+
+
减法
-
-
乘法
*
*
整数除法
/
div
实数除法
/
/
取余数
%
mod
小于
<
<
小于等于
<=
<=
大于
>
>
大于等于
>=
>=
相等
==
=
不等
!
=
<>
位非
~
not
逻辑非
!
not
位与
&
and
逻辑与
&&
and
位或
|
or
逻辑或
||
or
位异或
^
xor
位左移
<<
sh
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Pascal C+