C++ Primer Plus学习:第四章

C++入门第四章:复合类型

1 数组

数组(array)是一种数据格式,能够存储多个同类型的值。

使用数组前,首先要声明。声明包括三个方面:

  • 存储每个元素中值的类型
  • 数组名
  • 数组中的元素个数

声明的通用风格如下:

typename arrayname[arrysize];

注;arrysize指定元素数目,必须是整型常量,不能是变量。

数组的很多用途均基于这样一个事实:可以单独访问数组元素。方法是使用下表或索引对元素进行编号。C++数组从0开始编号,并使用带索引的方括号表示法来指定数组元素。

注:编译器不会检查使用的下表是否有效,所以确保有效的下标值非常重要。

数组的初始化规则

只有在定义时才能使用,以后就不能用了,也不能将一个数组赋值给另一个数组。

int cards[4]={3,6,8,10};

初始化时提供的值可以少于元素数目。如果只对数组的一部分进行初始化,则编译器将其他元素设置为0。

如果初始化数组的时候方括号内为空,编译器将计算元素的个数。如:

short a[]={1,2,3,4};

编译器使a数组包含4个元素。

注:让编译器去计算数组大小是很糟糕的事情。

C++11数组初始化方法

首先,初始化时能够省略等于号。

int a[2]{1,2};

其次,不必在大括号内包含任何东西,这将把所有元素全部置0。

int b[10]={};

第三,列表初始化禁止缩窄。

long c={1.0,2.0,4} //不允许

2 字符串

字符串是存储在内存的连续字节中的一系列字符。

C++使用两种方法处理字符串。一种是C风格字符串,另种是基于string类的方法。

C-风格字符串以空字符作为字符串的结尾。

例:char c1={‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘}; //不是字符串

char c2={‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘\0‘}; //字符串

cout打印字符串碰到\0后停止。

C++中另一种初始化字符串的方法:双引号。

char c3[11]="C++ language.";

char c4[]="C++ language.";

在这时,让编译器自己计算字符串长度显得更安全。

注意,字符串常量(双引号)和字符常量(单引号)不能够互换。

字符串的返回值是首字母的地址。

拼接字符串:cout<<"a" "b";

字符串的输入输出

cin使用空白(空格、制表符和换行符)来确定字符串的结束位置。这意味着cin每次仅能读取一个单词。

每次读取一行字符串输入

  • 面向行的输入:getline()

getline()函数读取整行,它使用通过回车键输入的换行符来确定输入结尾。使用cin.getline()来调用此种方法。函数有两个参数:第一个参数用来存储输入行的数组名称,第二个参数为要读取的字符数。最多读取数为该数字减1(最后一个存储\0)。此函数在读取指定字符或者遇到换行符时自动停止读取。

例:cin.getline(name,20),最多包涵19个字符。

此函数自动忽略换行符。

  • 面向行的输入:get()

基本用法与getline()相同,但是此函数不丢弃换行符。

例:cin.get(name,20)

cin.get()可自动读取下一字符。

另:类成员拼接:

cin.get(name1,20).get();

或:cin.getline(name1,20).getline(name2.20);

空行输入

get()遇到空行时会设置失效位使输入阻断。

使用cin.clear();可删除失效位,恢复输入。

和溢出会产生问题。

字母数字混合输入的问题:

cin>>year;

cin.get();

3 string类简介

C++98标准通过添加string类扩展了C++库,因此现在可以使用string类型的变量(C++中的对象)而不是字符数组来存储字符串。

要使用string类,必须使用名称空间std并且包含头文件string。

string的方式:

  • 可以使用C语言风格来初始化string变量。
  • 可以使用cin将键盘输入存储到string对象中。
  • 可以使用cout来显示string对象。
  • 可以使用数组表达式法来访问存储在string中的字符。

getline(cin,str);

string类将字符串声明为一个简单变量。

程序能够自动处理string的大小。

string类简化了字符串的合并操作。使用"+"可以实现字符串合并,使用"+="可实现在一字符串后添加字符串。

str1.size()返回字符串str1的长度,size()为一个类方法。

