C#练习作业

实现通用打印泛型类

在我们日常进行程序的编写与测试时,时常有需要将数组,栈,队列等的数据结构中存储的内容输出出来的需求,为了我们日常使用的方便,我们创建一个工具类的静态方法,解决这个问题。

为了实现通用这个属性,我们需要对这些数据结构进行分析,经过分析后,发现它们都继承了IEnumerable这个类,所以我们在定义参数类型时,需要限制传入的参数是IEnumerable这个类,又因为这些数据结构中存储的类型未知,所以它们的泛型约束为T。接着将传入的的数据结构按照for或者foreach进行打印即可。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DJConsoleProject
{
    //自定义工具类
    //泛型类
    internal class DJTools
    {
        //通用的打印
        static public void println<T>(IEnumerable<T> collection)
        {
            foreach (T item in collection)
            {
                Console.Write(item + " ");
            }
            Console.WriteLine();
        }
    }
}

计算遍历目录的耗时

计算遍历目录的耗时,首先要将遍历目录的方法写出来,很明显的需要借用递归进行遍历,以下是遍历目录的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace DJConsoleProject;
using System.Collections.Generic;

internal class DirectoryTraversal
{
    private int file_num=0;
    private Dictionary<string, int> ext_data = new Dictionary<string, int>();
    public void TraverseDirectory(string path)
    {
       
            string[] files = Directory.GetFiles(path);
            string[] directories = Directory.GetDirectories(path);

            // 遍历文件
            foreach (string file in files)
                {
                    FileInfo fileInfo = new FileInfo(file);
                    //Console.WriteLine("文件名为"+fileInfo.Name);
                    file_num += 1;
                    if(ext_data.ContainsKey(fileInfo.Extension))
                    {
                        ext_data[fileInfo.Extension]++;
                    }
                    else
                    {
                        ext_data.Add(fileInfo.Extension, 1);
                    }
                }
        // 遍历目录,并递归调用本方法
            foreach (string directory in directories)
                {
                    //Console.WriteLine("目录为:"+directory);
                    TraverseDirectory(directory);
                }


    }
    public void LookData()
    {
        Console.WriteLine("文件数量为:"+file_num);
        foreach (var item in ext_data)
        {
            Console.WriteLine(item.Key + ":" + item.Value);
        }
    }

}

上述代码可以遍历出所给的目录下的所有文件,然后在启动类中调用该方法,在运行方法前,创建Stopwatch类的实例对象,该类是专门用来测算程序运行的时间的,性能比Timespan类好且准确,推荐使用。 

using DJConsoleProject;
using System.Diagnostics;

Stopwatch sw = Stopwatch.StartNew();
sw.Start();
DirectoryTraversal directoryTraversal = new DirectoryTraversal();
directoryTraversal.TraverseDirectory("C:\\Users\\86134\\Desktop\\软件工程作业");
sw.Stop();
Console.WriteLine("共耗费{0}ms",sw.ElapsedMilliseconds);

在启动类中调用,并计算耗费的时间。以下时我的运行结果。

 

运算符的类型

算术运算符
  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • % 取模(求余数)
赋值运算符
  • = 简单赋值
  • += 加法赋值
  • -= 减法赋值
  • *= 乘法赋值
  • /= 除法赋值
  • %= 取模赋值
  • &= 位与赋值
  • |= 位或赋值
  • ^= 异或赋值
  • <<= 左移赋值
  • >>= 右移赋值
比较运算符(关系运算符)
  • < 小于
  • > 大于
  • <= 小于等于
  • >= 大于等于
  • == 相等
  • != 不相等
逻辑运算符
  • && 逻辑与
  • || 逻辑或
  • ! 逻辑非
位运算符
  • & 位与
  • | 位或
  • ^ 异或
  • ~ 按位取反
  • << 左移
  • >> 右移
条件运算符(三元运算符)
  • ?: 格式:condition ? value_if_true : value_if_false
成员访问运算符
  • . 成员访问
  • -> 结构体指针成员访问
特殊运算符
  • ?. 空条件运算符(空安全调用)
  • ?? 空合并运算符
  • ??= 空合并赋值运算符

三目表达式

在C#中,三目表达式(也称作条件运算符)是一种简化版的if-else语句,它可以让你在一行代码内基于某个条件来选择两个可能的值之一。三目表达式的语法如下:

条件表达式 ? 值如果真 : 值如果假;

这里的条件表达式必须产生一个布尔值(truefalse)。如果条件表达式的结果为true,那么整个表达式的结果就是值如果真,否则结果就是值如果假。例子:

int x = 10;
int y = 20;
int max = x > y ? x : y;
Console.WriteLine(max);  // 输出 20

运算符的优先级

在C#中,运算符的优先级决定了表达式中各个部分的计算顺序。当一个表达式包含多个不同类型的运算符时,高优先级的运算符会先于低优先级的运算符进行计算。优先级口诀:有括号先括号,后乘除再加减,然后位移再关系,逻辑完后再条件。如果分不清优先级,比较推荐多使用括号,可以更好的看出优先级。下表按最高优先级到最低优先级的顺序列出 C# 运算符。 每行中运算符的优先级相同。

