第1章C++程序设计基础
C++是在C的基础上扩充而成的,因其独特的机制在计算机领域有着广泛的应用。本章主要讲述C++的基本知识,主要包括词法单位、数据类型、变量和常量、运算符和表达式、语句等基础知识,最后介绍简单的输入与输出方法。
1.1为什么要学习C++程序设计
随着计算机软硬件技术的发展,计算机应用规模不断提高,在软件开发语言和工具方面不断地推陈出新,新语言、新工具层出不穷。目前,国内许多高校,无论是计算机专业还是非计算机专业,都开设了C++语言程序设计课程,并且将它作为一门专业必修课程。
C++是C的扩充版本。C++对C的扩充是由Bjarne Stroustrup于1980年在美国新泽西州玛瑞惠尔的贝尔实验室提出来的,起初,他把这种语言称为“带类的C”,到1983年才改名为C++。
在计算机刚发明时,人们采用打孔机直接进行机器指令程序设计,当程序长达几百条指令时,采用这种方法就很困难了。后来人们设计了用符号表示机器指令的汇编语言,从而能够处理更大更复杂的程序。到了20世纪60年代出现了结构化程序设计方法(C语言就采用这种方法),这使得人们能够容易编写较为复杂的程序。但是,一旦程序设计达到一定的程度,即使结构化程序设计方法也变得无法控制,其复杂性超出了人的管理限度。例如,一旦C程序代码达到了25?000行至100?000行,系统就变得十分复杂,程序员很难控制,而设计C++语言的目的就是为了解决这个问题,其本质就是让程序员理解和管理更大、更复杂的程序。因此,采用支持面向对象的C++语言进行程序设计是时代发展的需要。
C++吸收了C和Simula67(一个古老的计算机语言)的精髓,它具有C所无法比拟的优越性。C++在维持C原来特长(如效率高和程序灵活)的基础上,借鉴了Simula67的面向对象思想,将这两种程序设计语言的优点相结合。C++的程序结构清晰、易于扩展、易于维护同时又不失效率。目前,C++的应用已超出了当初设计其的目的,被成功地应用到数据库、数据通信等系统,并成功地构造了许多高性能的系统软件。C++与C相比,具有三个重要的特征,从而使其优越于C。
第一个特征是支持抽象数据类型(Abstract Data Type,ADT),在C++中ADT表现为类,是对对象的抽象,而对象是数据和操作该数据代码的封装体,它提供了对代码和数据的有效保护,可防止程序其他不相关的部分偶然或错误地使用对象的私有部分,这是C所无法实现的。
第二个特征是多态性,即一个接口,多重算法。C++既支持早期联编又支持滞后联编,而C仅支持前者。
最后一个特征是继承性。继承性一方面保证了代码复用,确保了软件的质量;另一方面也支持分类的概念,从而使对象成为一般情况下的具体实例。
这三个特性,我们将在后面的章节给予详细的讲解。
C++对C基本上完全兼容,很多用C写的应用程序都可以在C++环境中使用,因此C++不是一个纯粹的面向对象程序设计语言,它即支持面向对象的程序设计方法,又支持面向过程的程序设计方法。
目前许多系统软件,如操作系统,数据库管理系统(DBMS)等都采用C++编写,所以从事有关软件开发、自动控制和计算机应用的人员,不掌握C++简直寸步难行。一句话:掌握C++编程已成为许多专业学生的必然选择。
C++有很多版本,国内比较流行的是微软公司推出的Visual C++,本教材采用的是Microsoft Visual Studio 2010,简称VS 2010。
1.2简单的C++程序举例
【例1-1】下面通过一个简单程序来分析C++程序的基本构成和特点。为了便于解释程序,我们给程序加了行号,这在写程序时是不需要的。
1 #include (iostream)
2 using namespace std;
3
4 int main( )
. 5 {
6 int a, b; // 定义两个变量
7
8 cout (( "输入变量a和b:" ;
9 cin )) a )) b; /*从键盘输入a和b的值*/
10 cout (( "a + b = " (( a + b (( endl;
11
12 system("pause");
13 return 0;
14 }
将该程序以扩展名为.cpp的文件形式保存,经过编译、链接生成可执行文件,运行后显示如下信息:
输入变量a和b:22 88 [Enter]
a + b = 110
用户输入22和88并按回车键后,输出它们相加的和是110。
上述C++程序由编译预处理指令、程序主体和注释组成。
程序的第1行是编译预处理指令,include称为文件包含,它使后面的iostream成为本程序的一部分,这样本程序可以直接使用包含文件中的函数。编译预处理是C++提供的组织程序的一种工具,我们将在3.13节介绍。
第2行是用using告诉编译器名字空间的名字,上例中的std代表系统提供的标准名字空间,当采用“using namespace std;”说明以后,程序就可以访问std名字空间中的内容。
第4~14行是程序的主体,其中第4行是函数头,第5~14行称为函数体。一个C++程序由一个或多个函数构成,并且在这些函数中,有且仅有一个主函数main,它是程序执行的入口。任何一个函数由“{}”中的语句序列描述,如本例中的第5行和第14行,而它们括起来的第6~13行是程序执行的语句,并且任何一个语句都以“;”结束。C++程序严格区别字母的大小写。
注意:程序第12行调用系统的暂停功能,当程序执行到此行时,在命令行窗口中输出“请按任意键继续...”的提示,并暂停程序,等待用户按一个键,然后继续执行。如果没有此行,在VS 2010环境下,程序将一晃而过。如果你采用的是低版本的开发环境,则不需要此行,一个程序运行结束后,将自动暂停。在此后的程序中,我们省略了该行,请读者根据开发环境来取舍。
1.3注释方法
C++的注释形式有两种。一种是“/**/”格式,这是C语言中的注释风格。因为C++是C的扩充版,所以它支持C的注释方法。在C语言中,注释是以“/*”开头,以“*/”结束。编译器将忽略这两个符号之间的所有语句,如上例中的第9行采用的就是这种注释风格。另一种注释格式是双斜线(//),在双斜线之后的部分都会被视为注释,如程序中的第6行。注释是程序员用来说明程序或解释代码的语句。注释是程序的组成部分,但编译器在编译时忽略它,不构成可执行代码。它也属于编程风格中关键的一环。
许多程序员都会在源程序中尽可能少地添加注释语句,因为编写源代码本身已经很痛苦了。但是,养成加注释的习惯是很有帮助的。虽然程序员在编程时可能要花费额外的时间,但在以后将会节省很多时间。假设你辛苦数月,编写了一个8?000~60?000行代码的C++程序,你完成了编码,并且调试成功,交给了客户使用,于是你继续做下一个项目。一年以后你需要对程序进行修正,当你打开数万行没有注解的源代码时,你发现有许多函数已经不知道它们的功能,当初设计的目的是什么都不知道。这时你就会想,要是当初加一些必要的注释就好了,但为时已晚,此时要做的只能是用较多的时间来理解源程序,或重写代码。
注意:不必为程序的每一行都加注释,也不必为一目了然的代码加注释,只要注解适当的代码,有助于他人理解即可。
C注释方法能跨越多行,便于对多行注释。但对单行注释并不方便,程序员往往把两者结合起来使用:使用C注释方法完成多行注释,使用C++注释方法完成单行注释。
1.4编程风格
程序员使用标识符、空格、Tab键、空行、标点符号、代码缩进排列和注释等来安排源代码的方式,就构成了编程风格中重要的组成部分。
当编译器对源程序进行编译时,它会将程序处理为一个长字符串。一条语句不在同一行或者操作符和操作数之间有空格,都不会影响编译。但阅读程序的人很难读懂这种书写不规范的程序。例1-2虽然没有什么语法错误,但却很难读。
【例1-2】一个令人难以理解的程序。
#include (iostream)
using namespace std;
int main( ){int a, b; cout (( "输入变量a和b:" ; cin
)) a )) b; cout (( "a + b = " (( a + b (( endl; return 0; }
上面的程序虽然没有违反C++的语法规则,但却难以阅读。较为理想的编程风格应在编程时使用空格、空行和代码缩进排列,从而使别人能很快读懂你的程序。
警告:尽管编程风格的自由度很大,但还是应该遵循程序设计的国际常规,这样其他程序员才会很容易读懂你的程序。建议你模仿本书的编程风格。当然,你也可以参考国际知名公司(如微软、IBM等)的风格。不同的公司编程风格不尽相同,可以参考其提供的样式文件,这对培养编程风格大有裨益。
1.5C++程序的词法单位
本节介绍C++程序使用的字符、关键字和标识符。
1.5.1C++程序中的字符
标准的C++程序采用0x00到0x7F范围内定义的ASCII码所表示的西文字符作为程序的基本字符单位,主要包括26个小写英文字母、26个大写英文字母、10个阿拉伯数字和其他一些符号,如+、-、*、/等,其中每个ASCII码字符占用一个字节。
1.5.2标识符
标识符是程序员自己定义的“单词”,标准C++的标识符由字母、下划线和数字组成,且第一个字符不能为数字,长度一般不超过32个,文件名只识别前8个字符。标识符区分大小写,同一个单词的不同大小写被编译器看作不同的标识符。在实际使用时应尽量采用有意义的单词作为标识符,达到见名知义。
虽然C++编译器允许用户定义的标识符以下划线开始,但因为系统定义的内部符号以下划线或双下划线开始,所以自定义的标识符不提倡以下划线开始。
以下均是合法的并且达到见名知义的标识符:
studentName、StudentName、name_of_student、salary
通过变量名studentName,可以很容易地看出该变量的意义。这种编程风格使得程序易于理解和维护,因为一个大的系统通常由数万行源代码构成,程序的可读性十分重要。定义标识符应尽量选择有含义的英文单词,以下变量命名就毫无意义:
abc、xyzw、a123、x888888
标识符是区分大小写的,变量studentName和StudentName是不同的变量。我们之所以将变量studentName中的“N”大写,是为了增强程序的可读性,如studentname是全部由小写字母构成的变量名,使人不易读懂,因此这不是最好的变量名。
总之,选择标识符时,要尽可能做到“见名知义”,选择有含义的单词符号作为标识符,使别人(包括你本人)容易读懂你的程序。
以下是非法的标识符:
8abc // 标识符不能以数字开头
Student Name // 标识符中间不能有空格
$bill // 标识符不能以$开头
1.5.3关键字
关键字又称保留字,是系统定义的一些特殊标识符,它们具有特定含义,不允许程序员将它们挪作他用,如作为一般标识符使用。C++中常用的部分关键字如表1-1所示:
表1-1C++常用关键字
类型 关键字
数据类型说明符和修饰符 bool、char、class、const、double、enum、float、int、long、short、signed、struct、union、unsigned、void、volatile
存储类型说明符 auto、extern、inline、register、static
访问说明符 friend、private、protected、public
语句 break、case、catch、continue、default、do、else、finally、for、goto、if、return、switch、throw、try、while
运算符和常量 delete、false、new、sizeof、true
其他 asm、explicit、namespace、operator、template、this、typedef、typename、using、virtual
还有一些不常用的关键字:bad_cast、bad_typeid、const_cast、dynamic_cast、except、mutable、reinterpret_cast、static_cast、type_info、typeid和wchar_t。我们会在后面的章节中逐步引入并介绍常用关键字的含义,其他内容读者可参考有关手册。
1.6C++的基本数据类型
从程序设计语言原理的角度讲,C++是一种强类型的语言,必须严格遵循“先定义后使用”的原则。读者可以在后续的学习中慢慢品味该原则。
C++的数据类型分为两大类:基本数据类型和导出数据类型。
基本数据类型也称为C++预定义的类型或内置数据类型,包括字符型(char)、整型(int)、单精度实型(float)、双精度实型(double)、布尔型(bool)和空类型(void)。这些预定义的类型,不仅定义了数据类型,还定义了常用的操作。
导出数据类型是由基本数据类型构造出来的数据类型,包括数组、指针、引用、结构体、共用体、枚举和类等。
字符型用来存放一个字符的ASCII码值,可以将其看成一个8位二进制码的整数,如大写字母A的ASCII码是65。宽字符类型(wchar_t)也称为双字节字符,往往采用Unicode编码格式,该标准中的所有字符都是双字节的,这样可以统一处理西文、中文、阿拉伯文和其他语言的符号。但宽字符类型不属于基本类型,限于篇幅,本书不做介绍。
整型用来存放一个整数,一般占用4个字节,无符号数采用原码的形式表示,而有符号数采用补码表示。
实型用来存放实型数据,C++提供了float和double两种实型类型,因占用的字节数不同,其表示的数据范围也不同。
逻辑型也称布尔型。为了纪念英国的数学家乔治·布尔(George Boolean),在程序设计语言中引入了“布尔”类型。布尔型用来处理逻辑量,取值只有true(真)和false(假)两个,占1个字节,我们将非0值解释为true,将0值解释为false。
注意:从程序设计语言原理的角度讲,布尔变量的取值只能是真或假,但C++中对它的定义很不严格,将0看做false,将非0看做true。这是为了向下兼容,即兼容它的子集C语言,因为C就是这样定义的。
空类型(void)用来定义指针,或用来说明函数的返回值类型,将在5.7.1节讲解。
C++允许在整数、字符或浮点类型前面加上修饰符:short(短类型)、long(长类型)、signed(有符号类型)和unsigned(无符号类型)。表1-2列出了C++中基本数据类型及其变量的取值范围。
表1-2C++中所有的基本数据类型
类型 名称 占用字节数 取值范围
bool 布尔型 1 true,false
[signed] char 有符号字符型 1 -128~127
unsigned char 无符号字符型 1 0~255
[signed] short[int] 有符号短整型 2 -32768~32767
unsigned short[int] 无符号短整型 2 0~65535
[signed]int或signed 有符号整型 4 -231~(231-1)
unsigned[int] 无符号整型 4 0~(232-1)
[signed]long[int] 有符号长整型 4 -231~(231-1)
unsigned long[int] 无符号长整型 4 0~(232-1)
float 实型 4 -1038~1038
double 双精度实型 8 -10308~10308
long double 长双精度实型 8 -10308~10308
注意1:可选项问题。例如[signed]char中的“[signed]”代表可选项,即它等价于:signed char或char。
注意2:有些教材将void类型作为基本数据类型,我们不赞成这种观点。因为void在C++中只能用来修饰指针和函数,后面的章节会讲解它的用途。
1.7变量与常量
1.7.1变量
C++作为一种强类型的程序设计语言,在使用变量前应当先说明类型,然后再定义变量,以便于编译器分配内存空间,以及对程序中的数据类型和运算等进行常见错误检查,以提高程序的编译和运行效率。
在程序运行中,值可变的量称为变量。变量必须用标识符(即变量的名字)来标识。变量根据其取值范围的不同可分为字符型、整型、实型变量等。在程序运行时,系统将会给每个变量分配一段连续的内存单元,用来存放变量的值。
变量有三个要素:变量名、变量的内存空间和变量的值。
1.?定义变量
定义变量的一般格式为:
[(存储类别)] (数据类型) (变量名1)[, (变量名2), …(变量名n )];
其中,“()”括起来的是必选项。存储类别将在3.5节介绍。下面定义几个变量:
bool b; // 定义1个布尔型变量 b
char gender, ch; // 定义2个字符型变量gender和ch
int a, b ; // 定义2个整型变量a和b
double dx ; // 定义1个双精度实型变量dx
float f ; // 定义1个单精度实型变量f
unsigned u ; // 定义1个无符号整型变量u
变量必须先定义后使用,原因如下:
1)变量定义后就具有了变量名和类型。编译系统根据类型给变量分配内存空间,并建立变量名和其内存空间的对应关系,于是可以通过变量名给变量的内存空间赋值或读取该内存空间中的值。
2)变量确定类型后,编译器可以对变量参与的运算做合法性检查。
2.?变量赋值
当使用变量时,变量必须有一个确定的值,给变量赋值的方法有以下两种:
1)变量定义后,用赋值语句赋初值。例如:
int a;
char gender;
a = -12+100;
gender = 'M';
此处“=”是赋值运算符,表示将赋值号右边的运算结果放入左边变量对应的内存空间中。
2)在定义变量的同时,直接对变量赋初值,称为变量的初始化。例如:
int a = 12; // 采用12初始化变量a
char gender='M'; // 采用'M'初始化变量gender
注意:初学者往往有一个疑问,如果变量不赋值,其值是什么,例如:
int a;
在不赋值的情况下,a的值可能是0,也可能是一个不确定的值。既然存在不确定性,就可能导致程序出错,所以我们要对变量赋一个确定的值。
1.7.2文字常量
在程序运行过程中,值不能被改变的量称为常量。其中,文字常量是指程序中直接使用的常量。文字常量存储在代码区而不是数据区,对它的访问不是通过地址进行的。根据取值方式和表达方法的不同,文字常量分为整型、实型、字符型和字符串型。
1.?整型常量
1)十进制整数,如789、-456。
2)八进制整数,如0345、-026。
八进制整数以0(零)开头,在数值中可以出现数字符号0~7。
3)十六进制整数,如0x789、-0xAB。
十六进制整数以0x(零x)或0X开头,在数值中可以出现数字符号0~9、A~F(或a~f)。
4)长整型与无符号型整数:长整型整数,如12L、0234L、-0xABL、12l、0234l、-0xABl;无符号型整数,如12U、0234U、0xABU、12u、0234u、0xABu。
在一个常数后加L或l(小写的L)表示该常数是长整型的整数;在一个常数后加U或u表示该常数是无符号型的整数。
2.?实型常量
实型常量在内存中以浮点形式存放,在程序中书写时,均为十进制数。两种书写形式分别为:
1)小数形式:必须写出小数点,如1.65、1.、.123均是合法的实型常量。
2)指数形式:也称为科学表示法形式,如1.23×105和1.23×10-5在程序中表示为1.23e5或1.23e-5。此处的e也可写成大写的E但e或E前必须有数字,e或E后必须是整型数;1000应写为1e3,而不能写成e3。
3.?字符型常量
用单引号括起来的一个字符称为字符型常量(简称字符常量),如'a'、'A'、'?'、'#'。在内存中对应存放字符的ASCII码值,其数据类型为char。用这种方式只能表示键盘上的可输入字符,而有些控制字符,如回车符、换行符、制表符、响铃、退格等,就不能用这种方式表示,如ASCII码值为10的字符表示换行,就无法用前述方式表示。
针对这些无法直接表示的或具有特殊含义的字符,C++提供了另外一种称为转义序列的表示方法,即“转义”字符。转义字符是以反斜杠“\”开始的特殊字符常量。如'n'表示字母n,而'\n'代表一个字符,即换行符,跟在“\”后的字母n的含义发生了改变,所以称为转义字符。在表1-3中列出C++中定义的转义字符及其含义。
表1-3C++中定义的转义字符及其含义
转义字符 名称 功能或用途
\a 响铃 用于输出响铃
\b 退格(Backspace键) 输出时回退一个字符位置
\f 换页 用于输出
\n 换行符 用于输出,移至下一行行首
\r 回车符 用于输出,回退至本行行首
\t 水平制表符(Tab键) 用于输出,跳至下一制表起始位置
\v 纵向制表符 用于制表
\\ 反斜杠字符 用于表示一个反斜杠字符
\' 单引号 用于表示一个单引号字符
\" 双引号 用于表示一个双引号字符
\nnn nnn是ASCII码的八进制值,最多三位 用八进制ASCII码表示字符
\xhh hh是ASCII码的十六进制值,最多两位 用十六进制ASCII码表示字符
表1-3中最后两行是所有字符的通用表示形式,即用反斜杠加ASCII码表示,它可以表示任一字符。如'\n'表示“换行”,它的ASCII码是十进制数10,10的八进制和十六进制表示分别是12和a,因此'\n'也可以表示成'\12'和'\xa'。字母A的ASCII码是十进制数65,它的八进制和十六进制表示分别是101和41,所以字母A也可以写成'A'、'\101'或'\x41'的形式。
4.?字符串型常量
字符串型常量(简称字符串常量)是用双引号括起来的字符序列,如"123"、"I am a Chinese."、"a"。字符串常量在内存中是按顺序逐个存储串中字符的ASCII码,并在末尾加一个结尾标志'\0'字符,称为串结束符。'\0'表示ASCII码值为0的字符,即ASCII码表中第一个字符,也称为“空字符”,其值为0。字符串的长度是串中'\0'字符之前的所有字符的个数,因此,字符串常量实际占用的字节数是串长加1。
注意:字符串常量"a"和字符常量'a'不同。字符常量'a'在内存中占用一个字节,而字符串常量"a"在内存中占用两个字节。
思考:如果在程序中出现了下面3个串,它们分别代表什么?
"I\"ve done" "dog \" s toy" "\"Love\""
1.7.3符号常量
我们可以在程序中直接书写常量,但有时会遇到一些麻烦,如在程序中需要多次使用3.1415926,这样编写程序时可能出现数字书写错误,同时如果精度上需要变化,如将3.1415926改为3.14,就需要在程序中做多处修改。
C++提供了一种称为符号常量的机制,以避免上述麻烦,即用一个标识符代表一个常量,称为符号常量。只要在程序的开头定义一个符号常量,令其代表一个数值,在程序的后面使用该符号常量即可。符号常量的定义形式为:
#define PI 3.1415926
定义符号常量的好处是,如果在程序中多处使用了同一个常量,当需要对该常量修改时,只需在定义处修改即可,而不需要修改程序中的多处。给符号常量取有意义的名字有利于提高程序的可读性,另外,一般用大写字母给符号常量命名。
1.7.4常变量
const是constant的缩写,是“恒定不变”的意思。被const修饰的变量或对象(参见第8章),都将受到强制保护,可以预防意外的改变。C++采用const定义一种称为常变量的量,其形式为:
const double pi=3.14159;
pi具有变量的三个要素,即具有变量名、内存空间和值。但必须在定义时赋初值,且它的值在程序的运行过程中不能被改变。常变量存储在数据区,并且可以按地址访问,但在初始化后不允许再次被赋值。编译器在编译时会对常变量进行类型检查,这比符号常量要好,因此在C++编程中,完全可以用const常变量取代符号常量。
1.8运算符和表达式
对变量或常量进行运算或处理的符号称为运算符,参与运算的对象称为操作数。
数据处理是通过运算实现的。为表示一个计算过程,需要使用表达式,表达式是由运算符、运算量构成的一个计算序列。在C++有很多运算符,如算术运算符(+、-、*、/、%)、关系运算符()、)=、(、(=、==、!=)等。
1.8.1算术运算符和算术表达式
C++的5个算术运算符是:+(加)、-(减)、*(乘)、/(除)、%(求余),它们是二元运算符,其中+(正号)和-(负号)又可作为一元运算符。
运算符总是与操作数联系在一起,相同的运算符对不同类型的操作数执行运算,其结果是有差异的,称为运算符重载。对于除运算符“/”,当两个运算量均为整数时为整除,如5/2结果为2。当至少有一个运算量为实数时则为通常意义的除法,如5.0/2结果为2.5。
对于求余运算(或称模运算),要求运算量必须为整数,如8%3结果为2,而8.0%3为非法表达式。这说明C++对求余运算符“%”没有重载。
由算术运算符、操作数和括号连接而成的表达式称为算术表达式。当表达式中的每个变量都有确定的值时,才能进行表达式求值。算术运算会产生数据溢出,即运算结果超出表示范围。C++编译器仅对除法运算中除数为0的情况给出错误提示,而溢出不作为错误处理,程序将继续执行,并产生错误的计算结果。因此,我们要注意数据溢出问题。
1.8.2初识运算符的优先级和结合性
如果表达式中出现多个运算符和运算量,计算表达式时必须按照一定的次序,运算符的优先级和结合性规定了运算次序。
所谓优先级是指不同的运算符具有不同的运算优先次序。若在同一个表达式中出现了不同级别的运算符,首先执行优先级较高的运算符。例如表达式d=a+b*c中,三个运算符的优先级由高到低依次是*、+、=,所以先算乘法,再算加法,最后执行赋值运算,即将赋值运算符右边的表达式的值赋给变量d。
括号可以改变运算符的优先级。如表达式d=(a+b)*c的运算次序是+、*和=。在写程序时,若不清楚它们的优先级,就加括号以确定优先级。
结合性是指在表达式中连续出现若干个优先级相同的运算符时,各运算符的执行次序。如表达式中d=a+b-c出现了三个运算符,即+(加)、-(减)、=(赋值),其中加和减的运算优先级相同,而赋值运算符优先级较低。那么加和减运算的结合性是从左向右,因此计算该表达式时,先计算加,再计算减,最后进行赋值。
1.8.3赋值运算符和赋值表达式
将数据存放到变量所标识的内存单元的操作称为赋值。如果该单元中已经有值,则赋值操作以新值取代旧值。从某个变量的内存单元中取出数据的操作称为使用,使用不影响内存单元中的值,即可以多次使用同一个变量。常量只能使用,不能赋值,C++的赋值运算符为“=”,其意义是将赋值号右边的值送到左边变量的内存单元中。