其他形式的字符串字面值

C++还有类型wchar_t,C++11新增了类型char16_t、char32_t。C++使用前缀L、u和U表示。

例:wchar_t a[]=L"abcd";

char16_t a[]=u"abcd";

char32_t a[]=U"abcd";

C++新增了一种字符串类型:原始字符串(raw)。在原始字符串中,字符表示的就是自己。例如序列\n表示的就是\和n而不是换行符。

例:cout<<R"ab "c",\n"<<endl; 显示为:ab "c",\n

cout<<R"+*(abc(abc)"a"\n.)*+"; 显示为:abc(abc)"a"\n.

即:使用R"";可在其中加\和双引号。使用R"+*()*+"可显示加\、双引号和括号。

  • 结构简介

结构是一种比数组更灵活的数据格式,统一结构可以存储不同类型的数据。结构是C++OOP编程的基石。

结构定义:

struct structname

{

datatype1 name;

……..

}

结构声明与使用:

C语言形式:struct structname a

C++形式:structname a

C++声明结构变量时可以省略struct

变量声明在函数内,结构声明在函数外。

变量初始化的方式:

例:已定义了一个结构变量student(包含姓名、学号和姓名)。则可通过如下方式初始化:

student a={"Tom",123456,20}或

student a {"Tom",123456,20}

即由逗号分隔值列表,并将这些值用花括号括起。在程序中,每个值可以个占一行,也可以全部放在同一行。赋值符号可以省略。

初始化时大括号内可以为空,此时全置为0,如果有未初始化的成员,置为0。

最后,不允许缩窄变换。

其他结构属性

可以将结构作为参数传递给函数,也可以让函数返回一个结构。可将一个结构赋给另一个结构。

结构数组

结构体变量也可组成数组,例:(struct) student a[100];引用方式:a[1].name。

初始化方式:

student a[2]=

{

{"Tom",20110601,20},

{"Jack",20110602,20}

};

当中都要使用逗号分隔。

  • 共用体

共用体是一种数据格式,可以存储不同的数据类型,但只能同时存储其中的一种类型。

例:union student

{ char name[20];

int number;

int age;

};

每个时刻共用体只能存储一个值。

匿名共用体:

例:struct student

{ char name[20];

union

{ int id1;

int id2;

};

}a;

可使用a.id1引用结构体中的id1。

  • 枚举

enum工具提供了另一种创建符号常量的方式。使用方法与结构体类似。

例:enum day {Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};其中,Sunday=0,Monday=1,以此类推。

上面定义的Sunday等是符号常量,又被称为枚举量。

枚举量有一些特殊属性:

  • 在不进行强制类型转换的时候,只能将定义枚举时使用的枚举量赋给这种枚举的变量。例:

enum day;

day a;

a=Sunday; //正确

a=0; //不正确,非枚举量

  • 可通过强制类型转换进行赋值。例:

a=day(1);但是a=day(10)是错误的。

若只是使用枚举量创建常量,可直接使用以下语句定义:enum {a,b,c,d};省略枚举类型的名称。

设置枚举量的值

enum bit{one=1,two=2,four=4};

其中,指定的值必须为整数。

enum num{a=1,b,c=9,d}; b=2,d=10;

枚举值的取值范围

取值范围的定义:首先找出枚举值中最大的数。在2的幂中,找到比这个数大的最小值,然后减1即为上限。(如:枚举中的最大值为101,则上限为2^7-1=127)。如果最小值不小于零,下限为0,否则,与上限同理。

  • 指针和自由存储空间

指针是一个变量,其存储的是值的地址,而不是值本身。

对于常规变量,应用地址运算符(&),就可以获得它的位置。比如home为一变量,&home,就是变量的地址。

使用常规变量时,值是指定的量,地址为派生量。而指针将地址视为指定的量,而将值视为派生量。指针名表示的是地址,*运算符被称为间接值或解除引用运算符,将其运用于指针,可以得到该地址处存储的值。

一般计算机使用16进制表述指针,也有十进制的。

指针的声明

