第一部分 – 入门基础
第一部分 入门基础一、C++简介
1.融合的编程方式:C语言代表的过程性语言、面向对象(OOP)编程、C++模板支持的泛型编程。
2.汇编语言依赖于计算机内部的机器语言(都属于低级语言,直接操作硬件。汇编语言是机器语言的助记符),C、C++是高级语言。
3.数据+算法=程序,C语言为结构化编程(顺序、循环、分支)。
4.C++语言的基本的模块:函数
5.C++由Bjarne Stroustrup于20世纪80年代在贝尔实验室开发。
6.在一定程度上来说,C++是C的超集。(几乎所有的有效C语言程序都是有效的C++程序)但C++并没有完全包含C语言。



7.将程序的源代码译为机器语言,形成目标代码(object code,.obj);将启动代码与库代码和目标代码链接在一起,即链接,得到可执行文件。
二、第一个程序
示例程序:摘自C++ PRIMER PLUS(6TH EDITION)
// myfirst.cpp–displays a message
#include <iostream> // a PREPROCESSOR directive
int main() // function header
{ // start of function body
using namespace std; // make definitions visible
cout << “Come up and C++ me some time.”; // message
cout << endl; // start a new line
cout << “You won’t regret it!” << endl; // more output
// If the output window closes before you can read it,
// add the following code:
// cout << “Press any key to continue.” <
// cin.get();
return 0; // terminate main()
} // end of function body
7.单行注释:// 开头;多行注释:/* */ 开头。编译器会忽略注释。
8.▲C++对大小写敏感,Cout与cout并不一样。
9.C++源文件的扩展名:.cpp
10.main()函数
main()是默认的主函数。函数定义由花括号及其里面的语句组成,int main()叫做函数头,花括号中包括的语句叫函数体,指出了函数具体做什么。return 0;是返回语句,结束该函数,返回0表示程序执行成功并退出。
11. 每条完整的指令称为语句,以分号结束。
12. 
位于函数名前面的部分叫做函数返回类型,函数名后括号里的部分叫做形式参数列表(简称形参列表)。
13. main()函数被启动代码调用。
14. C++函数给调用参数返回的值是返回值。此处int表示整数值。空括号意味main()不接受参数。
15. int main(void)是一种变体,void关键字指出函数不接受任何参数,与int main()等价。
16. #include
17. 像iostream这样的文件叫包含文件,也叫头文件。
C语言头文件的后缀为.h,C++的头文件没有后缀。C++可以使用C语言标准头文件,需去掉.h后缀并加上c前缀。如:math.h -> cmath
18. using namespace std;是using编译指令,表示使用std(即标准名称空间)名称空间。
如果名称空间a中有函数b(),则调用时为a::b().
19. using std::cout;表示只使用std::cout这个名称,而不是将整个std都导入。
20. cout<<表达式0<<表达式1<<.......;可以把表达式插入到输出流中输出。
21. cout << “Come up and C++ me some time.”; 其中的字符串以“”扩起。(注意是英文标点符号)
22. 控制符endl:进行换行,在名称空间std中被定义。其等价于换行符’\n’(注意:字符串用“”引起,字符用‘’引起),其被视作一个字符。在字符串中包含它可以换行。
23. 空格、制表符与回车统称空白。
24. 声明语句声明变量: 类型名称 变量名(=值);如int total;或int total=0;
25. 变量名标识了一个内存单元,因其可以修改,称作变量。
26. 程序中的声明语句叫声明定义语句,简称为定义。会导致编译器为其分配内存空间。
27. C++中还有引用声明,声明不一定是定义,但定义一定是声明。
28. =是赋值运算符,使用方法: 变量名=值; 其从右向左执行。可以连续使用赋值运算符。
29. cout可以输出变量,插入时输入变量名。
30. 使用cin: cin可以进行输入,用法cin>>变量0>>……;输入多个值用空格回车分隔。
31.
cmath中的sqrt()计算算术平方根。sqrt(25)值为5.sqrt(25)叫函数调用,被调用的函数叫做被调用函数(被调函数,called function),包含函数调用的函数叫调用函数(主调函数,calling function)。
32.
函数调用圆括号的值是实际参数(实参)。
33. 函数原型:sqrt()的函数原型:
double sqrt(double);
double表示双精度浮点数(小数)
函数原型只描述函数接口。
34. 在创建变量时赋值叫初始化。
35. 用户定义函数:语法:
返回类型 函数名(形参列表)
{
语句
}
原型:返回类型 函数名(形参列表或形参类型的列表);
在形参列表中,每个参数以 “类型 参数名”的形式出现,中间以逗号分隔。
▲每个函数都是独立的,不可嵌套。
例:int solve(int,double); int solve(int a,double b){…}
无返回值的函数返回类型为void.
36. ▲变量名和函数名的命名规则:
(1)不能使用关键字作为名称
(2)不能在名称中带有空格
(3)在同一作用域下,一些名称不可重复(函数重载除外)
(4)名称以字母、下划线开头,以字母、下划线与数字组成。
37. 在函数外使用using指令:对所有函数有效,在函数里使用using指令:对本函数有用。
总结:简单程序的结构 #include<标准头文件> //…引入若干个头文件 using namespace std; int main() //或 int main(void) { //一些语句 return 0;//程序成功执行后退出 } |
三、基本数据类型
38. 整型:没有小数部分的数字。分为符号整型与无符号整形。符号整型有正数、0、负数。
而无符号整型没有负数。
(1)符号整型short、int、long、long long
①.short至少16位,int至少与short一样长,long至少32位,且至少与int一样长,long long至少64位,且至少与long一样长。
②.大部分系统使用的长度:
short为16位 int和long为32位 long long 为64位
③.在头文件climits中表示各种限制的符号名称,如下:

