Bootstrap

C#-z4

1. 整数转换,整数和字符串,字符串和整数之间的转换怎么实现?

整数转字符串:

ToString()方法来完成这个转换

int number = 123;
string strNumber = number.ToString();
Console.WriteLine(strNumber);   

此外,ToString()方法允许你指定格式字符串,这样你就可以控制输出的格式。例如,如果你想以十六进制形式显示整数,你可以这样做:

int number = 255;
string hexString = number.ToString("X");  // X代表十六进制
Console.WriteLine(hexString);  // 输出: FF

另一个常见的格式化字符串是"N0",它用于显示带有千位分隔符的数字:

int number = 123456789;
string numberWithCommas = number.ToString("N0");
Console.WriteLine(numberWithCommas);  // 输出: 123,456,789

如果你想要更高级的格式化,比如固定小数点后的位数,你可以使用类似"F2"这样的格式字符串,其中2表示小数点后两位:

double number = 123.456789;
string formattedNumber = number.ToString("F2");
Console.WriteLine(formattedNumber);  // 输出: 123.46

请注意,虽然最后一个例子使用的是double类型,但ToString()方法同样适用于整数类型。如果你需要将整数转换为字符串,只需使用intlong或其他整数类型即可。

字符串转整数:

在C#中,将字符串转换为整数可以通过多种方法实现,其中最常见的是使用int.Parse()int.TryParse()方法。

使用 int.Parse()

int.Parse()方法将字符串转换为32位有符号整数。如果字符串不能被解析为一个有效的整数,该方法将抛出一个FormatException

string strNumber = "12345";
int number = int.Parse(strNumber);
Console.WriteLine(number);  // 输出: 12345

使用 int.TryParse()

int.TryParse()方法也是将字符串转换为整数,但它不会抛出异常。相反,它返回一个布尔值,指示转换是否成功。如果转换成功,它通过out参数返回转换后的整数值;如果转换失败,out参数将被设置为int类型的默认值(通常是0)。

string strNumber = "12345";
int number;
bool success = int.TryParse(strNumber, out number);
if (success)
{
    Console.WriteLine(number);  // 输出: 12345
}
else
{
    Console.WriteLine("转换失败");
}

其他转换方法

除了int.Parse()int.TryParse()之外,还可以使用Convert.ToInt32()方法,它提供了额外的转换选项,如指定基数(例如,二进制、八进制或十六进制)。

string hexNumber = "1A";
int number = Convert.ToInt32(hexNumber, 16);
Console.WriteLine(number);  // 输出: 26

总结

在实际应用中,推荐使用int.TryParse()方法,因为它可以避免因无效输入而导致的异常,使代码更加健壮。如果输入的字符串可能不符合预期的格式,使用TryParse()可以让你更优雅地处理错误情况。

2. 日期转换,获取当前日期,字符串转日期,日期转字符串怎么实现?

获取当前日期和时间

你可以使用DateTime.NowDateTime.UtcNow来获取本地或UTC的当前日期和时间。

DateTime localNow = DateTime.Now;
DateTime utcNow = DateTime.UtcNow;

日期转字符串

要将日期转换为字符串,你可以使用ToString()方法,并传入一个格式字符串来指定你想要的格式。

DateTime someDate = new DateTime(2023, 1, 1);
string dateString = someDate.ToString("yyyy-MM-dd");
Console.WriteLine(dateString);  // 输出: 2023-01-01

DateTime dt2 = new DateTime(2024,1,1,9,51,09);
Console.WriteLine(dt2.ToString());
 
Console.WriteLine(dt2.Year.ToString());
Console.WriteLine(dt2.Month.ToString());
Console.WriteLine(dt2.Day.ToString());

常见的格式化模式包括:

  • "yyyy-MM-dd": 四位年-两位月-两位日
  • "dd/MM/yyyy": 两位日/两位月/四位年
  • "HH:mm:ss": 24小时制的小时:分钟:秒
  • "hh:mm:ss tt": 12小时制的小时:分钟:秒 AM/PM

字符串转日期

要将字符串转换为日期,你可以使用DateTime.Parse()或更安全的DateTime.TryParse()方法。

string dateString = "2023-01-01";
DateTime parsedDate;
if (DateTime.TryParse(dateString, out parsedDate))
{
    Console.WriteLine(parsedDate);  // 输出: 1/1/2023 12:00:00 上午
}
else
{
    Console.WriteLine("日期格式不正确");
10}