例:int *p_updates;其中,p_updates为地址。

传统C语言初始化方式:int *p;

C++方式:int* p;表示int* 为一种指向int类型的指针。

甚至也可以这样:int*p;

注:对每个指针变量名,都必须使用*,即int* p1,p2;其中p2为一个int型变量。

指针的危险

在C++中创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。为数据提供空间是一个独立的步骤。

例:long *a;*a=233333;

上述代码并没有将地址赋给a,233333将放在哪里呢?我们不知道,a指向的地方并不是233333的地址。所以一定要在指针使用*之前初始化它。

指针和数字

指针不是整型,但是计算机通常把指针当做整型变量来存储。指针不能进行乘的运算,不能将整数赋给指针。如:

int *p;p=0xB8000000;

但是可以通过强制类型转换赋值。即:

int *p;p=(int *) 0xB8000000;

使用new来分配内存

int *pnew=new int;

new运算符实现了在运行阶段为int值分配未命名的存储空间,并通过指针来访问这个值。

如果使用的是:int a;int *pt=&a;则可使用a来访问该值,而使用new只能够使用指针访问该值。

我们称pnew指向的是一个"数据对象"。处理数据对象的指针方法可能不一定好用,但是这在管理内存方面有更大的控制权。

为一个数据对象(基本类型或者结构)获得并指定分配内存的方法:

typename *pointer_name=new typeName;

使用举例:

int *pn=new int;

*pn=1001;

使用delete释放内存

使用delete释放new分配的内存。

例:int *pn=new int;

delete pn;

但是这并不是意味着删除指针pn本身,删除的只是pn指向的内存块而已。

new和delete应该成对使用,否则会出现内存泄露的情况。

使用new来创建动态数组

使用声明来创建一个数组,在编译时给它分配内存空间,属于静态联编,使用new来创建数组,在运行时分配空间,属于动态联编。

例:int *pn=new int [10]; //创建动态数组

delete [] pn; //删除动态数组

上面的pn指向数组中的第一个值。

即:

type_name *pointor_name=new type_name [num_elem];

其中,num_elem可以是整型常量或者变量。

使用动态数组的方法:

以上面的pn为例,可使用pn[0]……pn[9]访问数组元素。也可使用*(pn+1)进行访问。

  • 指针、数组和指针算数

指针和数组基本等价的原因在于指针算术和C++内部处理的方式。C++将数组名作为指针,且为常量。

将指针变量加1后,增加的值等于指向类型占用的字节数。

注:数组名代表数组第一个值的地址,&数组名代表整个数组的地址。

指针和字符串

例:char a[20]="name";

我们可以认为a是字符串第一字符‘n‘的地址。如果使用cout输出的话,从‘n‘开始输出,知道碰到\0结束。

注:在cout和多数C++表达式中,char 数组名、char 指针以及使用引号括起来的字符串常量都被解释为字符串第一个字符的地址。

字符串的字面值是常量。

注:在将字符串读入程序时,应使用已分配的内存地址。该地址可以是数组名、也可以是使用new初始化过的指针。但不可使用字符串常量和为被初始化过的指针来接受输入。

一般来说,如果给cout提供一个指针,他将打印指针。但如果指针的类型为char *,cout将显示字符串,如果要显示地址,必须使用强制类型转换,如:(int *)字符指针。

例:char a[20]="an animal";

char *ps=new char[strlen(a)+1];

strcpy(ps,a);

注:上面的程序中不能使用ps=a;否则ps分配的内存将无法使用。

另:strcpy(a,b);//a:目标地址,b:源地址

如果b的长度比a定义的长,则会继续复制。

strncpy(a,b,n);//a:目标地址,b:源地址,n:长度

使用new创建动态结构

首先定义一个结构

struct student

{

char name[10];

int num;

int age;

};

student *ps=new student;

此时,要使用"->"运算符引用结构中的元素。(也可以使用(*ps).num引用)。

自动存储、静态存储和动态存储

根据分配内存的方式,C++有三种管理数据内存的方式:自动存储、静态存储和动态存储。C++11新增了一种:线程存储。

  1. 自动存储