运算符类别或名称
x.yf(x)a[i]x?.yx?[y]x++x--x!newtypeofcheckeduncheckeddefaultnameofdelegatesizeofstackallocx->y主要
+x-x、x~x++x--x^x(T)xawait、&&x*xtrue 和 false一元
x..y范围
switchwithswitch 和 with 表达式
x * yx / yx % y乘法
x + yx – y加法
x << yx >> yShift
x < yx > yx <= yx >= yisas关系和类型测试
x == yx != y相等
x & y布尔逻辑 AND 或按位逻辑 AND
x ^ y布尔逻辑 XOR 或按位逻辑 XOR
x | y布尔逻辑 OR 或按位逻辑 OR
x && y条件“与”
x || y条件“或”
x ?? yNull 合并运算符
c ? t : f条件运算符
x = yx += yx -= yx *= yx /= yx %= yx &= yx |= yx ^= yx <<= yx >>= yx ??= y=>赋值和 lambda 声明

break,continue,return的区别

在编程中,`break`、`continue`和`return`是控制流程的关键字,它们分别用于不同的目的。下面是这三种关键字的主要区别和用法:

1. **break**
   - 用途:`break`关键字用于完全退出循环(`for`、`while`、`do-while`)或`switch`语句。
   - 效果:当`break`在一个循环中被触发时,它会立即停止当前循环的执行,跳过循环剩余的部分,然后继续执行紧跟在循环之后的第一条语句。
 

 for (int i = 0; i < 10; i++)
     {
         if (i == 5)
             break;
         Console.WriteLine(i);
     }

执行结果:

2. **continue**
   - 用途:`continue`关键字用于跳过循环体中剩余的代码,并直接进行到下一次循环的开始。
   - 效果:当`continue`在一个循环中被触发时,它会立即跳过当前迭代中剩余的所有代码,然后开始下一次循环的条件检查。
 

 for (int i = 0; i < 10; i++)
     {
         if (i % 2 == 0)
             continue;
         Console.WriteLine(i);
     }

执行结果:

 

3. **return**
   - 用途:`return`关键字用于从一个函数或方法中返回,并可选地带回一个值。
   - 效果:`return`会立即结束当前函数或方法的执行,跳过所有剩余的代码,然后将控制权返回给调用者。如果函数有返回类型,`return`可以跟一个表达式一起使用,作为返回值。
   

int test()
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(i);
        if (i == 5)
            return 0;
    }
    Console.WriteLine("**********");
    return 1;
}
test();

运行结果:可以看出return后面的代码直接就没有运行。

在实际应用中,`break`和`continue`通常用于循环内部,以根据某些条件提前结束循环或跳过某次迭代。`return`则用于函数的任何地方,但通常位于函数的末尾,除非你使用它来提前退出函数。

冒泡排序 

冒泡排序的本质是双重for循环,它是比较慢的算法,因为它遍历一次数组只能确定一个元素的位置,外面的i控制需要遍历几次,才能排序成功,比如如果arr有7个元素,那么需要遍历6次,才能完全排序成功。里面的j控制每次遍历需要比较的次数,因为每次i遍历一次就确定了一个元素的位置,下一次的遍历就可以少比较一个元素,所以j=arr.Length-i-1。-1是因为数组是从0开始的,这就是冒泡排序的过程。

using DJConsoleProject;

int[] arr = {1,37,24,3,13,78,12,83,26,4};

for (int i = 0; i < arr.Length-1; i++)
{
    for (int j = 0; j <arr.Length-i-1 ; j++)
    {
        int temp = 0;
        if (arr[j] > arr[j+1])
        {
            temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
    }
}

DJTools.println(arr);

程序运行的结果: 

打印九九乘法表

打印九九乘法表是我们编程的一道基础题,使用双重for循环即可轻松实现。主要注意循环要从1开始,因为乘法表就是从一开始的。

for(int i=1;i<10;i++)
{
    for(int j=1;j<i+1;j++)
    {
        Console.Write("{0}*{1}={2}  ", j, i, i * j);
    }
    Console.WriteLine();
}

 程序运行结果:

文件找不到抛出异常

在我们的日常编程过程中,我们希望实现一个如果文件不存在,则抛出异常提示。我们可以通过throw抛出异常。该checkfile方法可以判断传入的路径是否存在,如果不存在就抛出文件不存在的警告。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DJConsoleProject
{
    public class checkfile
    {
        static public void FileCheck(string path)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException(string.Format("文件{0}未找到。",path));
            }
        }
    }

}

在启动类中调用,我传入的是我电脑中并不存在的路径。

using DJConsoleProject;

try
{
    string path = "C:\\Users\\86134\\Desktop\\软件工程作";
    checkfile.FileCheck(path);
}
catch (FileNotFoundException ex)
{
    Console.WriteLine(ex.Message);
}

 

以下是运行结果,在try的代码段中成功的抛出了FileNotFoundException类型的错误,并被成功的捕捉,打印出它的警告信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值