学习《C++ Primer Plus》05

复合类型

第一部分:数组、字符串、结构体、共用体和枚举

1.数组

数组是一种数据格式,能够存储多个同类型的值。每个值都存储在一个独立的数组元素中,计算机在内存中依次存储数组的各个元素。要创建数组,可使用声明语句。数组声明应指出以下三点:

  1. 存储在每个元素中的值的类型;
  2. 数组名;
  3. 数组中的元素数。

e.g. short months[12];  //create array of 12short

通用类型:

typeName arrayName[arraySize];

arraySize指定元素数目,它必须是整型常数或const值,也可以是常量表达式,即其中所有值在编译时都是已知的。具体地说,arraySize不能是变量,变量的值是在程序运行时设置的。必须保证有效的下标值,上诉months[14],编译时不会指出错误,但是程序运行时后,这种赋值可能引发问题。

作为复合类型的数组:

数组之所以被称为复合类型,是因为它是使用其他类型来创建的。不能仅仅将某种东西声明为数组,它必须是某种特定类型的数组。

数组元素赋值和初始化:

int yams[3];

    yams[0] = 1;

    yams[1] = 2;

    yams[3] = 3;

 

int yamcost[3] = { 2,4,6 };

 

C++允许在声明语句中初始化数组元素;只有在定义数组时才能够使用初始化,以后就不能使用了,也不能将一个数组赋给另一个数组;提供的值可以少于数组元素的个数;如果只对一部分元素初始化,则编译器将其余元素设为0(int a[100]={0};即初始化全部元素为0);如果初始化数组时方括号[]为空,编译器将计算元素个数,但不推荐,一般对于初始化一个字符串比较安全。

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

    int num_elemwnts = sizeof things / sizeof(short);

sizeof()运算符返回类型或数据的长度,如果将sizeof()用于数组名,得到的是整个数组中的字节数,若用于数组元素,得到的是元素的长度(字节)。

C++11中的列表初始化新增了一些功能:

  1. 初始化数组时,可省略=;
  2. 可以不在大括号内包含任何东西,这将把所有元素初始化为0;
  3. 列表初始化禁止缩窄转换。

 

2.字符串

1)C-风格的字符串

存储在连续字节中的一系列字符意味着可以将字符串存储在char数组中,其中每个字符位于自己的数组元素中。

C-风格字符串具有一种特殊的性质,以空字符结尾,空字符被写作“\0”,其ASCII码为0,用来标记字符串的结尾。

    char dog1[8] = { 'b','e','a','u','t','y','D','\0' };

    char dog2[8] = { 'b','e','a','u','t','y','D','D' };

    char bird[11] = "Mr. Cheese";

char fish[] = "Bubbles";

dog1是字符串,dog2不是。这两个数组都是char数组。将数组初始化为字符串冗长乏味,还有一种方法,只需一个引号,这种字符串称为字符串常量或字符串字面值。引号括起的字符串隐式地包括结尾的空字符,因此不用显式包括它。

警告:在确定存储字符串所需的最短数组时,别忘了将结尾的空字符计算在内!

    char shirt_size = "s";

“s”不是字符常量,它表示的是两个字符(字符s和\0)组成的字符串;更糟糕的是,s”实际上表示的是字符串所在的内存地址。因此该语句试图将一个地址赋给shirt_size,由于地址是一种独立的类型,因此C++不允许这种不合理的做法。

拼接字符常量:

    cout << "I'd like to be a" "good person.\n";

任何两个由空白(空格、制表符和换行符)分隔的字符串常量都将自动拼接成一个,拼接时不会在被连接的字符串之间添加空格。

要将字符串存储在数组中,最常用的方法有两种:将数组初始化为字符串;将键盘或文件输入读入到数组中,。

标准头文件cstring提供函数strlen(),返回存储在数组中字符串的长度,而不是数组本身的长度。另外,strlen()只计算可见的字符(空格是可见的字符!),而不把空字符计算在内。数组的长度不能短于strlen()+1。

cin使用空白(空格、制表符和换行符)来确定字符串的结束位置;cout是到空字符\0’处截至,注意区分这两者

如何每次读取一行字符串输入:

getline()和get();这两个函数读取一行,直到到达换行符。然而,随后getline()将丢弃换行符,而get()将换行符保留在输入序列中。

#include<iostream>

int main()

{

    using namespace std;

    const int ArSize = 20;

    char name[ArSize];

    char dessert[ArSize];

 

    cout << "Enter your name:\n";

    cin.get(name, ArSize).get();

    cout << "Enter your favorite dessert:\n";

    cin.getline(dessert, ArSize);

    cout << "I have some decious " << dessert    //加空格的艺术

        << " for you:" << name<<".\n";

    cin.get();

    return 0;

}

警告:混合输入数字和面向行的字符串时会导致问题,先输入数字后,将回车键生成的换行符留在了输入队列。在输入数字语句后需加cin.get();

可以将调用拼接起来:

例如:(cin>>year).get();

 

2)基于string类