函数内部定义的常规变量使用自动存储空间,被称为自动变量。函数调用时产生,函数结束时消亡。

自动变量为一局部变量,作用域为代码块(花括号中的一段代码)。

自动变量存储在栈中。

  1. 静态存储

整个程序执行期间都存在的变量,使用static声明。

3,动态存储

new和delete提供的方式。

  • 类型组合

本章介绍的数据类型可以组合

struct student

{ char name[20];

int num;

int age;

}

现在声明一个变量:

student Tom;

可使用Tom.age访问结构中的成员。

若 student * ptom=&Tom;

则使用ptom->age访问。

若声明一个数组:student s[3];

s[0].age 访问成员

(s+1)->age 访问其成员

同时可创建指针数组:

const student *pp[3]={&s[1],&s[2],&s[3]};

访问成员方法:

std::cout<<pp[1]->age<<std::endl;

可创建指向指针的指针:

const student **ppp=pp;

C++11中也可写成:const student ppp=pp;

  • 数组的替代品

  • 模板类vector

模板类vector类似于string类,也是一种动态数组。可在运行阶段设置vector的长度,可在末尾附加新数据。

  • 使用模板应包含头文件vector
  • vector包含在名称空间std中
  • 模板使用不同的语法来指出存储的数据类型
  • vector使用不同的语法来指定元素数

例:#include<vector>

using namespace std;

vector<int> vi;

int n;

cin>>n;

vector<double> vd(n);

声明vector对象的方法:

vector<typename> vt(n_elem);

其中n_elem可以是整型常量或者变量,省略则默认为0。

2 模板类array

C++11中提供的新类型,固定长度的数组,但是比普通数组更方便和安全。

例:

#include<array>

using namespace std;

array<int,5> ai;

array<double,4> ad={1.1,1.2,1.3,1.4,1.5};

声明方式:

array<typename,n_elem> arr;

其中n_elem必须是整型常量

总结

array和数组存放在栈中,vector存储在自由存储区或者堆中。

array对象可以整个赋值。

例:

array<double,4> a1={1.1,1.2,1.3,1.4,1.5};

array<double,4> a2;

a2=a1;是合法的。

a1[-2]=199;是合法的。

即*(a1-2)=199;

但是会产生意想不到的错误。

vector和array避免此类错误的方法:

a1.at(1);

如果它捕获非法索引,则中断程序。

总结

数组、结构和指针是C++中的3种复合类型。

数组可以在一个数据对象中存储多个同类型的数据。通过索引和下标访问。

结构可将多个不同类型的值存放在同一数据对象中。使用成员关系运算符(.)来访问其中的成员。

共用体只能存储一个值。

指针使用来存储地址的变量。new运算符允许程序运行时为数据对象提供内存,返回获得的内存地址。

C++98新增的标准模板库(STL)提供了模板类vector。

时间: 2024-09-29 01:48:08

C++ Primer Plus学习:第四章的相关文章

学习第四章Android移植环境搭建心得体会

在第四章我先学习如何搭建嵌入式交叉开发环境,包括交叉编译环境,各种服务程序和应用程序的安装,配置和使用.驱动目标必须先做好Bootloder,操作系统内核及文件系统,介绍Bootloder的概念及U_boot的编译和移植的方法,在实践的过程中我了解了安卓系统下linux内核的相关知识,然后学会了内核编译和移植的方法. 安卓基于Linux操作系统,由硬件,系统内核,系统服务和应用程序四大部分组成.安卓内核和标准的Linux内核一样,主要实现内存管理,进程调度,进程间通信等功能.说到移植,就是把程序

汇编学习第四章

在第四章,通过前面的学习,我们已经了解了汇编语言的基本知识,现在我们开始学习编写汇编程序. (一)源程序   一个源程序从写出到执行需要三步: 编写:通过文本编辑器用汇编语言写出程序的文本文件 编译连接:通过汇编编译程序将文本文件编译成目标文件,再用连接程序连接,生成可执行文件 执行:即执行上一步生成的可执行文件 源程序中包含两种指令,一种是汇编指令,一种是伪指令.汇编指令是指可以被编译为机器指令的指令,由CPU执行,而伪指令没有对应机器码,由编译器执行. 源程序的基本格式: assume 段寄