④.符号常量以#define定义,#define是预处理指令,用法:
#define 名称 表达式(表达式可省略,只定义一个名称)
这些定义也叫宏定义。在预处理时会进行文本替换。
⑤.初始化:可以将变量初始化为另一个变量(乙定义)、表达式、字面值常量。
⑥.C++的初始化方法:类型名 变量名(表达式);
将大括号初始化器用于单值变量:类型名 变量名={表达式};
***C++11初始化方式:将大括号初始化器用于单值变量:类型名 变量名{表达式};
大括号中可以不包含任何信息,变量会初始化为0
类型名 变量{}; 或 类型名 变量={}; 其中变量的值为0.
(2)无符号类型:
unsigned short、unsigned int(unsigned)、unsigned long、unsigned long long
(3)整型字面量:
①C++整型的三种表示:十进制、八进制、十六进制
如果第一位为1~9,基数为10;如果第一位为0,第二位为1~7,基数为8;如果前两位为0x或0X,基数为16.(基数为R表示R进制数)
▲▲计算机中的数据都以二进制存储。
②cout的控制符hex表示输出16进制整数,oct表示输出8进制整数,dec表示输出10进制整数。默认为10进制整数。
③C++将整型常量存储为int类型
④其他类型常量的表示:
前后缀 表示的类型 前后缀 表示的类型
l或L后缀 long u或U后缀 unsigned int
ul后缀 (不区分大小写与顺序) unsigned long
ll\LL后缀 long long ull\Ull\uLL\ULL后缀 unsigned long long
(4)char类型:字符、小整数
①char 只有8位,常用于处理字符
▲cout将char类型数据打印为字符,int类型打印为整数。
例:char ch;cin>>ch;此时cout<<++ch;打印字符(++ch的值为char),而ch+1为整型
cout.put(ch);打印字符ch
▲必记ASCII码:”a”为97,”A”为65,“ ”(空格)为32
②转义序列:
基于八进制和十六进制的转义序列:如’\032’或’\0x1a’(Ctrl+Z)
*通用字符名:独立于任意的键盘,用于表示特殊字符
以\u或\U开头,\u后面为4个二进制位,\U后面为8个二进制位,其参照ISO 10646码点
可在标识符和字符串中使用通用字符名。
*signed char、unsigned char
char在默认情况下既不是没有符号,也不是有符号
*wchar_t(宽字符类型)
wcin和wcout可用于处理wchar_t流。前缀L指示宽字符常量和宽字符串
***C++11新增:char16_t和char32_t:都是无符号的,一个16位,一个32位。前缀u表示char16_t字符常量与字符串,前缀U表示char32_t字符常量与字符串。
(5)bool类型:变量值为true(非0)和false(0).true为真,false为假。
39. ▲const限定符:格式:
const 类型 变量名=值;
该限定符指明变量是只读的,在初始化之后不可修改(声明时就要初始化),const值可以用来声明数组值。
40. 浮点数:带有小数部分的数字。
(1)表示法:①常规表示法:即使小数部分为0也视作浮点数
②E表示法(类似于科学计数法,E或e都可以视作E表示法)
3.54E6表示
,6叫做指数,3.54叫做尾数。
(2)
浮点类型:float、double、long double:
有效位是数字中有意义的位,float至少32位,double至少48位,不少于float,long double为80~96~128位。指数范围至少为-37~37.在cfloat中有。如下:
// the following are the minimum number of significant digits
#define DBL_DIG 15 // double
#define FLT_DIG 6 // float
#define LDBL_DIG 18 // long double
// the following are the number of bits used to represent the mantissa
#define DBL_MANT_DIG 53
#define FLT_MANT_DIG 24
#define LDBL_MANT_DIG 64
// the following are the maximum and minimum exponent values
#define DBL_MAX_10_EXP +308
#define FLT_MAX_10_EXP +38
#define LDBL_MAX_10_EXP +4932
#define DBL_MIN_10_EXP -307
#define FLT_MIN_10_EXP -37
#define LDBL_MIN_10_EXP -4931
cout.setf(ios_base::fixed,ios_base_floatfield);防止程序把较大的值切换为E表示法。
通常cout会删除小数结尾的0.
(3)浮点常量:默认为double类型,f或F后缀表示float浮点常量,l或L后缀表示long double浮点常量。
->整数和浮点数统称算术类型
四、算数运算
41. 算术运算符二元:加法、减法、乘法、除法、取模(取余)一元:正号、负号(相反数)
二元:+运算符执行加法操作,-运算符执行减法操作,*运算符执行乘法操作,/运算符执行除法操作,%运算符执行取模操作。一元:+为正号,-为负号
·▲对于/运算符,若两个操作数都为整数,则结果为整数(丢弃小数位),如:5/2为2;若有一个操作数为浮点数,则结果也是浮点数。如5/2.0为2.5,5.0/2为2.5,5.0/2.0为2.5.
·▲对于%运算符,两个操作数必须为整数,如果其中一个是负数,则结果的符号应满足如下规则:(a/b)*b+a%b=a。
·▲运算符的优先级:改变优先级:加上括号,括号先算;* / %最优先,+ -其次,同级按先后顺序运算。在C++中,操作数的结合性是从左到右表示如果两个同级运算符被同时应用到一个操作数上时,首先应用左侧的运算符,从右到左则首先应用右边的运算符。
五、类型转换初步
▲42.类型转换:
*自动转换:
(i) 将一种算术类型的值赋给另一种算术类型的变量
(ii)表达式中包含不同的类型
(iii)将参数传递给函数
*转换会出现的问题:精度降低、小数部分丢失,超出目标类型取值范围,只复制右边的字节。
***C++11:以{}的方式初始化时进行的转换:
使用大括号的初始化叫做列表初始化。列表初始化不允许进行缩窄,即变量的类型无法表示赋给它的值。
·表达式的转换:
C++将bool、char、unsigned char、signed char、short转换为int(true为1,false为0)叫整型提升。在运算涉及两种类型时,较小的类型被转换为较大的类型。
·▲强制类型转换:(类型)表达式 或 类型(表达式)
static_cast<类型>(值) 较为严格的转换。
C++11的auto声明:auto 变量名=值;编译器会自动将变量的类型设置为与变量的初始值相同类型的类型。此为自动推断类型。
六、复合类型
▲43.数组:能存储多个同类型的值的数据结构。(类似于数学中的集合)
(1)声明:”元素类型 数组名[数组长度];”其中数组长度为整型常数或const值或常量表达式。
(2)使用元素:”数组名[下标(索引)]”C++的数组下标从0开始。该形式可以当作单个变量使用。
(3)
▲▲sizeof运算符:
计算类型或变量或数值占用的字节数。格式:
sizeof 类型名或变量或数值
如:sizeof int或sizeof(int)
(4)将sizeof用于数组名时,得到整个数组的占用字节(以下称为长度),用于元素时,返回元素的长度。
(5)数组初始化:只有定义时可以初始化,此后不可使用,不能将一个数组赋给另一个数组。
·格式:类型 数组名[数组长度]={初始化列表};初始化列表中的每个值以逗号分隔,并按照列表的顺序分别对每个元素初始化。如:
int arr[4]={1,2,3,4};其中a[0]初始化为1,a[1]初始化为2,依此类推。
·可以只初始化前几个元素,编译器将把其他元素设为0;
·把数组的元素都初始化为0:类型 数组名[数组长度]={0};此时显式把第一个元素初始化为0,其他元素自动设为0。
·如果初始化时方括号为空,编译器自动计算元素个数,如:short arr[]={1,2};
***C++11数组初始化方法:可将列表初始化用于任何类型,
·列表初始化可省略等号
·可不在大括号里包含任何内容
▲44.字符串
(1)定义:字符串是存储在内存的连续字节的一系列字符。
(2)C风格字符串(C-style string):来自C语言
·可以将字符串存储在char数组里
·C风格字符串以空字符结尾,写作\0,ASCII码为0.例:
char my_english_name[]={‘H’,’A’,’I’,’R’,’S’,’B’,’O’,’Y’,’\0’};
带有空字符的字符数组才是字符串
·许多处理字符串的函数都以空字符为结束的标志。
·初始化字符数组:可以使用字符串,即:字符类型 数组名[]=字符串常量;
字符串常量用引号引起,也叫字符串字面值。
如:char fruit[]=”apple”;或char fruit[6]=”apple”;
▲:注意’S’是字符,等价于ASCII码的83,”S”是字符串,它的值是它所在的地址。
·拼接字符串常量:两个字符串常量由空白分开,其将自动拼成一个。如:”114” “514”会自动合并为一个字符串。第二个字符串的首字符与第一个字符串的最后一个字符将会直接连在一起。
·使用字符串:
计算字符串的长度:cstring中的strlen()用法:接受一个字符串(不一定是字符数组的长度,是数组中的字符串的字符数),计算可见的字符,不包括空字符。
·字符串的输入:cin>>字符数组名;
cin使用空白来确定字符串的结束位置。所以cin会一次只读取一个单词。输入多个单词会缓存在输入队列里,然后逐一被读取,也无法防止单词过长的问题。
▲每次读取一行的输入:都读取一行输入,直到到达换行符。
①cin.getline(字符数组名,字符数(字符数组长度))
本函数丢弃换行符,用空值字符替代,接受两个参数,此处的字符数包括了空值字符,若参数为20,则最多读取19个字符。在读取指定数目字符或遇到换行符时停止读取。
②.cin.get(字符数组名,字符数(字符数组长度))
将换行符留在输入队列中,其他的与cin.getline()相似
③cin.get()和cin.getline()都返回cin对象的引用,便可再次调用其他方法。当get()读取空行时设置失效位(failbit),如果输入字符数较多,余下的字符留在输入队列中,getline()设置失效位。
·混合输入面向行的数字和字符串:在输入数字后,换行符被保留,需要自行丢弃。
常规的cin输入返回cin对象的引用。如cin>>year;返回istream&类型(即cin对象的引用)。
(3)string的初识
·头文件:string
·名称空间:std
·初始化的方式与字符数组相同,允许使用列表初始化(C++11)。
·赋值、拼接和附加:
①可以直接把string对象赋给另一个string对象。
②可使用+运算符把两个string对象相加。可以把字符(串)与string对象合并。即:
string+string,string+char*,char*+string,char+string,string+char的组合。只要保证其中有一个操作数为string对象即可。
·C风格字符串的操作:头文件cstring中的函数,用法如下:
strcpy(目标,源字符串)复制字符串,
strcat(目标,源字符串)附加一个字符串到另一个字符串末尾。
strncat()、strncpy()前两个参数,第三个参数还要指出最大复制多少字符,更安全
·.size()和.length()表示对象的长度,没有被初始化时,长度为0
·string的I/O:可使用cin和cout来输入输出string对象。
输入string:getline(istream对象,string对象);在使用该函数时,可以这么使用:
getline(cin,string对象);
(4)原始字符串(C++11)
在原始字符串中,字符串表示的就是自己,\n在原始字符串中不是换行符,可在字符串中使用”。原始字符串以 ”( 和 )” 来作为界定,并使用前缀R。也可以在” 和 ( 之间添加其他字符,结尾的)和“也是如此。前缀可以混合使用。

