专栏导航
- ← 上一篇:数学运算与逻辑判断 - 运算符与条件语句
- ← 第一篇:编程世界初探
- 专栏目录
单个变量只能存储一个数据。数组让我们可以像收纳盒一样,整齐地存储多个相同类型的数据。
什么是数组?
现实生活中的类比
想象一个班级的花名册:
座位号:1 2 3 4 5
学生:小明 小红 小刚 小丽 小伟
- 花名册 = 数组
- 每个座位 = 数组的元素
- 座位号 = 数组的索引(下标)
为什么需要数组?
不使用数组(存储多个学生姓名):
string student1 = "小明";
string student2 = "小红";
string student3 = "小刚";
string student4 = "小丽";
string student5 = "小伟";
// ... 如果有 50 个学生呢?
使用数组:
string[] students = { "小明", "小红", "小刚", "小丽", "小伟" };
数组的特点
✅ 相同类型:所有元素必须是相同的数据类型
✅ 固定长度:创建后长度不能改变
✅ 连续存储:元素在内存中连续存放
✅ 索引访问:通过索引(从0开始)快速访问元素
声明和初始化数组
方式一:声明并初始化
// 完整语法
类型[] 数组名 = new 类型[长度];
示例:
// 声明一个长度为 5 的整数数组
int[] numbers = new int[5];
// 声明一个长度为 3 的字符串数组
string[] names = new string[3];
方式二:声明并直接赋值
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
string[] names = { "张三", "李四", "王五" }; // 简化写法
数组的索引
数组的索引从 0 开始,最后一个元素的索引是 长度 - 1。
string[] names = { "张三", "李四", "王五", "赵六", "孙七" };
// 索引: 0 1 2 3 4
访问数组元素:
string[] names = { "张三", "李四", "王五", "赵六", "孙七" };
Console.WriteLine(names[0]); // 输出:张三
Console.WriteLine(names[2]); // 输出:王五
Console.WriteLine(names[4]); // 输出:孙七
修改数组元素:
int[] numbers = { 1, 2, 3, 4, 5 };
numbers[2] = 100; // 修改索引为 2 的元素
Console.WriteLine(numbers[2]); // 输出:100
数组的属性
获取数组长度
使用 Length 属性获取数组的长度(元素个数)。
int[] numbers = { 1, 2, 3, 4, 5 };
Console.WriteLine($"数组长度:{numbers.Length}"); // 输出:数组长度:5
遍历数组
int[] numbers = { 1, 2, 3, 4, 5 };
// 方式一:使用 for 循环
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
}
// 方式二:使用 foreach 循环(推荐)
foreach (int num in numbers)
{
Console.WriteLine(num);
}
数组常见操作
存储一组学生姓名
using System;
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
// 创建字符串数组存储学生姓名
string[] students = { "张三", "李四", "王五", "赵六", "孙七" };
Console.WriteLine("=== 班级花名册 ===");
Console.WriteLine($"班级人数:{students.Length}");
Console.WriteLine();
// 遍历输出所有学生
for (int i = 0; i < students.Length; i++)
{
Console.WriteLine($"学号{i + 1}:{students[i]}");
}
Console.WriteLine();
Console.WriteLine("=== 使用 foreach 遍历 ===");
foreach (string student in students)
{
Console.WriteLine($"学生:{student}");
}
}
}
}
输出:
=== 班级花名册 ===
班级人数:5
学号1:张三
学号2:李四
学号3:王五
学号4:赵六
学号5:孙七
=== 使用 foreach 遍历 ===
学生:张三
学生:李四
学生:王五
学生:赵六
学生:孙七
统计数组最大值
using System;
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
int[] numbers = { 23, 45, 12, 67, 34, 89, 56 };
Console.WriteLine("数组元素:");
foreach (int num in numbers)
{
Console.Write(num + " ");
}
Console.WriteLine();
// 找最大值
int max = numbers[0]; // 假设第一个元素是最大的
for (int i = 1; i < numbers.Length; i++)
{
if (numbers[i] > max)
{
max = numbers[i];
}
}
Console.WriteLine($"最大值:{max}");
}
}
}
输出:
数组元素:
23 45 12 67 34 89 56
最大值:89
统计数组最小值、平均值
int[] numbers = { 23, 45, 12, 67, 34, 89, 56 };
// 最大值
int max = numbers[0];
// 最小值
int min = numbers[0];
// 总和
int sum = 0;
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] > max)
max = numbers[i];
if (numbers[i] < min)
min = numbers[i];
sum += numbers[i];
}
double average = (double)sum / numbers.Length;
Console.WriteLine($"最大值:{max}");
Console.WriteLine($"最小值:{min}");
Console.WriteLine($"平均值:{average:F2}");
输出:
最大值:89
最小值:12
平均值:46.57
使用 LINQ 快速计算(推荐!)
对于数组或 List<T>,可以使用 LINQ 提供的扩展方法快速进行统计计算,大大简化代码!
using System;
using System.Linq; // 引入 LINQ 命名空间
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
int[] numbers = { 23, 45, 12, 67, 34, 89, 56 };
// LINQ 扩展方法自动完成计算
int sum = numbers.Sum(); // 求和:326
int max = numbers.Max(); // 最大值:89
int min = numbers.Min(); // 最小值:12
double avg = numbers.Average(); // 平均值:46.571...
Console.WriteLine($"数组元素:{string.Join(", ", numbers)}");
Console.WriteLine($"总和:{sum}");
Console.WriteLine($"最大值:{max}");
Console.WriteLine($"最小值:{min}");
Console.WriteLine($"平均值:{avg:F2}");
}
}
}
输出:
数组元素:23, 45, 12, 67, 34, 89, 56
总和:326
最大值:89
最小值:12
平均值:46.57
LINQ 扩展方法一览
| 方法 | 功能 | 返回类型 |
|---|---|---|
Sum() | 计算元素总和 | int/double 等 |
Max() | 获取最大值 | 元素类型 |
Min() | 获取最小值 | 元素类型 |
Average() | 计算平均值 | double |
注意事项
- 必须引入命名空间:
using System.Linq; - 适用于数组:
int[] a = { 1, 2, 3 }; a.Sum(); - 适用于 List:
List<int> list = new List<int> { 1, 2, 3 }; list.Sum(); - 空集合:对空集合调用这些方法会抛出异常,使用前应检查:
list.Count > 0 ? list.Sum() : 0;
对比:传统方式 vs LINQ
int[] numbers = { 1, 2, 3, 4, 5 };
// 传统方式(需要 10+ 行代码)
int sum = 0;
for (int i = 0; i < numbers.Length; i++)
{
sum += numbers[i];
}
// LINQ 方式(1 行代码搞定!)
int sum = numbers.Sum();
数组排序
排序是数组操作中的常见需求。C# 提供了多种排序方式。
使用 Array.Sort() 方法(数组原地排序)
Array.Sort() 会对数组进行原地排序(直接修改原数组)。
using System;
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
int[] numbers = { 23, 45, 12, 67, 34, 89, 56 };
Console.WriteLine("排序前:");
Console.WriteLine(string.Join(", ", numbers));
// 原地升序排序(直接修改原数组)
Array.Sort(numbers);
Console.WriteLine("\n升序排序后:");
Console.WriteLine(string.Join(", ", numbers));
// 原地降序排序(先升序,再反转)
Array.Reverse(numbers);
Console.WriteLine("\n降序排序后:");
Console.WriteLine(string.Join(", ", numbers));
}
}
}
输出:
排序前:
23, 45, 12, 67, 34, 89, 56
升序排序后:
12, 23, 34, 45, 56, 67, 89
降序排序后:
89, 67, 56, 45, 34, 23, 12
使用 LINQ OrderBy() 方法(返回新数组)
LINQ 的排序方法不会修改原数组,而是返回一个新的已排序数组。
using System;
using System.Linq;
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
int[] numbers = { 23, 45, 12, 67, 34, 89, 56 };
Console.WriteLine("原数组:");
Console.WriteLine(string.Join(", ", numbers));
// 升序排序(返回新数组)
int[] ascSorted = numbers.OrderBy(x => x).ToArray();
Console.WriteLine("\n升序排序(新数组):");
Console.WriteLine(string.Join(", ", ascSorted));
// 降序排序
int[] descSorted = numbers.OrderByDescending(x => x).ToArray();
Console.WriteLine("\n降序排序(新数组):");
Console.WriteLine(string.Join(", ", descSorted));
Console.WriteLine("\n原数组保持不变:");
Console.WriteLine(string.Join(", ", numbers));
}
}
}
输出:
原数组:
23, 45, 12, 67, 34, 89, 56
升序排序(新数组):
12, 23, 34, 45, 56, 67, 89
降序排序(新数组):
89, 67, 56, 45, 34, 23, 12
原数组保持不变:
23, 45, 12, 67, 34, 89, 56
字符串数组排序
using System;
using System.Linq;
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
string[] names = { "张三", "李四", "王五", "赵六", "孙七" };
Console.WriteLine("排序前:");
Console.WriteLine(string.Join(", ", names));
// 按字母顺序排序
string[] sortedNames = names.OrderBy(x => x).ToArray();
Console.WriteLine("\n排序后:");
Console.WriteLine(string.Join(", ", sortedNames));
// 按字符串长度排序
string[] lengthSorted = names.OrderBy(x => x.Length).ToArray();
Console.WriteLine("\n按长度排序:");
Console.WriteLine(string.Join(", ", lengthSorted));
}
}
}
输出:
排序前:
张三, 李四, 王五, 赵六, 孙七
排序后:
李四, 孙七, 王五, 张三, 赵六
按长度排序:
张三, 李四, 王五, 孙七, 赵六
排序方法对比
| 方法 | 是否修改原数组 | 返回值 | 适用场景 |
|---|---|---|---|
Array.Sort(arr) | ✅ 是 | void | 需要原地排序,节省内存 |
arr.OrderBy(x => x) | ❌ 否 | IOrderedEnumerable<T> | 需要保留原数组 |
arr.OrderByDescending(x => x) | ❌ 否 | IOrderedEnumerable<T> | 降序排序 |
Array.Reverse(arr) | ✅ 是 | void | 反转数组 |
实践:学生成绩排序
using System;
using System.Linq;
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
double[] scores = { 85.5, 92.0, 78.5, 90.0, 65.0, 88.5 };
Console.WriteLine("原始成绩:");
Console.WriteLine(string.Join(", ", scores));
// 升序排序
var ascScores = scores.OrderBy(x => x).ToArray();
Console.WriteLine($"\n最低分:{ascScores.First()}"); // 65.0
Console.WriteLine($"最高分:{ascScores.Last()}"); // 92.0
// 降序排序(方便排名)
var descScores = scores.OrderByDescending(x => x).ToArray();
Console.WriteLine("\n成绩排名:");
for (int i = 0; i < descScores.Length; i++)
{
Console.WriteLine($"第{i + 1}名:{descScores[i]}");
}
}
}
}
输出:
原始成绩:
85.5, 92, 78.5, 90, 65, 88.5
最低分:65
最高分:92
成绩排名:
第1名:92
第2名:90
第3名:88.5
第4名:85.5
第5名:78.5
第6名:65
数组的常见错误
索引越界
int[] numbers = { 1, 2, 3, 4, 5 };
// 索引: 0, 1, 2, 3, 4
Console.WriteLine(numbers[5]); // 错误!索引越界
错误信息:
IndexOutOfRangeException: Index was outside the bounds of the array.
正确做法:
if (index >= 0 && index < numbers.Length)
{
Console.WriteLine(numbers[index]);
}
else
{
Console.WriteLine("索引越界!");
}
数组未初始化
int[] numbers;
Console.WriteLine(numbers[0]); // 错误!未初始化
正确做法:
int[] numbers = new int[5]; // 初始化数组
Console.WriteLine(numbers[0]); // 输出:0(默认值)
数组默认值
创建数组时,元素会有默认值:
| 类型 | 默认值 |
|---|---|
int | 0 |
double | 0.0 |
bool | false |
string | null |
int[] numbers = new int[3];
Console.WriteLine(numbers[0]); // 输出:0
string[] names = new string[3];
Console.WriteLine(names[0] ?? "空"); // 输出:空
List 简介(动态数组)
数组长度固定,而 List<T> 可以动态增删元素,更灵活。
创建 List
using System.Collections.Generic; // 需要引入命名空间
// 创建空的整数列表
List<int> numbers = new List<int>();
// 创建带初始元素的列表
List<string> names = new List<string> { "张三", "李四", "王五" };
List 常用操作
List<string> students = new List<string>();
// 添加元素
students.Add("张三");
students.Add("李四");
students.Add("王五");
// 访问元素
Console.WriteLine(students[0]); // 输出:张三
// 修改元素
students[0] = "小明";
// 删除元素
students.Remove("李四"); // 删除指定值
students.RemoveAt(0); // 删除指定索引
// 获取元素数量
Console.WriteLine($"学生数量:{students.Count}"); // Count,不是 Length
// 遍历
foreach (string student in students)
{
Console.WriteLine(student);
}
// 查找元素
bool exists = students.Contains("王五"); // true
// 清空所有元素
students.Clear();
数组 vs List
| 特性 | 数组 | List |
|---|---|---|
| 长度 | 固定 | 动态 |
| 添加/删除 | 不支持 | 支持 |
| 访问速度 | 快 | 快 |
| 内存占用 | 小 | 稍大 |
| 适用场景 | 长度固定、频繁访问 | 频繁增删 |
使用 List 存储学生成绩
using System;
using System.Collections.Generic;
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
List<double> scores = new List<double>();
Console.WriteLine("===== 学生成绩管理 =====");
// 添加成绩
scores.Add(85.5);
scores.Add(92.0);
scores.Add(78.5);
scores.Add(90.0);
Console.WriteLine($"已添加 {scores.Count} 个成绩:");
foreach (double score in scores)
{
Console.WriteLine(score);
}
// 计算平均分
double sum = 0;
foreach (double score in scores)
{
sum += score;
}
double average = sum / scores.Count;
Console.WriteLine($"\n平均分:{average:F2}");
// 查找最高分
double maxScore = scores[0];
foreach (double score in scores)
{
if (score > maxScore)
maxScore = score;
}
Console.WriteLine($"最高分:{maxScore}");
// 删除低于 80 分的成绩
scores.RemoveAll(s => s < 80);
Console.WriteLine($"\n删除低分后剩余:{scores.Count} 个");
foreach (double score in scores)
{
Console.WriteLine(score);
}
}
}
}
输出:
===== 学生成绩管理 =====
已添加 4 个成绩:
85.5
92
78.5
90
平均分:86.50
最高分:92
删除低分后剩余:3 个
85.5
92
90
实践:购物清单管理
using System;
using System.Collections.Generic;
namespace Week5Practice
{
class Program
{
static void Main(string[] args)
{
List<string> shoppingList = new List<string>();
Console.WriteLine("===== 购物清单管理 =====\n");
while (true)
{
Console.WriteLine("1. 添加商品");
Console.WriteLine("2. 删除商品");
Console.WriteLine("3. 查看清单");
Console.WriteLine("4. 退出");
Console.Write("请选择操作:");
string choice = Console.ReadLine();
switch (choice)
{
case "1":
Console.Write("请输入要添加的商品:");
string item = Console.ReadLine();
shoppingList.Add(item);
Console.WriteLine($"已添加:{item}\n");
break;
case "2":
if (shoppingList.Count == 0)
{
Console.WriteLine("清单为空!\n");
break;
}
Console.WriteLine("当前清单:");
for (int i = 0; i < shoppingList.Count; i++)
{
Console.WriteLine($"{i + 1}. {shoppingList[i]}");
}
Console.Write("请输入要删除的序号:");
int index = int.Parse(Console.ReadLine()) - 1;
if (index >= 0 && index < shoppingList.Count)
{
string removed = shoppingList[index];
shoppingList.RemoveAt(index);
Console.WriteLine($"已删除:{removed}\n");
}
else
{
Console.WriteLine("序号无效!\n");
}
break;
case "3":
Console.WriteLine("===== 购物清单 =====");
if (shoppingList.Count == 0)
{
Console.WriteLine("清单为空!");
}
else
{
for (int i = 0; i < shoppingList.Count; i++)
{
Console.WriteLine($"{i + 1}. {shoppingList[i]}");
}
}
Console.WriteLine($"总计:{shoppingList.Count} 件商品\n");
break;
case "4":
Console.WriteLine("再见!");
return;
default:
Console.WriteLine("无效的选择!\n");
break;
}
}
}
}
}
运行示例:
===== 购物清单管理 =====
1. 添加商品
2. 删除商品
3. 查看清单
4. 退出
请选择操作:1
请输入要添加的商品:牛奶
已添加:牛奶
1. 添加商品
2. 删除商品
3. 查看清单
4. 退出
请选择操作:1
请输入要添加的商品:面包
已添加:面包
1. 添加商品
2. 删除商品
3. 查看清单
4. 退出
请选择操作:3
===== 购物清单 =====
1. 牛奶
2. 面包
总计:2 件商品
1. 添加商品
2. 删除商品
3. 查看清单
4. 退出
请选择操作:4
再见!
本章总结
- ✅ 理解了数组的概念和使用
- ✅ 学会了声明、初始化和访问数组
- ✅ 掌握了数组的遍历和常见操作
- ✅ 了解了 List 动态数组
- ✅ 实践了购物清单管理系统