【C++ 从基础到项目实战】C++(二):数组、字符串与结构体——组织数据的容器

📌 阅读时长:25分钟 | 关键词:C++、数组、二维数组、C风格字符串、std::string、结构体、枚举

引言

上一篇文章我们学会了用指针和引用来操控单个变量。但现实中,我们往往要处理一堆数据------全班 50 个学生的成绩、一段文本、一个商品的信息。这篇就来学习 C++ 组织数据的核心工具:数组、字符串和结构体。

一、一维数组:同类型数据的集合

1.1 声明与初始化

cpp 复制代码
int scores[5] = {80, 90, 75, 85, 95};  // 完整初始化
int nums[5] = {1, 2};                   // 部分初始化:剩余自动补 0
int data[] = {10, 20, 30};              // 省略大小,编译器自动推断为 3

1.2 下标访问与遍历

C++ 数组下标从 0 开始,访问越界会导致未定义行为(程序崩溃或数据错乱):

cpp 复制代码
int arr[5] = {10, 20, 30, 40, 50};

// for 循环遍历
for (int i = 0; i < 5; i++) {
    std::cout << arr[i] << " ";
}
// 输出:10 20 30 40 50

计算数组元素的平均值:

cpp 复制代码
int numbers[5] = {10, 20, 30, 40, 50};
int sum = 0;
for (int i = 0; i < 5; i++) {
    sum += numbers[i];
}
double avg = static_cast<double>(sum) / 5;
std::cout << "平均值为: " << avg << std::endl;  // 30

1.3 数组名 = 指向首元素的指针

数组名在大多数情况下会退化为指向首元素的常量指针:

cpp 复制代码
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;  // p 指向 arr[0]

std::cout << arr[2] << std::endl;    // 3
std::cout << *(p + 2) << std::endl;  // 3(等价写法)
表达式 含义
arr 数组首元素地址
*arr 首元素的值
arr + i 第 i 个元素的地址
*(arr + i) 第 i 个元素的值(等价于 arr[i]

二、二维数组与行指针

2.1 内存布局:按行优先

二维数组在内存中是按行连续 存储的,例如 int m[2][3]

复制代码
内存布局:m[0][0] m[0][1] m[0][2] m[1][0] m[1][1] m[1][2]

2.2 行指针:指向一行的指针

cpp 复制代码
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};

// matrix 退化为指向第一行的行指针(类型:int (*)[3])
int (*p_row)[3] = matrix;

std::cout << matrix[1][2] << std::endl;            // 6
std::cout << *(*(p_row + 1) + 2) << std::endl;     // 6(行指针方式)

// p_row + 1 → 跳过一整行(3个int),指向第二行
// *(p_row + 1) → 第二行的首地址(int* 类型)
// *(p_row + 1) + 2 → 第二行第 3 个元素的地址
// *(*(p_row + 1) + 2) → 第二行第 3 个元素的值

2.3 指针数组 vs 数组指针

这是一对容易混淆的概念------注意括号位置

cpp 复制代码
int *ptr_arr[5];      // 指针数组:5个指针的数组,每个指向int
int (*arr_ptr)[5];    // 数组指针:1个指针,指向包含5个int的数组
类型 本质 示例含义
int *p[5] 数组 有 5 个 int* 元素的数组
int (*p)[5] 指针 指向「含 5 个 int 的数组」的指针

三、字符串:从 C 风格到 std::string

3.1 C 风格字符串

C 风格字符串本质是字符数组 ,以空字符 \0 作为结束标志:

cpp 复制代码
char str1[] = "hello";                          // 自动在末尾加 '\0',数组大小为 6
char str2[6] = {'h', 'e', 'l', 'l', 'o', '\0'}; // 手动添加尾零
char str3[10] = "world";                        // 剩余 4 个位置补 '\0'

std::cout << strlen(str1) << std::endl;  // 5(不计算 '\0')

关于 '\0'' ' 的区别:

字符 ASCII 码 含义
'\0' 0 字符串结束标记(非打印字符),不计算长度
' ' 32 普通空格字符(打印字符),计算长度

