C++

C++ plus6th 第4章 复合类型

2021-03-21  本文已影响0人  Leon_Geo

1.关于读取字符串

以上宽字符类型,分别冠以L、u、U前缀,后两种为C++11新增的,其使用如下:

wchar_t title[] = L"Chief Astrogator";
char16_t name[] = u"Felonia Ripova";
char32_t name[] = U"Humber Super";

C++11还支持Unicode字符编码方案UTF-8。使用u8前缀来表示该类型字符串字面值。

C++还支持原始字符串(raw)。原始字符串表示的就是自己,例如\n不再表示换行符,而是\和n本身。因此,原始字符串以R作为前缀,且使用 “( 和 )“ 表示字符串的起始和终止符。例如:

cout << R"(Jim "King" uses "\n" instead of endl.)" << '\n'

上述代码将输出:Jim "King" uses "\n" instead of endl.

而如果使用标准字符串字面值,将需要如下编码:

cout << "Jim \"King\" uses \"\\n\" instead of endl." << '\n'

如果在原始字符串中需要输入“( 和 )”时又该如何表达呢?此时你可以自定义定界符,只要满足“(或)”之间加入任意数量的除空格、左右括号、斜杠和制表符、换行符等控制字符之外的基本字符即可。例如“+-(和)+-”

在键盘上输入原始字符串时,按下回车键不仅会移到下一行,而且还会在原始字符串中添加回车字符。

可将前缀R与其它字符串前缀结合使用,例如Ru、UR等。

2.关于结构

struct inflatable   //结构体声明
{
    char name[20];  //或使用string类:   std::string name;
    float volume;
    double price;
};

struct inflatable goose;    //C风格,struct必须包含
balls goose;        //C++风格,struct可省略

与C一样,字段的类型应为整型或枚举,接下来是字段名(可选)和冒号,后面跟字段的位数,一般用以表示某寄存器结构。

struct torgle_register
{
    unsigned int SN : 4;    //4 bits for SN value
    unsigned int : 4;       //4 bits unused
    bool goodIn : 1;
    bool goodTorgle : 1;    
};

torgle_register tr = {14, true, false};

3.关于共同体

共同体一般用于对象可能是多种数据类型的情况,可以大大节省存储空间。例如商品id既可能是数字也可能是字符串:

struct widget
{
    char brand[20];
    int type;
    union id
    {
        long id_num;
        char id_char[20];
    }id_val;
};
...
widget prize;
...
if (prize.type == 1)
    cin >> prize.id_val.id_num;
else
     cin >> prize.id_val.id_char;

当然,也可以使用匿名共同体,此时上述程序可以改写为:

struct widget
{
    char brand[20];
    int type;
    union
    {
        long id_num;
        char id_char[20];
    };
};
...
widget prize;
...
if (prize.type == 1)
    cin >> prize.id_num;
else
     cin >> prize.id_char;

由于匿名,id_num和id_char被视为prize的两个成员,因为他们的地址相同,所以不需要使用中间标识符id_val。程序猿负责确定当前哪个成员是活动的。

4.关于枚举

enum提供了另一种创建符号常量的方式,这种方式可以代替const。其句法如下:

enum spectrum {red, orange, green, blue, violet, indigo, ultraviolet};

以上定义让spectrum成为新的类型名称,其定义的变量只允许赋大括号的值(red, orange等),默认情况下,依次赋值0,1,2…给red, orange等。当然,也可以显示的指定整数值来覆盖默认值。

枚举变量仅定义了赋值运算,其它运算符对其非法。

枚举变量是整型,可被提升赋值给int变量,但反过来结果未知。但如果int变量的值在枚举值范围内,则也是可以的,如定义了一个spectrum枚举变量band,如下句子合法:band = spectrum(3);

如果只使用枚举常量,而不创建枚举类型的变量,则可以省略枚举类型名称。

//默认依次从0增加,后者的值比前者的值加1.若前者显示赋值,则后者在前值基础上加1
enum bits {zero, null = 0, one, numero_uno = 1, two}; 
//zero = null =0; one = numero_uno = 1,two = 2.

C++通过强制类型转换,可以将在枚举变量取值范围内的整数合法的赋给枚举变量。这个范围是:上限是枚举变量最大值向上取2的幂整减去1,下限是0或者负数的向下取2的幂整加1.

enum bits {one = 1, two = 2, four = 4, eight = 8}; //rang=[0, 15]
enum aha {neg = -6, one = 1, hud = 101};    //rang=[-7, 127]
aha value;
value = aha(120);   //合法

所以,只要赋给bits类型枚举变量的整数值在[0,15]范围内都是合法的,赋给aha类型枚举变量的整数值在[-7,127]范围内都是合法的.

每个枚举变量占用存储空间大小由编译器决定,早期C++,只能将int型赋给枚举变量,但新版本可以使用long,甚至long long型的值。所以其取值范围小的可以用单字节,取值范围大的可以用4字节。

5.关于指针和动态存储空间(堆heap)

int *ptr_a; //C style
int* ptr_a; //C++ style
int* ptr_a, ptr_b;  //ptr_a是指针,但ptr_b是int变量!!!
int *ptr_a, *ptr_b; //此时二者均为指针!
long *fellow;       //定义了一个地址,但未赋初值。
*fellow = 22334;    //将22334存贮在一个未知地址,极其危险!!!
int *ptr;
ptr = (int *)0xb8000000;
int *ps = new int;
...
delete ps;  //释放ps指向的空间到内存池中,但ps指针变量不会被删除,可以重新指向另一个地址。
int *ps = new int;
int *pq = ps;
delete pq;  //仅需要释放一次,不需要再释放ps了。
int *psome = new int[10];//分配含10个int元素的数组,并返回数组首地址
int *pone = new int;
。。。
delete []psome;             //释放动态数组
delete []pone;              //非法!!!
delete null;                //合法。
int * ps = new int[3];
int pa[3];
...
size_ps = sizeof(ps);   //得到的是地址大小4,假设地址变量占用4个字节空间
size_pa = sizeof(pa);   //得到数组大小3*4=12,假设int变量占用4个字节空间
int * ps = new int[3];
ps[0] = 0;              //or *ps = 0;
ps[1] = 1;              //等价于 *(ps+1) = 1;
ps[2] = 2;
cout << ps[0] << endl;  //输出0
ps = ps + 1;            //指向下一个元素地址
cout << ps[0] << endl; //输出1
ps -= 1;
delete []ps;
#include <vector>
...
using namespace std;
vector<int> vi; //创建0长度的整型数组vi
int n;
cin >> n;
vector<double> vd(n);   //根据用户输入创建一个长度为n的双实型数组

7.模板类array, C++11 style

如果想创建长度固定的数组,且操作比数组方便,那就选择array。它与数组一样,使用栈空间,其效率同数组,但更方便和安全。创建array,需要包含头文件array。

#include <array>
...
using namespace std;
array<int, 5> ai;   //创建包含5个元素的整型数组ai
array<double, 4> ad = {1.2, 2.3, 3.4, 4.5}; //创建包含4个元素的double型数组di

为了错误引用数组界外的元素,可使用array类的成员函数at(index),它会检查提供的索引值index是否在数组界内。

上一篇 下一篇

猜你喜欢

热点阅读