C++ 复合类型

本文深入探讨了C++中的各种数据结构,包括数组、字符串、结构体、共用体、枚举、指针以及动态内存管理。详细讲解了每种数据结构的特点、声明、初始化及使用方法,同时介绍了vector和array作为数组的现代替代方案。

阅读者你好!?如果您是编程高手,请误笑我的无知。 由于本人是一个编程界菜鸟,希望通过写博客的方式激励自己不断的学习
学无止尽,嘿嘿!?我会继续加油的!

复合类型

  • 数组
  • 字符串
  • 结构体
  • 共用体
  • 枚举
  • 指针
  • 数组的代替品

数组

存储多个同类型数据

  • 数组声明
    1. 每个元素的类型
    2. 数组名
    3. 数组元素个数
// 声明
int number[10];
// 初始化
number[0] = 100;

// 声明且初始化
int number[5] = {1, 2, 3, 4, 5};

// 访问数组元素,赋值
cout << number[0] << endl;
number[0] = 1000

// sizeof 查询数组变量中,共有多少字节
sizeof num
// sizeof num / sizeof(int) int数组长度
复制代码

字符串

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

  • C 风格

  • 基于 string 类库

C 风格字符串

  • 存储在内存的连续字节中的一系列字符

  • cstring 头文件,strlen("") 返回字符串长度

可以将字符串存储在char类型数组中,每个元素就是一个字符,注意:要以空字符结尾(“\0”)

char name[6] = {'h','e','l','l','o','\0'};

cout << name << endl;

输出:hello
复制代码
  • 简单的声明初始化,不需要手动加 ‘\0’
char[6] = "hello"; //注意数组长度要加一,给‘\0’留位置

char[] = "hello";
复制代码

注意: "S" 表示:两个字符(‘s’和‘\0’),"S"返回的是字符串内存地址

拼接字符串字面量

“hello” “world” 任何在两个字符串中间(空白、制表符、换行符)都会自动的拼接起来,第一个字符串最后的‘\0’将被第二个字符串第一个字符取代

在数组中使用字符串

  • 将数组初始化为字符串常量
char name1[] = "hello";

cout << name1 << endl;
复制代码
  • 将键盘或文件输入读入到数组中
const int Msize = 15;
char name[Msize];
cout << "请输入名称:";
cin >> name;
cout << name << endl; 
cout << strlen(name) << endl; 
复制代码

每次读取一行字符串输入

cin 接收输入,并且以空行、制表符、换行表示结束,想读取一行,cin提供了,getline()、get(),‘\n’表示结束

  1. getline() 将丢弃‘\n’
// 通过回车键输入的换行符,表示结束
// cin.getline(name, size); // name:数组,size:长度

const int Msize = 20;

char name[Msize];

cout << "请输入姓名: ";

cin.getline(name, Msize);

cout << name << endl;
复制代码
  1. get() 保留'\n'

因为get()保留'\n',当第一次调用get()后,第二次调用,会读到第一个的‘\n’,所以第二次就直接结束了,现在可以通过get(),读取下一个字符,跳过第一次调用的'\n'

const int Msize = 20;

char name[Msize];
char age[Msize];

cout << "请输入姓名: ";
cin.get(name, Msize).get(); // 跳过'\n'
cout << "请输入年龄: ";
cin.get(age, Msize);
复制代码
  1. 空行问题

当调用get直接输入空行的话,会被设置失效位,接下来的输入会被阻断,解决:cin.clear()

string类 简介

  • string 头文件

  • std::string,在std空间下

  • string name = "hello world";

  • string name = {"hello"};

  • string name = {'h','a'};

  • .size() 返回长度

  • 可以像数组一样通过下标访问 name[0]

  • 可以cin输入内容到string对象

注意

  • 不能将一个数组赋值给另一个数组,但是可以将string赋值给另一个string

  • C风格字符串,通过cstring头文件,提供的方法处理字符串,比如:strlen() 、 strcat() 、 strcpy(),现在string类操作很简单:如.size() 、 name1 = name2 、 name1 += "adadasd"

    string name1;
    string name2 = "world";
    name1 += "hello ";

    cout << name1 + name2 << endl;
    cout << (name1 + name2).size() << endl;
复制代码

结构体(struct)

存储多种数据类型,是用户定义的类型

  • 可以将结构体,作为参数传递给函数

  • 函数可以将结构体,作为返回值

  • 定义结构描述

    struct person {

        string name;

        unsigned short age;
    };
复制代码
  • 创建结构变量
    // 声明并初始化
    struct person p1 = {
        "hello",
        99
    }
