第三章:数组深入理解与字符串操作

🎯 学习目标

3.1 一维数组的详细操作

3.1.1 数组声明和初始化的多种方式

// 方式1:先声明后初始化
int[] numbers1;
numbers1 = new int[5]; // 创建包含5个元素的数组,默认值为0

// 方式2:声明并初始化大小
int[] numbers2 = new int[3]; // 3个元素,都是0

// 方式3:声明并直接赋值
int[] numbers3 = new int[] { 1, 2, 3, 4, 5 };

// 方式4:简化语法(最常用)
int[] numbers4 = { 10, 20, 30, 40, 50 };

// 方式5:使用var关键字
var numbers5 = new[] { 1, 2, 3 }; // 编译器推断类型

3.1.2 数组内存结构示意图

3.1.3 数组的遍历方法

string[] fruits = { "苹果", "香蕉", "橙子", "葡萄", "芒果" };

// 方法1:for循环(可以控制索引)
Console.WriteLine("使用for循环遍历:");
for (int i = 0; i < fruits.Length; i++)
{
    Console.WriteLine($"索引 {i}: {fruits[i]}");
}

// 方法2:foreach循环(更简洁,只读)
Console.WriteLine("\n使用foreach循环遍历:");
foreach (string fruit in fruits)
{
    Console.WriteLine(fruit);
}

3.1.4 遍历方法性能对比

方法控制索引修改元素性能使用场景
for循环需要索引操作
foreach简单遍历
GetEnumerator特殊需求

3.1.5 数组的常用操作

// 创建测试数组
int[] scores = { 85, 92, 78, 96, 88, 90 };

// 1. 访问和修改元素
scores[0] = 87; // 修改第一个元素
Console.WriteLine($"第一个分数: {scores[0]}");
Console.WriteLine($"最后一个分数: {scores[scores.Length - 1]}");

// 2. 数组排序
Array.Sort(scores);
Console.WriteLine("\n排序后的分数:");
foreach (int score in scores)
    Console.Write(score + " ");

// 3. 数组反转
Array.Reverse(scores);
Console.WriteLine("\n反转后的分数:");
foreach (int score in scores)
    Console.Write(score + " ");

3.1.6 数组操作效果图

3.2 多维数组

3.2.1 二维数组(表格结构)

// 声明和初始化二维数组
int[,] matrix = new int[3, 3]; // 3行3列

// 初始化二维数组
int[,] matrix2 = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

3.2.2 二维数组结构图

3.2.3 访问和遍历二维数组

// 访问二维数组元素
matrix[0, 0] = 10; // 第一行第一列
matrix[1, 2] = 20; // 第二行第三列

// 遍历二维数组
Console.WriteLine("二维数组内容:");
for (int row = 0; row < matrix2.GetLength(0); row++) // GetLength(0)获取行数
{
    for (int col = 0; col < matrix2.GetLength(1); col++) // GetLength(1)获取列数
    {
        Console.Write(matrix2[row, col] + "\t");
    }
    Console.WriteLine();
}

3.2.4 锯齿数组(数组的数组)

// 声明锯齿数组
int[][] jaggedArray = new int[3][];

// 初始化每个子数组(长度可以不同)
jaggedArray[0] = new int[] { 1, 2, 3 };
jaggedArray[1] = new int[] { 4, 5 };
jaggedArray[2] = new int[] { 6, 7, 8, 9 };

3.2.5 锯齿数组结构图

索引0: [1] [2] [3]
索引1: [4] [5]
索引2: [6] [7] [8] [9]

3.2.6 多维数组 vs 锯齿数组

特性多维数组锯齿数组
内存布局连续不连续
每行大小固定可变
性能更好稍差
灵活性

3.3 实际应用:学生成绩表

// 使用二维数组存储多个学生的多科成绩
int[,] studentScores = {
    {85, 92, 78},  // 学生1的语文、数学、英语成绩
    {76, 88, 95},  // 学生2
    {90, 87, 84},  // 学生3
    {82, 79, 91}   // 学生4
};

string[] subjects = { "语文", "数学", "英语" };

3.4 字符串操作

3.4.1 字符串的不可变性

string str1 = "Hello";
string str2 = str1;  // str2和str1引用同一个字符串

