780 0
2016-03-14 Dodu 业界资讯

前面我们接触了数据类型和变量、操作符以及常用的控制流语句,利用这些知识我们已经可以写一些简单的程序。本文我们通过实际的例子对C#语言中的方法进行学习,并对涉及到前面学习过的知识进行回顾。

再强调,我们的目标人群是初学者,有经验的朋友自觉点击右上角。但初学者仅仅靠几篇文章是不能掌握语言的,这里只能作为辅助,还要自己下功夫。

本文我们将完成一个比较有趣的程序,它包含三个功能:

1、通过输入要查询的数字和国家代号查询近15天内各个国家必应壁纸(图片描述+地址);

2、将查询到的壁纸下载到本地电脑中;

3、将下载得到的壁纸设置为桌面背景;

顺便也了解了这些内容:

4、控制台应用程序输入输出操作;

5、从字符串中截取部分字符串(从网页源码中获取地址);

在开始之前先对方法有一个感性的认识。

我们的程序支持循环查询并可还可能会对功能进行扩展,那么以上这些功能需要重复使用,为了使用上的方便以及代码的易读性(全部写在一块必然是一锅乱粥),最好的办法就是对这些功能进行分块,每个功能被包装成一个黑盒子,对于使用这些功能的人来说,不需要去知道其内部的具体实现方式,只要将必需的信息传送给黑盒子(参数),它就应该返回我们所需的信息(返回值),这个黑盒子便是方法。注意,有些情况下不需要输入信息或输出信息,即方法可以有无参数,也可以有无返回值。下面我们看看方法长什么样子。

1、首先新建一个控制台应用程序

打开Visual Studio 2015,新建——项目,如下图所示,在模版——Visual C#——Windows中选择控制台应用程序,项目名称填写为bing,确定即可。注意记录下项目路径。

▲新建项目

新建项目仅包含如下所示代码:

▲新建项目默认代码

回顾之前类(class)的概念,C#程序是由一个或多个类组成的,就好比一场音乐会,有拉小提琴的、有吹小号的……我们可以根据类实例化出多个基于该类的对象,比如拉小提琴的有5个…当然这里的类可被实例化的前提是,他是一个非静态类。对于静态类,是不能被实例化的。

在上面的代码中只包含一个Program类,注意它的定义方式,class后面跟类名,而类的内容被包含在一对大括号中。

在类的内部就可以包含一些方法,表示这个类可以完成的一些功能。在上面的代码中,包含了一个名为Main的方法,它同时也是应用程序运行的起点,具有固定的名称,不可更改。而且必须是静态方法(用static修饰),不需要对类进行实例化就可以运行。Main方法默认前面用void进行修饰,void即表示方法不需要返回数据。方法名后有一对圆括号,用于向方法传递参数。方法的主体内容则都放在紧随其后的一对大括号中。

有了Main方法,我们就可以在其中写一些代码,编译运行,我们所写的代码就会依次执行。

注意到,在类代码外层还有命名空间(namespace),这是对类进行分类的一种方式。比如一个项目需要多人完成,为了避免类名冲突,将各自的类放在不同的命名空间中做区分。新建项目默认将类放在以项目名为名称的命名空间中。

方法的调用:

在编写代码时,我们经常会使用平台为我们写好的现成方法,要使用这些方法,分两种情形:

对于静态方法,直接通过类名进行调用,方法为:

类名.方法

对于非静态方法,需要通过类的实例化对象进行调用,方法为:

对象名.方法

由于这些类与我们项目中的类不在同一个命名空间,因此需要通过using语句将其命名空间添加近来,在代码的最顶部就可以发现有若干using语句。

对于类内部的方法,则可以直接通过方法名进行调用。

2、获取用户输入

在控制台应用程序中进行输入和输出分别使用System命名空间中的Console.ReadLine()和Console.WriteLine()方法。(实际上是Console静态类中的两个静态方法)。

Console.WriteLine()方法没有返回值,只需将需要输出的值放在括号内即可在控制台中输出。

Console.ReadLine()则会将我们在控制台中输入的一行字符作为字符串返回。那么我们可编写出如下图所示的三行代码,每一行都是一条语句,每条语句都以英文分号结束:

▲控制台输入和输出

这里第一行语句只是简单的给出一个提示(提示内容作为参数传入),第二行会等待用户输入,输入完成后回车程序会将输入内容返回并赋值给day字符串变量,第三行则输出day字符串变量,只是为了验证一下我们的输入。点击上图中顶部的绿色启动按钮,编译运行,验证一下程序是不是正常,如下图所示:

▲控制台输入和输出演示(第二行为输入,第三行为输出)

注:运行完成后控制台窗口会自动关闭,这是正常现象。

我们的目标是由用户输入两个参数,即日期和国家代码,将这两个参数分别赋值给day和mkt两个字符串变量,那么可编写如下代码:

▲控制台获取两个数据

但这样的代码看起来可能不太直观,我们尽可能让代码看起来更简洁一些,于是我们开始编写我们的第一个自定义方法——获取用户输入。

▲将从控制台获取数据包装为方法

这个方法我们将它取名为GetInputString,圆括号内指定了方法要求传入的参数(称为形参),这里需要一个字符串类型参数,方法名前面的string修饰符表示该方法需要返回一个字符串值。方法内的第一条语句接受参数值,并输出作为提示,这里我们使用了另外一个方法Console.Write,它在输出提示内容后不换行。第二条语句通过return关键字返回程序运行时你所输入内容。