如果字符串的日期格式不固定,或者有多种可能的格式,你可以使用DateTime.TryParseExact(),并提供所有可能的格式字符串。

string dateString = "01/01/2023";
string[] formats = { "dd/MM/yyyy", "MM/dd/yyyy", "yyyy-MM-dd" };
if (DateTime.TryParseExact(dateString, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsedDate))
{
    Console.WriteLine(parsedDate);
}
else
{
    Console.WriteLine("无法解析日期");
}

以上代码演示了如何在C#中处理日期和时间的转换,包括获取当前日期时间、日期格式化、以及从字符串解析日期。

3. 举例一维、二维、三维数组

一维数组

一维数组是最基础的数组形式,它相当于一个线性的数据列表。

// 定义一个一维整型数组
int[] oneDimensionalArray = new int[5];

// 初始化一维数组
oneDimensionalArray = new int[] { 1, 2, 3, 4, 5 };

// 或者在定义时初始化
int[] oneDimArray = { 10, 20, 30, 40, 50 };

二维数组

二维数组可以想象成一个表格,它具有行和列,可以看作是多个一维数组的集合。

// 定义一个二维整型数组
int[,] twoDimensionalArray = new int[3, 4];

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

// 或者在定义时初始化
int[,] twoDimArray = 
{
    { 13, 14, 15, 16 },
    { 17, 18, 19, 20 },
    { 21, 22, 23, 24 }
};

三维数组

三维数组可以看作是一个立方体,它有三个维度,通常用来表示三维空间中的数据。

// 定义一个三维整型数组
int[,,] threeDimensionalArray = new int[2, 3, 4];

// 初始化三维数组
threeDimensionalArray = new int[,,]
{
    {
        { 1, 2, 3, 4 },
        { 5, 6, 7, 8 },
        { 9, 10, 11, 12 }
    },
    {
        { 13, 14, 15, 16 },
        { 17, 18, 19, 20 },
        { 21, 22, 23, 24 }
    }
};

// 或者在定义时初始化
int[,,] threeDimArray =
{
    {
        { 25, 26, 27, 28 },
        { 29, 30, 31, 32 },
        { 33, 34, 35, 36 }
    },
    {
        { 37, 38, 39, 40 },
        { 41, 42, 43, 44 },
        { 45, 46, 47, 48 }
    }
};

注意,在初始化多维数组时,数组的维度必须匹配。例如,在二维数组中,每一行的列数必须相同;在三维数组中,每一层的行数和列数也必须相同。

4. 需求:有个88笔费用记录,总额3亿,金额在300万~800万之间,随机数如何实现?并记录总耗时。

// 引入System.Diagnostics命名空间,用于使用Stopwatch类
using System.Diagnostics;

// 创建一个随机数生成器
Random rand = new Random();

// 创建一个计时器,用于记录生成随机数所花费的时间
Stopwatch stopwatch = new Stopwatch();

// 开始计时
stopwatch.Start();

// 初始化一个空的列表,用于存储生成的随机数(费用)
List<int> fees = new List<int>();

// 设置总的金额
int totalAmount = 300000000;

// 设置需要生成的随机数(费用)的数量
int count = 88;

// 计算平均每个随机数(费用)应该大约是多少
// 注意:实际生成的数值由于随机性不会严格等于这个平均值
double averageAmount = (double)totalAmount / count;

// 循环生成指定数量的随机数(费用)
for (int i = 0; i < count; i++)
{
    // 生成一个介于300万到800万之间的随机整数(包含上下限)
    // 注意:这里rand.Next()的上限参数是开区间,即8000001是不包含在内的
    int amount = rand.Next(3000000, 8000000);

    // 将生成的随机数添加到列表中
    fees.Add(amount);

    // 从总金额中减去本次生成的随机数
    // 这是为了尽可能使生成的随机数总和接近3亿
    // 但实际总和由于随机性可能不会恰好等于3亿
    totalAmount -= amount;
}

// 停止计时
stopwatch.Stop();

// 输出整个生成随机数的过程所花费的时间,单位为秒
// 使用string interpolation(字符串插值)来方便地在字符串中嵌入变量值
Console.WriteLine($"Total time taken: {stopwatch.Elapsed.TotalSeconds} seconds");

5. 简述常见的集合类型的存储结构和它们的作用以及优缺点,并写出实现案例