Console.WriteLine($"str1: {str1}"); // Hello
Console.WriteLine($"str2: {str2}"); // Hello

// 修改str1
str1 = str1 + " World";  // 创建新的字符串对象

Console.WriteLine($"修改后str1: {str1}"); // Hello World
Console.WriteLine($"str2: {str2}");       // Hello (保持不变)

3.4.2 字符串不可变性示意图

初始状态:
str1 → "Hello" ← str2

修改后:
str1 → "Hello World"
str2 → "Hello"

3.4.3 重要概念对比

特性普通字符串StringBuilder
可变性不可变可变
线程安全
性能(大量修改)
内存使用

3.5 字符串常用方法

3.5.1 长度和空值检查

string text = "C# Programming";

// 基本属性
Console.WriteLine($"字符串: {text}");
Console.WriteLine($"长度: {text.Length}");
Console.WriteLine($"是否为空: {string.IsNullOrEmpty(text)}");
Console.WriteLine($"是否为空白: {string.IsNullOrWhiteSpace(text)}");

3.5.2 字符串检查方法统计

3.5.3 子字符串操作

string sentence = "The quick brown fox jumps over the lazy dog";

// Substring - 提取子字符串
string part1 = sentence.Substring(4);      // 从索引4开始到结尾
string part2 = sentence.Substring(4, 5);   // 从索引4开始,取5个字符

Console.WriteLine($"原句: {sentence}");
Console.WriteLine($"从索引4开始: {part1}");
Console.WriteLine($"从索引4取5个字符: {part2}");

3.5.4 查找和定位

string text = "Hello World, Welcome to C# Programming";

// 查找方法
int index1 = text.IndexOf('W');           // 查找字符第一次出现的位置
int index2 = text.IndexOf("World");       // 查找子字符串
int index3 = text.LastIndexOf('o');       // 从后往前查找

Console.WriteLine($"'W'的位置: {index1}");
Console.WriteLine($"\"World\"的位置: {index2}");
Console.WriteLine($"最后一个'o'的位置: {index3}");

3.5.5 字符串查找性能对比

方法方向返回值性能
IndexOf前→后第一个匹配索引O(n)
LastIndexOf后→前最后一个匹配索引O(n)
Contains前→后boolO(n)

3.5.6 修改和转换

string original = "  Hello C# World  ";

// 去除空格
string trimmed = original.Trim();         // 去除两端空格

// 大小写转换
string upper = original.ToUpper();        // 全大写
string lower = original.ToLower();        // 全小写

// 替换操作
string replaced = original.Replace("C#", "CSharp");

3.5.7 字符串转换流程图

3.5.8 分割和连接

// 分割字符串
string data = "John,25,Developer,New York";
string[] parts = data.Split(',');

Console.WriteLine("分割结果:");
foreach (string part in parts)
{
    Console.WriteLine(part);
}

// 连接字符串数组
string[] words = { "Hello", "C#", "World" };
string joined1 = string.Join(" ", words);      // 用空格连接

3.5.9 字符串格式化

string name = "张三";
int age = 25;
double salary = 7500.50;

// 方法1:字符串插值(推荐)
string message1 = $"姓名: {name}, 年龄: {age}, 薪资: {salary:C}";

// 数字格式化
double number = 1234.5678;
Console.WriteLine($"默认: {number}");
Console.WriteLine($"货币: {number:C}");
Console.WriteLine($"小数两位: {number:F2}");

3.5.10 格式化方法使用统计

方法可读性性能推荐度
字符串插值($")⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
string.Format⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
字符串拼接⭐⭐⭐⭐⭐⭐

3.6 StringBuilder 类

3.6.1 为什么需要StringBuilder?

using System.Text;

// 性能测试对比
DateTime start1 = DateTime.Now;
string result1 = "";
for (int i = 0; i < 10000; i++)
{
    result1 += i.ToString(); // 每次拼接都创建新字符串对象
}
DateTime end1 = DateTime.Now;

DateTime start2 = DateTime.Now;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
    sb.Append(i.ToString()); // 在同一个对象上操作
}
string result2 = sb.ToString();
DateTime end2 = DateTime.Now;

3.6.2 性能对比图表

普通字符串拼接:
操作次数: 10000
耗时: 150ms
内存分配: 10000+ 个对象