复制代码
  • 创建并声明变量
    struct person {

        string name;

        unsigned short age;
    } p1, p2;
复制代码
  • 结构数组
    person ps[10];

    person ps = {
        {"asd", 29},
        {"asd", 20}
    }
复制代码
  • 结构中的位字段,用于硬件
    struct test{
        unsigned int SN : 4; // 分配4bit
        unsigned int : 4; // 表示间隔
        bool isopen : 1; // 分配1bit
    } t1;
复制代码

共用体(union)

能过存储不同的数据类型,但是只能是其中的一种,如:

    union id {
        int a;
        long b;
        double c;
    }mId;

    mId.a = 10;
    mId.c = 10.0; //这个时候a,b的值将丢失
复制代码

用途:

  • 当数据项使用两种或多种格式,但不同时使用的时候,可以节省空间

匿名共用体

    struct person{
        union {
            char[] id_str, // 将成为成员变量
            int id_int  // 将成为成员变量
        }
    }
    // id_str,id_int在内存中地址一样
复制代码

枚举

  • enum color {red, blue, green}

  • enum color {red = 1, blue = 2}

  • enum color {red, blue = 100, green}

  • color c; 声明枚举变量

    color c = blue;

    cout << c << endl;
复制代码

指针与自由存储空间

指针是一个变量,存储的是值的地址,不是值本身,指针名表示的是地址

  • & 地址运算符,可以获取变量的内存地址
    int a = 100;
    &a // 变量a返回内存地址 十六进制 
复制代码
  • * 间接值 或者 解除引用 运算符,运用于指针
    int a = 1000;
    int *p = &a; // p 指针变量

    cout << p << endl; // 输出地址
    cout << *p << endl; // 输出值
复制代码
  • 指针需要知道指向的数据类型
    int a = 100;
    int *p_a = &a; // 指向int 类型指针

    double b = 100.0;
    double *b = &b; // 指向double 类型指针
复制代码

注意

  • int* p1, p2; 声明了一个指向int的p1指针,声明了一个变量p2

  • 一定要在对指针*解除引用运算之前,将指针初始化为一个确定的、合适的地址

指针真正的作用在于,在运行阶段,分配未命名的内存以存储值,在这种情况下,只能通过指针来访问内存

使用 new 来分配内存

new 运算符

  • new 数据类型; 来分配给类型的内存空间,并返回地址

  • 最大的用处是,在运行时,觉得,要不要分配内存空间,用就分配,不用就不分配

  • 通常,大型数据(数组、字符串、结构等),需要在运行是觉得是否用,用new来分配内存

    int *p = new int;
    *p = 1000; //赋值

    // 动态创建数组
    int *p = new int[10];

    cout << p << endl;

    *p = 10; // 相当于 p[0] = 10

    *(p + 1) = 11; // 相当于 p[1] = 11

    cout << *(p + 1) << endl;

    delete[] p;
复制代码

new 一定要用 delete 去释放内存

使用delete释放内存

delete 会释放指针指向的内存,但是不会删除指针本身

    delete 指针变量
复制代码

注意

  • 不要使用delete释放,不是new出来的内存块

  • 不要使用delete释放同一个内存两次

  • 如果使用new xx []分配的内存,应该使用delete [] 指针名,来释放

  • 对空指针应用delete是安全的

指针、数组、指针运算符

  • 大多数情况下,C++将数组名解释为数组第一个元素的地址
    int num[] = {1,2,3,4}
    int *p = num; // p指向num数组的第一个元素地址
复制代码
  • p[2] 等价与 *(p+2)
    p1 = {
            {1, 2, 3, 4, 5, 6, 7},
            "hello",
            29
    };

    person *p = &p1;

    cout << p->age << endl; // -> 间接成员运算符,结构指针访问属性
复制代码

数组的替代 vector、array (模版类)

vector 效率低

动态数组,可以在最后追加,可以插入,本质上也是通过new delete动态分配内存的

  • 头文件vector,在std命名空间中

  • std:vector<类型> vn(长度)

    vector<int> vn(2);
    vn[0] = 102;
    vn[2] = 111;
    vn[3] = 1231; // 自动扩容

    cout << vn[0] << endl;
    cout << vn[1] << endl;
    cout << vn[2] << endl;
    cout << vn[3] << endl;
复制代码

array (c++11)

  • 头文件array,在std命名空间中

  • std::array<类型,长度>

    array<int, 2> a = {1,2}

    array[0]
    
    array[1]
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值