▲▲45.结构体
·声明结构体:
struct 结构体所代表的类型名
{
结构体成员(用分号分隔)
};
对于结构来说,声明结构体相当于创建自己的类型。所以可以创建结构变量。
·声明结构变量:类型名称 变量名={初始化列表}; 或 类型名称 变量名;
在声明结构变量时不用像C语言一样去在类型名前加上struct关键字。
·访问成员:使用成员运算符. 访问成员。即 结构变量名.成员
该形式可赋值或修改。
▲在main()外声明结构(外部声明)有所有的函数共享,内部声明只能被内部的函数使用。
·初始化方式:
类型名 结构变量名=
{
成员1的值,
成员2的值,
……
成员n的值
};
·C++11结构初始化:支持列表初始化器,可省略=,空的括号把每个成员设为0.
·其他:▲可以将结构变量赋给同一类型的结构变量,这样每个成员都一样,叫成员赋值。可以同时完成定义结构与变量的工作:
还可以声明没有名称的结构,方法是省略名称,同时定义一个结构类型和一个这种类型的变量。
结构还可以有成员函数。
*结构位字段:C++允许指定占用特定位数的结构成员。
~46.共用体(联合)
·能够存储不同的数据类型,但只能同时存储其中的一种类型,句法与结构类似。
声明格式:
union 联合类型名
{
成员
}
共用体的长度为其最大成员的值。与结构一样,也可以有匿名共用体。在上面的声明中,id_num和id_char被视为prize的两个成员。
▲47.枚举
·格式 enum 枚举类型名{符号常量(枚举量)};
如:enum spectrum {red, orange, yellow, green, blue, violet, indigo, ultraviolet};
枚举量的的值从0开始,依次递增。
·枚举变量的声明:枚举类型名 枚举变量;
在不进行强制类型转换时,只能将定义枚举时的枚举量赋给这种枚举类型的变量。
枚举只定义了赋值运算符。可以提升为int。
·设定枚举量的值:使用赋值运算符:enum bits{one = 1, two = 2, four = 4, eight = 8};
·取值范围:比最大枚举值大且相近的2的幂减去1,否则采用与寻找上限相同的方法并加上负号。
▲▲▲▲48.指针
·概念:存储地址的变量或常量,&为取地址符,用法: &变量名
·声明:指向的类型* 指针名=地址; 或 指向的类型* 指针名;
·解除引用:取得指针所指向的值,用法 *地址 其效果相当于使用原变量。
·空指针:值为0的指针,标准库中有符号常量NULL来表示(C++11用关键字nullptr表示)
·显示地址时,cout以十六进制表示法显示。提醒:int *m强调*m为int变量,int* m强调m为int*变量。(以后用int*表示指向int的指针)int* p1,p2;会创建一个指针和一个变量,指针变量的长度一致。
警告:在解除引用指针前,要先初始化指针!!!
·▲▲动态分配内存
①.方法: 指针=new 要分配的类型;
new运算符会根据要分配的类型寻找内存,并把内存地址返回给指针。(在老的实现里,内存不足会返回空指针,新的实现可能引发异常)
释放内存: delete 指针;
注意:一定要把new和delete配对使用!!!!否者会发生内存泄露。delete释放指针指向的内存,不删除指针。不能尝试释放已经释放的内存块,这是未定义行为。
内存泄露:指因内存管理不当导致内存并未回收且无法被利用。
只能用delete来释放new分配的内存,对于空指针运用delete是安全的。
②.动态数组
(i)在编译时给数组分配内存叫静态联编(static binding)
(ii)在程序运行时选择数组的长度,叫动态联编(dynamic binding),创建的数组叫动态数组
(iii)创建方法: 指针=new 要分配的类型[元素类型];
返回首元素的地址
释放: delete[] 指针;
注意:new[]与delete[]配对使用!!!!
可以把指针当作数组名,如*arr等价于arr[0]。依此类推。
C与C++的数组与指针基本等价,其内部使用指针访问数组
·指针、数组、指针算术
将指针变量加一后,增加的量相当于它指向的类型的字节数。如_Type*的变量加一,指向地址向后偏移sizeof(_Type)。此处的_Type表示任意类型。
C和C++将数组名解释为地址。数组名的地址为数组首元素的地址。
▲如果a是数组,N是整数,则 *(a+N)等价于a[N],所以*a等价于a[0]