要使用string类,必须在程序中包含头文件string,string类位于命名空间std中。可以用string类型的变量(使用C++)的话说是对象而不是字符数组来存储字符串。

在很多方面,使用string对象的方式与使用字符数组相同:

  1. 可以使用C-风格字符串来初始化string对象;
  2. 可以使用cin来将键盘输入存储到string对象中;
  3. 可以使用cout来显示string对象;
  4. 可以使用数组表示法来访问存储在string对象中的字符。

两者主要区别就是,可以将string变量声明为简单变量,而不是数组。

从理论上说,可以将char数组视为一组用于存储一个字符串的char存储单元,而string类变量是一个表示字符串的实体。

类设计让程序能够自动处理string的大小。

赋值、拼接和附加:

可以将一个string对象赋给另一个string对象;

可以运用+将两个string对象合并起来,还可以使用+=将字符串附加到string对象的末尾:

string str1, str2, str3;

    str3 = str1 + str2; // assign str3 the joined string

str1 += str2;       // add str2 to the end of str1 str1=str1+str2

确定字符串中字符数的方法:

string str1;

    char charr[20];

    int len1 = str1.size();

int len2 = strlen(charr);

函数strlen()是一个常规函数,它接受一个C-风格字符串作为参数,并返回该字符串包含的的字符数。函数size()的基本功能与此相同,但句法不同。str1不是被用作函数参数而是位于函数名之前,它们之间用句点连接,这种句法表面str1是一个对象而size()是一个类方法,方法是一个函数,只能通过其所属类的对象进行调用。C函数使用函数参数来指出要使用哪个字符串,而C++string类对象使用对象名和句点运算符来指出要使用哪个字符串。

string类I/O:

可以使用cin和运算符<<来将输入存储到string对象中,使用cout和运算符<<来输出string对象,其句法与处理C-风格字符串相同。但每次读取一行而不是一个单词时,使用的句法不同

#include<iostream>

#include<string>

#include<cstring>

using namespace std;

 

int main()

{

    char charr[20];

    string str;

 

    cout << "Length of string in charr before input:"

        << strlen(charr) << endl;

    cout<<"Length of string in charr before input:"

        << str.size() << endl;

    cout << "Enter a line of text:\n";

    cin.getline(charr, 20);  //indicate maximum length

    cout << "You entered: " << charr << endl;

    cout << "Enter another line of text:\n";

    getline(cin, str);       //cin now an argument; no length spcifier

    cout << "You entered: " << str << endl;

    cout << "Length of string in charr before input:"

        << strlen(charr) << endl;

    cout << "Length of string in str before input:"

        << str.size() << endl;

    cin.get();

    return 0;

}

 

    cin.getline(charr, 20);

该句点表示法表明:函数getline()时istreasm类的一个类方法;

getline(cin, str); 

这个getline将cin作为参数,C++的istream类初始没有考虑string类型,所以有处理double、int和其他基本类型的的类方法,但没有处理string类的类方法。

cin>>str;  // read a word into the str string object

前面处理string对象的代码使用string类的一个友元函数。

可了解C++新增的原始字符串,可将\n,”等直接显示出来。

 

3.结构简介

结构是用户定义的类型,而结构声明定义了这种类型的数据属性。创建结构包括两步,首先,定义结构描述—它标记了能够存储在结构中的各种数据类型。然后按描述创建结构变量(结构数据对象)。

下面举一个例子:

关键字struct表面这些代码定义的是一个结构的布局。标识符inflatable是这种数据格式的名称:

struct inflatable  //structure declaration

    {

        char name[200];

        float volume;

        double price;

    };

其中每个列表项都是一条声明语句。结构声明最好放在main()的前面,外部声明可以被其后面任何函数使用,而内部声明只能被该声明所属的函数使用。

初始化:

inflatable guest =

    {

        "Heidi Lee",

        1.88,

        29.9

    };

C++11:

支持列表初始化用于结构,而且=号可以省略;其次如果大括号内未包含任何东西,各个成员都被设置为0.

可以使用赋值运算符=将结构赋给另一个同类型的结构,这样结构中每个成员都被设置为另一个结构中相应成员的值,即使成员是数组

可以同时完成定义结构和创建结构变量的工作:

struct inflatable  //structure declaration

    {

        char name[200];

        float volume;

        double price;

    }mr_join,mr_smith;

甚至可以初始化这种方式创建的变量。还可以声明没有名称的结构类型。

    了解结构数组。注意变量名称本身是一个数组。

 

4.共用体

共用体是一种数据格式,能够存储不同的数据类型,但只能同时存储其中一种类型。也就是说,结构体可以同时存储int,double,共用体只能存储int或double。

匿名共用体没有名称,其成员将成为位于相同地址处的变量。

 

5.枚举

C++的enum工具提供了另一种创建符号常量的方式,这种方式可以代替const。它还允许定义新类型,但必须按严格的限制进行。使用enum的句法与使用结构相似。

对于枚举,只定义了赋值运算符。

 

 

 

猜你喜欢

转载自blog.csdn.net/ly_222222/article/details/81147106