zoukankan      html  css  js  c++  java
  • 2.1 C#语法的学习(一) && 循环

    准备工作

    下面让我们以管理员身份运行Visual Studio,新建一个控制台项目,开始C#语法的学习。
    以管理员身份运行Visual Studio的问题,请直接搜索关键词:以管理员身份运行 Visual Studio。

    可以看到,连官方都有正解的,你没有理由不会!剩下的内容请自行摸索,很简单。
    打开Visual Studio后,完成初始化设置,新建一个.net core的控制台,命名为CSharpGrammarLearnConsole。


    Visual Studio的使用

    在开始学习C#前,最好先对Visual Studio有个初步的了解

    在菜单栏的View(视图)中,可以对工具栏、各种窗口的显示、隐藏进行修改,也可以通过拖拽,更改各个窗体的位置。这个根据个人的习惯和使用进行调整即可。

    在调试过程中,Visual Studio会发生变化,对于调试来说,比较重要的窗口有LocalsImmediate WindowWatch
    如图所示,在代码上打上断点(红点),程序会停在这里,然后可以在Locals窗口查看并修改当前的变量,Immediate Window则可以进行一些即时的运算,Watch则是自定义Locals,可以输入一些自己的关注点,以便多次调试的时候查看变化。
    更多详细的教程可以看欢迎使用 Visual Studio IDE
    Visual Studio比较重要的技能包括项目管理、调试和远程调试、git版本控制、生成与发布、扩展与更新Visual Studio。其他内容比如代码分析、性能测试等等,个人认为可以按需学习,用到的时候再看都可以。

    控制台程序

    控制台程序有一个入口,是Program的Main()方法,运行程序后,程序会从Main()方法开始执行。

    学习资料 && 学习方式

    C#的教学文章、视频,中文的、英文的、官方的、非官方的,很多很多,我在此不赘述,就推荐两个个官方的和一个非官方的吧。
    C# 官方文档
    .NET 官方文档
    菜鸟教程-C# 教程
    看了之后是不是觉得有点无从下手,或者不知道可以用它来干什么?很正常,正经的、归纳性的教程就是这样,因为它们更专注于知识点本身,其存在的意义是使大家学会使用XXX,比如学会理解并使用数组、属性、委托和事件。
    但它们并不会告诉你数组可以用来完成什么工作,在哪些场景推荐使用它,哪些场景不推荐,它们更多的时候是用来查阅的。比如我很久没有使用委托和事件了,不记得该怎么写了,我也会查一下关键词,随便找一篇文章扫一眼恢复一下记忆—————不必为这种行为感到羞耻,人的大脑不会记住所有事,而语法、语言对于开发者来说也不是非常重要的东西(初学者除外)。计算机思维、设计模式、解决一个问题的思路,这些才是重要的、需要深入理解的东西。
    讲C#语法这部分,我想更多的以解决某个问题,促成计算机思维的方式来完成。然后重点讲几个重要的思想:排序穷举递归循环
    在具体的语法上面不会做过多赘述,具体的、不明白的地方,看看上面提到的百科全书式的文档,都可以解决,我在用到的时候也会把具体的链接贴出来,请大家放心。希望大家可以和我一起来学习。

    第一个问题

    求1+2+3+„„+10的和。

    数学解法

    我们都知道,运算

    1+2+3+4+5+6+7+8+9+10=55
    

    但C#是不能写1+2+3+4+5+6+7+8+9+10=?这种等式的,等号左边不能写表达式,右边也不能写?。
    所以我们细想一下,实际上我们计算的方式是(不考虑1+9=10,2+8=10这种计算,按顺序执行求和)

    1+2=3
    3+3=6
    6+4=10
    ......
    45+10=55
    

    看明白了么?第一个数字和第二个数字求和,然后求和结果去同第三个数字求和,一直求和到最后一个数字。
    理解了如何计算出55这个结果,我们就可以开始写代码了。

    C#写法

    首先定义一个记录结果的变量

    var result=0;
    

    (强烈不建议命名x,y,z blabla,命名一定要有意义!有意义!有意义!重要的事情说三遍——————当然有时候命名会又臭又长,但是还是要好好命名~)
    然后我们开始计算

    result = result + 1;
    

    这里和数学公式的概念完全不同。
    在数学里,这是等式,表示result 等于 result + 1,这个等式并不成立。
    而在计算机语言里,这里是赋值,是告诉计算机,计算result + 1的值,并且把值赋给result。所以这个语句执行完毕后,result将等于1。
    C#语言中的等式,是双等号==,意义也与数学的等式有所差别,在此不扩展来说。
    然后我们继续计算

    result = result + 1;
    result = result + 2;
    result = result + 3;
    result = result + 4;
    result = result + 5;
    result = result + 6;
    result = result + 7;
    result = result + 8;
    result = result + 9;
    result = result + 10;
    

    然后输出结果

    Console.WriteLine(result);
    

    点击菜单栏下方工具栏中的绿色启动按钮,即可运行程序。

    得到结果:

    至此,我们完成了把一个问题通过代码来解决的过程。我们做了什么?分析问题-描述算法-把算法写成代码。
    不论是什么开发语言,什么问题,都是这样的过程。如果逻辑、算法是不清晰的,代码也是没有办法写的。

    或许有人会问,1-10求和,我自己也能算,我为什么还需要学习计算机如何计算?因为计算机不仅可以计算1-10,还可以快速的计算1-100、1-10000、1-99987的求和啊,计算机可以帮助人们快速进行大量的计算,这也是我们学习计算机的目的之一。
    下面我们继续分析我们的代码,上述的写法固然可以得到正确的答案,但写的太过冗余,比如如果求和1-100,不是要写100行代码么?这肯定不科学。
    累加求和工作内容是固定且重复的,我们可不可以换种轻松的方式来写呢?这时候我们需要一个新的概念,循环

    循环

    循环的详细描述和用法可以看C# 循环,我们直接开始使用吧~
    我们现在转变一下思路:
    我们有一个记录循环次数的变量i,
    我们需要10次循环,让i从1递增到10(包括10),
    则每次计算result = result + i,
    最后得到的result就是最终结果。
    所以代码是

    var result = 0;
    for (int i = 1; i <= 10; i++)
    {
    	result = result + i;
    }
    Console.WriteLine(result);
    

    是不是简洁很多?而且发现没有,只需要修改10这个数字,我就可以求和1-任意数字的累加和!
    那么问题又来了,我想计算1-999、1-8976,应该怎么办呢?我们或许需要交互来帮助我们完成工作。

    交互

    我们日常的鼠标点击、键盘输入,其实都是交互。比如,鼠标点击了文本框的某一行,光标到达了这一行的某个位置,其实是我们输入了点击这个位置的操作,计算机输出“光标达到这一行”的结果。比如,键盘按下A,文本框输出a,键盘按下Shift+A,文本框输出A,都是计算机根据我们的指令完成工作。
    所以同样的,现在我们的工作是,询问程序使用者,求和1-多少,并且输出结果。
    在控制台程序中,我们需要用到Console类来帮助我们完成工作。

    //询问
    Console.WriteLine($"求和1+2+3,,,+n,请输入n的具体数字。");
    //得到输入
    var n= Console.ReadLine();
    //C#是强类型,转换类型
    var endNumber = int.Parse(n);
    var result = 0;
    for (int i = 1; i <= endNumber; i++)
    {
    	result = result + i;
    }
    Console.WriteLine(result);
    

    这是一个正确的程序,但并不是一个健壮的程序,比如输入的不是数字,而是其他字符串,就会报错:

    对于一个开发者来说,我们不能信任用户的任何输入,我们需要用我们的代码作为武器,去规避、预防、解决这些错误的输入。

    判断

    在这里,我们可以使用TryParse方法来替换Parse方法。
    同时,我们使用了一个if-else的判断条件(C# 判断)。
    关于判断更多的内容可以看“2.5 C#语法的学习(五) && 判断”。

    var endNumber = 0;
    bool isSuccess=int.TryParse(n,out endNumber);
    if (isSuccess)
    {
    	var result = 0;
    	for (int i = 1; i <= endNumber; i++)
    	{
    		result = result + i;
    	}
    	Console.WriteLine(result);
    }
    else
    {
    	Console.WriteLine($"错误的输入{n}");
    }
    

    TryParse方法尝试将n转换为int类型,并且赋值给endNumber。isSuccess的结果则是TryParse是否执行成功。
    所以,我们使用isSuccess+if-else语句进行判断:如果isSuccess==true,则进行累加求和计算,如果isSuccess!=true,则输出错误提示。
    至此,我们学会了处理异常的输入。
    但这里似乎还是有一些不方便的地方,比如我如果想多次求和,1-100、1-999,我只能选择:打开一次程序-输入数字-得到结果-关闭程序,然后再次打开程序,重复操作。而且当我录入错误的时候,我还是只能关闭程序,再次打开重新输入。这并不合理。我们期望的效果是,这个程序可以多次计算求和,并且在我们不需要的时候,被我们手动关闭。
    我们在求和的时候,用到了循环,来重复的完成一些工作,那么现在我们是不是可以继续使用循环,来解决现在的问题呢?循环整个输入-计算-输出的过程,就可以了~(看到了么,重复性的工作,用循环来解决)

    //这里是一个无限循环,一般在开发中不常见,容易出现问题
    while (true)
    {
    	//我们需要循环的方法
    }
    

    实现效果:

    小结

    1.Visual Studio的基本使用
    2.等号与双等号在C#中的不同含义
    3.循环
    4.交互
    5.判断
    6.程序的正确性与健壮性

    延展

    1.不能信任用户的输入,在早期有非常严重的体现,就是sql注入。黑客通过系统的漏洞,通过输入不正常的、带有恶意的文本,非法获得系统数据,并对系统进行攻击,让开发者苦不堪言。所以对用户输入的审查,是至关重要的。现在大部分用户输入的校验都在前端、客户端完成,即在没有调用服务的时候,就对输入进行排查,不合法直接不提交数据。
    2.while(判断条件)/do-while(判断条件)使用时一定要注意,有时候可能会造成无限循环。
    比如,下面这种忘记给number计数。

    var number = 0;
    while (number < 100)
    {
    	//完成某件事情
    
    	//忘记写这句话
    	//number++;
    }
    

    或者更复杂一点,认为判断条件会在某个时间点为false以跳出循环,但某些情况下并不会实现。这种在开发过程中也并不一定会调试出来,可能开发过程中遇不到这种情况。比如尝试下载图片,下载图片完成才能进行下一步操作(显示图片)。正常情况下,下载完成-展示图片,没有问题,但如果遇到网络原因,造成下载图片失败,这种代码就会一直卡在这一步,造成无限循环。
    那正常情况下应该怎么处理呢?不知道?我们可以马上知道。
    把你的手机wifi、流量都关掉,然后打开淘宝,随便点一件商品,或者打开微信,随便看一篇文章——————这也是一种借鉴的思维,不知道,就去找类似的、你觉得它可能会出现的地方。
    然后我们就知道了,它会告诉我们,你的网络崩溃了。那我们的程序是不是应该这样做:
    (1)尝试下载图片,并计数尝试下载次数
    (2)如果下载成功,展示图片,完成工作
    (3)如果下载失败,判断尝试下载次数,
    次数没有达到上限100次,则回到(1)重复下载工作
    次数达到上限,告知用户下载失败了并指引他后续操作,完成工作
    这样的逻辑让这项工作成功、失败的时候,都有了一个“结束”的地方,保证了程序的健壮性。
    转换成C#代码如下:
    当且仅当尝试下载次数小于100,且下载没有成功时,执行下载操作。

    bool isDownloadSuccess = false;
    var number = 0;
    while (number < 100 && isDownloadSuccess==false)
    {
    	//下载图片
    	//如果下载图片成功,则设置:
    	//isDownloadSuccess = true;
    
    	//计数下载次数
    	number++;
    }
    

    这里还有一个小小的点,下载图片(特别是下载别人家的内容)过于频繁可能会被封掉,被判定是爬虫,所以可以在每次循环的末尾加上一个短时间的、手动的休眠Thread.Sleep(500);

    示例代码

    上述的大部分代码被上传到CumulativeSum
    在Program的Main()方法中取消注释,就可以运行。

    题外话

    这篇真的是写的,越写越多越写越多,感觉要说的太多了,跟写小论文似的。
    因为定位是零基础,所以写的很细,很口水,很简单。后面我也会写得很细,但是相同的问题就会一笔带过,不再重复,所以一定要仔细看哦~

  • 相关阅读:
    python中的json
    vmware workstation中的NAT配置
    python内置的一些模块
    datetime
    线程池的工作过程示例
    java io read中申请读的长度与实际长度不同|RocketMQ源码
    RocketMQ集群搭建及安装rocketmq-console
    使用MAT分析JVM内存溢出
    jdbcTemplate小用总结
    Spring线程安全为何非安全,场景重现,解决安全小结
  • 原文地址:https://www.cnblogs.com/Lulus/p/12343002.html
Copyright © 2011-2022 走看看