▲对数组名使用sizeof得到数组的大小,而对指针使用sizeof则为指针的大小,此时数组名不被视为地址。
▲▲易错点:对数组名取地址时,数组名不会解释为地址,而是得到整个数组的地址,如下:
short tell[10];//tell和&tell的指向地址一致。
此时tell(或说&tell[0])是两字节内存块的地址,对其加一后指针向后偏移两字节,而&tell是一块20个字节的内存块,在加一后该指针向后偏移20字节。即tell是short&。而&tell是short(*)[10]。可以这样声明:short (*pas)[10]=&tell;省略括号pas会先与[10]结合,导致pas是一个指针数组。(可以理解为*pas是一个数组,有括号先算括号)
指针算术还可以获得两个指针的差,获得一个整数,是中间间隔的元素个数。
·当给cout提供一个字符指针时,cout会从所给地址上的字符开始打印,直到遇到空字符。
字符数组和字符串常量都是一个地址,指向第一个字符。
·strcpy(目标,源字符串)复制字符串。
·new[]的括号中可以使用变量
·指向结构变量和对象的指针、使用new创建动态结构
箭头成员运算符:访问指针里的对象的成员,用法:
指针->成员 等价于 *(指针).成员
·存储与堆栈
(i)自动存储:在函数内部定义的常规变量使用自动存储空间,被称为自动变量。他们在所属的函数被调用时自动产生,在函数结束时消失。
(ii)静态存储:在整个程序执行的期间都存在的存储方式,创建静态变量的方式:在函数外面定义它;在函数内部使用关键字static。
(iii)动态存储:new和delete管理了内存池,叫自由存储空间(FREE STORE)或堆(HEAP),与静态变量和其他变量分开。
·类型结合:创建指针数组Type_name* ptr_arr[LENGTH]
49. 标准模板类初始
array、vector
·名称空间:std
·头文件名:array、vector
·声明的格式:
std::vector<元素类型> 名称(元素个数(可为变量));
atd::array<类型,元素个数(不可变)> 名称;
·在C++11中,可使用列表初始化器初始化他们,可将一个对象赋给同类型对象
·成员函数:.at(下标) 可以在运行期间捕获非法索引,时间更长。
第一部分总结
1. C++的特性:是一门面向对象的编译型编程语言,支持过程化程序设计、面向对象程序设计和泛型程序设计。
2. C++语言的基本模块是函数
3. sizeof运算符返回类型或变量或数值占用的字节数
4.cout.setf(ios_base::fixed,ios_base_floatfield);防止程序把较大的值切换为E表示法。
通常cout会删除小数结尾的0.
5.字符串的输入输出
方法 | 说明 |
std::cin>>字符数组; | 使用空白来确定字符串的结束位置,一次只读取一个单词。多余的在输入队列中,然后被逐一读取 |
cin.getline(字符数组名,字符数(字符数组长度)) | 读取一行输入,直到到达换行符。丢弃换行符,用空值字符替代。在读取指定数目字符或遇到换行符时停止读取。 如果输入字符数较多,余下的字符留在输入队列中,getline()设置失效位。 |
cin.get(字符数组名,字符数(字符数组长度)) | 读取一行输入,直到到达换行符。将换行符留在输入队列中。 读取空行时设置失效位(failbit) |
cin.get()和cin.getline()都返回cin对象的引用,便可再次调用其他方法。
6.混合输入面向行的数字和字符串:在输入数字后,换行符被保留,需要自行丢弃。
7.常规的cin输入返回cin对象的引用。
8.string
·头文件:string
·名称空间:std
·初始化的方式与字符数组相同,允许使用列表初始化(C++11)。
·赋值、拼接和附加:
方法 | 说明 |
string::operator=() | 把一个string对象赋给另一个string对象。 |
string::operator+() | 两个string对象相加,字符(串)与string对象合并。 其中有一个操作数为string对象 |
string::size() string::length() | 返回长度。没有被初始化时,长度为0 |
·string的I/O:输入string:getline(istream对象,string对象);
9. C风格字符串的操作
·头文件cstring(来自C)
·常用方法
strcpy(目标,源字符串) 复制字符串,
strcat(目标,源字符串) 附加一个字符串到另一个字符串末尾。
strncat()、strncpy()前两个参数同上,第三个参数指出最大复制多少字符