StringBuilder:
操作次数: 10000
耗时: 5ms
内存分配: 1 个主要对象

3.6.3 StringBuilder的常用方法

StringBuilder sb = new StringBuilder();

// 1. Append - 追加内容
sb.Append("Hello");
sb.Append(" ");
sb.Append("World");

// 2. AppendLine - 追加内容并换行
sb.AppendLine();
sb.AppendLine("这是新的一行");

// 3. AppendFormat - 格式化追加
sb.AppendFormat("当前时间: {0:yyyy-MM-dd}", DateTime.Now);

3.6.4 StringBuilder方法使用频率

3.7 实际应用场景

3.7.1 场景1:构建动态SQL查询

StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.Append("SELECT * FROM Users WHERE 1=1");

string nameFilter = "John";
int minAge = 18;

if (!string.IsNullOrEmpty(nameFilter))
{
    sqlBuilder.Append(" AND Name = '").Append(nameFilter).Append("'");
}

if (minAge > 0)
{
    sqlBuilder.Append(" AND Age >= ").Append(minAge);
}

string finalSql = sqlBuilder.ToString();

3.7.2 场景2:生成HTML内容

StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.AppendLine("<!DOCTYPE html>");
htmlBuilder.AppendLine("<html>");
htmlBuilder.AppendLine("<head>");
htmlBuilder.AppendLine("    <title>用户列表</title>");
htmlBuilder.AppendLine("</head>");

string[] users = { "Alice", "Bob", "Charlie" };
foreach (string user in users)
{
    htmlBuilder.AppendLine($"        <li>{user}</li>");
}

3.8 学习路径总结

3.8.1 技能掌握程度评估

技能点初学者进阶精通
数组声明初始化
数组遍历
多维数组
字符串基本操作
字符串不可变性
StringBuilder
性能优化

🎉 恭喜! 你已经完成了数组和字符串的深入学习。接下来通过实践练习来巩固这些知识吧!

3.9 动手练习

3.9.1 练习1:数组排序和统计

1.将原始数组45 78 23 91 34 67 82 15 56 89 72 39 64 97 28 51 76 43 88 61进行正序排序。
2.统计总和、平均值、最大值、最小值
3.统计0-20、21-40、41-60、61-80、81-100的人数

提示
  • 使用 Random 类生成随机数

  • Array.Sort() 可以快速排序数组

  • 遍历数组时注意边界条件

输出预期结果

3.9.2 练习2:字符串处理工具

输出原始文本' Hello, this is a Sample Text for Processing! '
1.将原始文本反转。 2.单词计数
3.去除原始文本多余空格。
4.将文本首字母大写 5.统计字母在文本中出现的频率
额外功能测试:
原始字符为C# programming is FUN!
1.字符串长度
2.是否包含'pro'
3.将字符串中的FUN替换为awesome
4.查找'is'的位置。

提示
  • 字符串是不可变的,所有修改操作都会返回新字符串

  • 使用 Split() 方法分割字符串时注意空条目

  • ToUpper()ToLower() 用于大小写转换

预期输出结果

3.9.3 练习3:学生成绩管理系统增强版

1.两个数组,学生和科目,为下面数组随机生成成绩报告单

// 使用二维数组和字符串操作构建完整的学生成绩管理系统
string[] studentNames = { "张三", "李四", "王五", "赵六" };
string[] subjects = { "语文", "数学", "英语", "物理", "化学" };

2.统计每个学生的平均分和等级

 if (average >= 90) return "优秀";
 else if (average >= 80) return "良好";
 else if (average >= 70) return "中等";
 else if (average >= 60) return "及格";
 else return "不及格";

3.输入一个学生学生姓名,查询学生成绩单 4.各科平均分统计 5.成绩等级分布

提示
  • 二维数组使用 GetLength(0)GetLength(1) 获取维度

  • 字符串格式化使用 PadRight() 对齐输出

  • 合理使用方法分解复杂逻辑

预期输出

🎉 加油!完成所有练习后,你将熟练掌握C#数组和字符串操作!

附录

所有示例代码,均已上传网盘,请自行点击下方获取

微信公众号【.NET修仙日记】

posted @ 2025-11-05 22:18  云中小生  阅读(11)  评论(0)    收藏  举报  来源