1. List<T>

  • 存储结构:动态数组。List<T>在内部使用一个数组来存储元素,当数组满时,它会自动扩容。
  • 作用:适用于需要频繁访问和修改元素的场景。
  • 优点
    • 提供了索引访问,查找元素速度快。
    • 支持动态增长和缩减。
  • 缺点
    • 插入和删除元素时,如果不在数组末尾,需要移动大量元素,效率较低。
  • 实现案例
    List<int> numbers = new List<int>();
    numbers.Add(1);
    numbers.Add(2);
    numbers.Insert(1, 3); // 插入慢
    numbers.RemoveAt(0); // 删除中间元素慢
    Console.WriteLine(numbers[1]); // 快速随机访问

2. Array

  • 存储结构:固定大小的数组。
  • 作用:用于存储固定数量的同类型元素。
  • 优点
    • 访问元素非常快。
    • 内存占用相对较小。
  • 缺点
    • 大小固定,一旦创建后无法改变。
  • 实现案例
    int[] arr = new int[5] { 1, 2, 3, 4, 5 };
    Console.WriteLine(arr[2]);

3. HashSet<T>

  • 存储结构:基于哈希表。HashSet<T>使用哈希函数将元素映射到桶中,桶中存储元素的引用。
  • 作用:用于存储不重复的元素,提供快速的查找和插入。
  • 优点
    • 查找、插入和删除操作的平均时间复杂度为O(1)。
  • 缺点
    • 不保持元素的插入顺序。
    • 需要一个良好的哈希函数以减少冲突。
  • 实现案例
    HashSet<int> uniqueNumbers = new HashSet<int>();
    uniqueNumbers.Add(1);
    uniqueNumbers.Add(2);
    uniqueNumbers.Add(2); // 不会被添加
    foreach (var num in uniqueNumbers)
    {
        Console.WriteLine(num);
    }

4. Dictionary<TKey, TValue>

  • 存储结构:基于哈希表的键值对集合。
  • 作用:用于存储键值对,键是唯一的,用于快速查找对应的值。
  • 优点
    • 查找、插入和删除操作的平均时间复杂度为O(1)。
  • 缺点
    • 键必须是唯一的。
    • 需要一个良好的哈希函数以减少冲突。
  • 实现案例
    Dictionary<string, int> scores = new Dictionary<string, int>();
    scores.Add("Alice", 90);
    scores["Bob"] = 80;
    if (scores.ContainsKey("Alice"))
    {
        Console.WriteLine(scores["Alice"]);
    }

5. Queue<T>

  • 存储结构:先进先出(FIFO)队列。
  • 作用:用于处理需要按顺序处理的元素队列。
  • 优点
    • 自动管理队列中的元素顺序。
  • 缺点
    • 插入和删除操作的时间复杂度为O(1),但访问中间元素较慢。
  • 实现案例
    Queue<string> messages = new Queue<string>();
    messages.Enqueue("Hello");
    messages.Enqueue("World");
    Console.WriteLine(messages.Dequeue());

6. Stack<T>

  • 存储结构:后进先出(LIFO)栈。
  • 作用:用于处理需要按后进先出顺序处理的元素堆栈。
  • 优点
    • 自动管理栈中的元素顺序。
  • 缺点
    • 只能访问栈顶元素,访问或修改其他元素较慢。
  • 实现案例
    Stack<int> stack = new Stack<int>();
    stack.Push(1);
    stack.Push(2);
    Console.WriteLine(stack.Pop());

7.LinkedList<T>

存储结构:双向链表,每个元素包含指向前后元素的链接。

作用:用于存储元素集合,提供高效的插入和删除操作。

优点

  • 插入和删除元素快,无需移动其他元素。

缺点

  • 随机访问效率低,需要遍历链表。
  • 每个元素需要额外的存储空间用于链接。
LinkedList<int> myList = new LinkedList<int>();
LinkedListNode<int> node = myList.AddLast(1);
myList.AddAfter(node, 2);
int firstItem = myList.First.Value;

这些集合类型的选择取决于具体的应用场景和性能需求。例如,如果需要快速的随机访问,可以选择ArrayList<T>;如果需要快速查找,可以选择Dictionary<TKey, TValue>HashSet<T>;如果需要在集合中频繁插入和删除元素,则LinkedList<T>可能是更好的选择。

;