Java基础知识二次学习--第四章 异常

第四章 异常处理 时间:2017年4月26日11:16:39~2017年4月26日11:28:58 章节:04章_01节 04章_02节 视频长度:20:46+01:16 内容:异常的概念 心得: Java异常是JAVA提供的用于处理程序中错误的一种机制 实在运行的过程中发生的一些异常事件(比如除0溢出,数组越界,要读取的文件不存在) 设计良好的程序应该在异常发生时提供处理这些错误的方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果 JAVA程序的执行过程中 如果出现异常事件,可以生成异

学习第四章与第五章的感悟

从第四章开始接触类与对象,了解类的定义,类包括标准类和用户自定义类,通常我们用的都是用户自定义类,在类中可以定义构造器,一个类中最少可以定义一个构造器,构造器与类同名,构造器有一个或多个参数,构造器没有返回值,伴随着new操作一起调用: 类具有三个特性:封装性.多态性.继承性:并且Java允许重载任何方法,不只是构造器方法,如果有多个方法,相同的名字,不同的参数,这样的方法叫做重载:如果在构造器中没有显式的赋初值,会给数值型默认赋值为0,对象引用为null,布尔为false. 在类的继承性中,子

tcp/ip协议学习 第四章 ARP:地址解析协议

派猴子来的救兵 关于ARP的RFC文档在此! ARP干嘛的 曾经有段时间, 六七年前了吧. 本科的时候, 流行了一阵子ARP病毒攻击, 导致整个局域网都不能上网了. 当时只听说这个东西防不住, 只要有一个人中毒, 就导致所有人上不了网. 现在也终于知道这是怎么回事了, 也能手工让某个同学上不了网了, 咳咳. 大家应该也都知道ARP是干嘛的, 我再啰嗦一下.. 比如我访问了百度, 百度回了包给我, 百度只知道我的IP是什么,不知道我的MAC地址. 这个包到网关的时候, IP这一层再把数据交给下一层

汇编语言学习第四章-第一个程序

本博文系列参考自<<汇编语言>>第三版,作者:王爽 前面的几章中我们断断续续的学习了一些指令,但是从来没有完整的通过汇编语言编写一个可执行文件即.exe文件.从本章开始我们将开始使用汇编语言并通过编译器编译链接一个完整的可执行文件. 4.1 一个源程序从写出到执行的过程 如下图所示,为一个完整的汇编程序到执行的过程: 上图的过程可以总结成以下几个步骤: (1) 根据汇编语言语法规则和目标程序工程编写汇编程序.这一步在文本编辑器或者在一些IDE中编写. (2) 通过汇编编译器将编写的

C++ Primer Plus学习:第二章

C++入门第二章:开始学习C++ 进入C++ 首先,以下是一个C++程序: //myfirst.cpp 显示一行文字 #include<iostream> //预处理器编译指令 int main() //函数头 { using namespace std; //编译指令 cout<<"学习C++"; //显示消息 cout<<endl; //开始下一行 cout<<"你不会后悔!"; //更多输出 return 0;

C++ Primer Plus学习:第一章

C++入门第一章:预备知识 C++简介 C++融合了三种不同的编程方式: C语言代表的过程性语言. C++在C语言基础上添加的类代表的面向对象语言. C++模板支持的泛型编程. C++简史 20世纪70年代贝尔实验室开发. C语言编程原理 计算机语言要处理两个概念:数据和算法. 数据是程序使用和处理的信息.算法是程序使用的方法. C语言为过程性(procedural)语言,强调编程的算法.过程化编程首先要确定计算机应采取的操作,然后使用编程语言实现这些操作. C语言具有结构化编程(structu

python爬虫学习第四章

html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption

网络学习第四章(交换机)

交换机就是多接口的网桥,网桥就是聪明的中继器.