空字符串 "" 只包含一个 '\0',长度为 0。

3.2 std::string:现代 C++ 的首选

C 风格字符串容易出错(缓冲区溢出、忘记 \0),std::string 类自动管理内存,更安全方便:

cpp 复制代码
#include <string>

std::string s1 = "hello";
std::string s2;
std::cin >> s2;                            // 输入字符串

std::cout << s1.length() << std::endl;     // 获取长度:5
std::cout << s1 + " " + s2 << std::endl;   // 字符串拼接:hello world

// 像访问数组一样访问单个字符
std::cout << s1[0] << std::endl;           // 'h'
s1[0] = 'H';                               // 修改

四、结构体:自定义你的复合数据类型

4.1 什么是结构体?

结构体允许你将不同类型的数据打包成一个有意义的整体:

cpp 复制代码
struct Student {
    std::string name;   // 姓名
    int id;             // 学号
    float score;        // 成绩
};

4.2 创建和使用

cpp 复制代码
Student s1;
s1.name = "张三";
s1.id = 2023001;
s1.score = 95.5;

std::cout << "姓名: " << s1.name << std::endl;
std::cout << "成绩: " << s1.score << std::endl;

4.3 C++ struct vs class

特性 struct class
默认成员权限 public private
默认继承方式 public private
能包含函数 ✅ 可以 ✅ 可以
约定用法 简单数据集合 复杂行为封装

💡 语法上两者几乎等价,只是默认权限不同。平时用 struct 存数据,用 class 做封装。

五、枚举:给整数起个有意义的名字

枚举把一组整型常量变成有意义的名称,告别"魔法数字":

cpp 复制代码
enum Weekday {
    Monday,     // 0
    Tuesday,    // 1
    Wednesday,  // 2
    Thursday,   // 3
    Friday,     // 4
    Saturday,   // 5
    Sunday      // 6
};

Weekday today = Wednesday;
if (today == Wednesday) {
    std::cout << "今天星期三!" << std::endl;
}
// 输出:今天星期三!

也可以手动指定值:

cpp 复制代码
enum Status { Success = 0, Warning = 10, Error = 20 };

小结

序号 知识点 一句话总结
1 一维数组 同类型数据连续存储,下标从 0 开始,越界会引发未定义行为
2 二维数组 按行优先存储,数组名退化为行指针
3 指针数组 vs 数组指针 看括号位置------*p[n] 是数组,(*p)[n] 是指针
4 C 风格字符串 字符数组 + \0 结尾
5 std::string 现代 C++ 字符串,自动管理内存,推荐使用
6 结构体 把不同类型数据打包成一个整体
7 枚举 给整型常量起名,提高可读性

下一篇文章,我们将进入 C++ 的核心------函数进阶:重载、默认参数、内联函数、回调与递归等高级用法。


本文是「C++ 从基础到项目实战」系列的第 2 篇。关注我,不错过后续更新。

相关推荐
叶子野格1 小时前
《C语言学习:文件操作》16
c语言·开发语言·c++·学习·visual studio
AI科技星1 小时前
万有引力G与真空介电常数ε0全维度完整关系式汇编(基于v=c螺旋时空理论)
c语言·开发语言·前端·javascript·网络·汇编·electron
如竟没有火炬2 小时前
寻找峰值——二分
java·开发语言·数据结构·python·算法·散列表
Lumbrologist2 小时前
【C++】零基础入门 · 第 17 节:多线程编程基础
java·c++·算法
JAVA社区2 小时前
Java高级全套教程(十三)—— 分布式锁超详细实战详解(原理+三种方案企业级落地)
java·开发语言·分布式·spring cloud·面试·java-zookeeper
超梦dasgg2 小时前
Java 生产环境 Maven 实战指南
java·开发语言·maven
A_humble_scholar2 小时前
C++11 学习笔记:统一初始化、右值引用与完美转发
c++·笔记·学习
叶子野格2 小时前
《C语言学习:位运算》17
c语言·开发语言·c++·学习·visual studio
RSTJ_16253 小时前
PYTHON+AI LLM DAY SIXTY-FOUR
开发语言·python