在Main方法中我们也改写了之前的代码,通过调用GetInputString方法,将提示语作为参数(调用者为方法传入的值称为实参,与形参必须是一一对应的),方法将用户输入内容赋值给两个字符串变量。至此我们已经完成了用户输入的获取。下面我们将根据用户的输入获取我们想要的东西——必应壁纸!

注意:在命名上我们有一些约定,对于方法名我们采用Pascal风格,即每个单词的第一个字母都大写,对于方法内部的变量(局部变量)和参数,则采用camel风格,即第一个字母小写,其余单词首字母大写。这并非强制规范,但是一种建议遵守的约定。

3、根据输入获取查询结果并输出

我们要从网页中获取必应壁纸查询结果,为了降低复杂度,豆豆简单制作了一个Web查询API,http地址规则如下:

http://test.dou.ms/bing/day/-1/mkt/zh-cn

其中day后面的数字即表示哪一天,可取值为-1、0、1…到15,分别表示明天(提前一天预览)、今天、昨天、前天…..15天前。mkt后面的zh-cn表示国家代码,可取值为JA-JP、ZH-CN、EN-IN、DE-DE、FR-FR、EN-GB、PT-BR、EN-CA、FR-CA、EN-US、EN-WW、EN-AU,其所代表的国家就不一一介绍了,这里也不区分大小写。那么上面这个地址其实是必应中国明天的壁纸信息(每天都在更新),也可通过浏览器打开,页面返回的只是简单的一串字符。当然,在与服务器进行数据传递时有更规范的数据格式,比如JSON、XML,但我们不想把事情搞“复杂”。

这里直接给出编写好的从http地址获取网页内容的方法GetHttpData,如下图所示:

▲从网页中获取数据的方法

该方法以地址作为参数,并返回网页内容(字符串)。这里面用到了四种类,分属System.IO、System.Net两个命名空间,因此需要在代码的最前面加上两行using语句。关于方法内每条语句的作用,可参考图中的注释,具体的代码含义等到学习过类的更多相关知识后会充分理解。

在C#语言中//表示行内注释,即在本行内,该符号后面的文字都被视为注释,注释是提供给人阅读的内容,有无注释对程序本身并无影响。

下面我们根据用户输入的两个参数直接调用上面的方法从对应地址获取到查询结果,代码如下图所示:

▲调用方法,获取网页内容

这里我们对字符串进行了拼接,字符串拼接使用+操作符,并将拼接好的字符串赋值给url字符串变量。然后以url为参数调用GetHttpData方法,并将返回的网页内容赋值给content字符串变量,最后将其输出。运行结果如下图所示:

▲查询结果

同样我们也可以对根据用户输入参数获取网页内容的过程进行包装,得到一个方法,命名为GetBingData,并改写Main方法中相关的代码,最终如下图所示:

至此,我们已经完成了根据参数获取必应壁纸信息的任务。

4、从查询结果中提取图片地址

上一步我们已将查询结果作为字符串存储在content变量中,接下来需要从中提取出图片地址,观察一下其实我们只需要在返回的字符串中截取“地址:”后面的字符串即可。在C#中字符串也是一个类,它有自己的方法,其中Split()方法的作用就是分割字符串,我们利用它来写一个自定义方法GetBingImageUrl,专门用来从查询结果中提取出图片地址,如下图所示:

同时我们在Main方法中调用自定义方法GetBingImageUrl获取了查询得到的必应图片的地址。

5、根据地址将文件下载到本地电脑

下载Http文件,可使用System.Net中提供的WebClient类的DownloadFile方法,同样,我们把这个功能写成一个方法DownLoadImage,如下图所示:

其中传递给DownloadFile的第二个参数为想要保存的文件名,Path.GetFileName()方法用于从地址中获取文件名和扩展名,最终文件被保存在与程序文件相同的目录(项目文件夹的\bin\Debug目录下)。

6、将下载到的图片设置为桌面背景

设置桌面壁纸我们需要调用Windows API来实现,对应的方法SystemParametersInfo在"C:\Windows\System32\user32.dll"文件中,在C#中调用Windows API需要从DLL中导出函数(使用DllImport特性,需要引入System.Runtime.InteropServices命名空间),即声明一个外部函数,具体方法如下图所示,外部函数用extern进行修饰,方法没有主体代码,并且为静态。

同时我们调用该静态方法自定义了一个用于设置桌面壁纸的方法SetWallpaper,以壁纸在本地电脑中的路径为参数。

随后在Main方法中我们调用了SetWallpaper方法设置了桌面壁纸。其中,Directory.GetCurrentDirectory()用于获取应用程序所在的目录,与文件名一起拼接成图片的完整路径。注意到,拼接时中间的路径分隔符使用了\\,这是因为\在代码中有特殊的用途(用作转义),将其作为字符使用时需要对其进行转义,而转义符又恰好是\。

最后为了实现重复查询,我们通过while语句将Main方法中的代码包起来,while语句的判断条件设置为true,结果就是while中的语句将循环不断地执行,直到关闭应用程序。最终Main方法中的代码如下,这样看起来思路还是比较清晰的。

最后编译运行代码,结果如下图:

▲最终效果

到此我们就完成了一个简单的必应壁纸查询工具,并且兼具壁纸下载和设置桌面壁纸功能。当然,程序还有很多不完善,比如你需要确保输入的参数没有错误,否则会引发异常。

源代码文件下载网盘下载(密码:fcbd)


发表评论: