方法是包含一系列语句的代码块,也可称为函数。方法的作用是模块化我们的程序,以及提高代
码的可重用性和可共用性。方法也可以看作就是实现某个功能的工具。比如现实生活中我们想要喝果
汁可以自己动手榨果汁,也可以使用榨汁机这个工具来榨果汁,当然使用工具更简单方便些,又比如
在我们程序中想要输出一些信息到控制台,不用我们自己写代码来完成输出信息的功能,而只要调用
Console 控制台类的 WriteLine 方法就可以实现输出信息到屏幕的功能了。
在 C#中,方法分为静态方法与非静态方法。非静态方法也称为实例方法。在声明方法的语法中,
实例方法不带 static 关键字,而静态方法有 static 关键字修饰。在本章中我们只了解静态方法,而
实例方法在以后的课程中再进行学习。
2.1、静态方法
在类中定义静态方法的语法如下。
[访问修饰符] static 返回类型 方法名 ([ 参数列表 ]) { 方法体; }
对此语法结构,作以下说明。
1、访问修饰符:可选,一般来说使用 public 和 private。默认为 private,这样的方法只能在类
的内部调用。
2、返回类型:可以是常见的系统基本类型(如 void、int、float、string 等),也可以是自定义
的类型(如对象类型等)。值得注意的是,如果类型是 void,则代表方法没有返回值;如果是其
它类型,则有返回值,方法体必须有 return 语句,通过 return 语句来返回结果。
3、方法名:如果是 public 修饰的方法,则采用帕斯卡命名法;否则,则采用驼峰命名法。
4、参数列表:可选,作用是接收用户传递过来的数据。参数列表是由逗号分隔的变量组成的,每
个参数都要带数据类型。
根据语法及说明,我们可以在类中定义一个最简单的方法试试,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { public static int Sum(int a, int b) { Console.WriteLine(a+"+"+b+"="); return a + b; } public static void Hello(String name) { Console.WriteLine("你好,"+name); } static void Main(string[] args) { Hello("张三"); Hello("李四"); Hello("王五"); int r = Sum(1, 1); Console.WriteLine(r); Console.WriteLine(Sum(100, 200)); } } }
通过上面的代码,我们定义了一个最简单的方法,访问修饰符和参数列表都省略没有写,以及方
法也没有返回值,所以方法的返回类型是 void,另外我们在本章中只了解静态方法,所以在定义方法
时都要加上 static 静态关键字, 然后我们可以看出其实现在定义的这个打招呼的方法跟之前我们一
直在用的 Main 方法只是方法名不一样,其他的代码完全一模一样。
注意 :定义方法的代码,可以写在 Main 方法定义的前面,也可以写在 Main 方法定义的后面,但
不能写到 Main 方法的一对大括号中,这是初学者经常会犯的错误。
当然现在上面程序运行后,屏幕上并不会显示大家好,而是什么都没显示。这是因为 Main 方法才
是程序的入口,程序运行时系统会自动调用 Main 方法,而我们定义的 Hello 方法没有被调用,所以
Hello 方法里面的代码没有被执行。那么如果我们希望 Hello 方法在程序运行时可以被执行,就可以
在 Main 方法中调用 Hello 方法即可,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication7 { class Program { static void add(int n) { int sum = 0; for (int i = 1; i <= n; i++) { sum = sum + i; } Console.WriteLine("和为:" + sum); } static void Main(string[] args) { add(100); add(95); add(999); } } }
调用方法很简单,只要写方法名,后面再加上一对小括号就可以了。注意小括号必须要写,无论
是定义方法还是调用方法,无论是有参数还是没参数,都必须要有小括号。
课堂作业:定义一个 Introduce 自我介绍的方法,然后在 Main 方法中调用它,运行看效果。
2.2、方法的参数
最简单的方法是不带参又没有返回值的方法,复杂一点的话我们可以定义带参的方法,在方法中
定义参数的目的是接收要处理的信息和数据,比如你用榨汁机时必须要放入水果才可以榨汁,有些方
法在实现功能时,必须要先接收一些数据,则这些方法就要定义成带参的方法,以及定义参数时必须
声明数据类型,比如榨汁机只能接收水果,不能接收其它类型的东西。
在方法中,参数的定义方式一般是这样的:
[访问修饰符] 返回类型 方法名称([ 参数类型 参数名1 1 ,参数类型 参数名 2, … , 参数类型 参数名称n n]) { 方法体 }
参数类型可以是系统类型,也可以是用户自定义类型,参数的名称的命名方式与变量类似,事实
上在方法中设定的参数可以在方法体内以变量的方式来使用,一个方法可以带多个参数,但是在同一
个方法的参数列表中不能出现两个名称完全相同的参数。
接下来我们定义一个带参的方法,实现求平方的功能,接收用户输入一个整数,代码如下:
class Program { //定义一个求平方的方法 static void Square(int num) { Console.WriteLine(num + "的平方是:" + num * num); } //定义一个Main方法(主方法,程序的入口) static void Main() { Square(8); //调用Square方法 } }
注意定义方法时声明了参数,那么在调用方法时就必须要传入参数,我们可以把定义方法时的参
数叫做 形式参数,简称 形参,把调用时传递的参数叫做 实际参数,简称 实 参。实参可以是常量、变
量、表达式或者方法等。在调用时,实参的值将按顺序传递给形参接收。在上例中 num 就是形参,而
调用方法时传入的数字 8 就是实参。
课堂作业:
1、定义一个 FoodQuery 方法,接收用户输入星期几,然后实现输出饭堂对应菜单的功能。并在
Main 方法中调用它,运行看效果。
2、定义一个 Rectangle 方法,接收用户输入行数和列数,然后实现输出对应行列数的矩形的功
能,然后在 Main 方法中调用它,运行看效果。
2.3、方法的返回值
最复杂的方法是又有参数又有返回值的方法,在方法中添加返回值的目的就是当方法执行完之后
可以将一个结果返回给调用这个方法的人。就好比榨汁机完成榨汁后会将果汁返回给使用榨汁机的人
一样。在我们的程序中,一个方法在执行完毕后也需要有一个反馈信息,以告诉用户执行的结果,这
个反馈我们可以用方法的返回值来实现。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication2 { class Program { public static void M1() { Console.WriteLine("无参数也无返回值的方法"); } public static void M2(int a) { a++; Console.WriteLine(a); } public static int M3(int a) { a++; return a; } static void Main(string[] args) { M1(); M1(); M2(100); M2(200); int r1 = M3(500); Console.WriteLine(r1); r1 = M3(600); Console.WriteLine(r1); } } }
在 C#程序中,方法如果有返回值,那么方法的类型就要由 void 空类型改为对应要返回的值的类
型,比如要返回一个整数,那么方法的类型就要改成 int 类型,要返回一个字符串的话,方法的类型
要改成 string 类型,以及方法如果有返回值的话,在方法体中就必须要有 return 语句,我们通过
return 语句将值返回,return 语句的基本语法如下:
return 表达式; ;
下面我们定义一个简单的求次方的方法,能接收两个整型的数,然后计算次方并将结果作为返回
值返回给调用者,比如接收的整数是 2 和 3,那么就要运算 2 的 3 次方,结果为 8。代码如下:
class Program { //定义一个求次方的方法 static int Power(int num1, int num2) { int result = 1; for(int i=0;i<num2;i++) { result *= num1; } return result; } //定义一个Main方法(主方法,程序的入口) static void Main() { //调用Power方法并将返回的结果输出 Console.WriteLine(Power(2,3)); } }
课堂作业:
1、定义一个 Max 方法,接收用户输入两个数,然后判断并返回较大的数,并在 Main 方法中调用
它,以及将得到的较大的数输出到控制台,最后运行看效果。
2、定义一个 Average 方法,接收一个整型数组,然后计算出平均值并返回结果,然后在 Main 方
法中定义一个整型数组并初始化,接着调用这个方法并传入数组,最后将得到的结果找个变量保存再
输出到控制台。
String ip = "192.168.0.256"; String[] ips = ip.Split('.'); for (int i = 0; i < ips.Length; i++) { int temp = Convert.ToInt32(ips[i]); Console.WriteLine(ips[i]); if (temp > 255) { Console.WriteLine("错误"); } else { Console.WriteLine("正确"); } }View Code 三、方法重载
在 C#中,允许同一个类的 2 个或 2 个以上的方法有同一个名字,只要它们的参数声明不同即
可,这种情况被称为 方法重载。
当一个重载方法被调用时,C#用参数的类型或参数的数量来表明实际调用的是哪个重载方法。因
此,每个重载方法的参数类型或参数数量必须是不同的。这里面,跟方法的返回值是否相同没有关
系。
其实,我们非常熟悉的 Console 类的 WriteLine()方法有多达 19 种重载方式,它可以输出各种形
式的数据,如下所示(部分):
public static void WriteLine(); public static void WriteLine(int); public static void WriteLine(float); public static void WriteLine(char); public static void WriteLine(bool); public static void WriteLine(double); public static void WriteLine(string);
接下来我们尝试定义多个实现数据相加的方法,代码如下:
class Program { //方法重载:方法名相同,参数类型或个数不同 static int Add(int x,int y) { return x+y; } static int Add(int x,int y,int z) { return x+y+z; } static double Add(double x,double y) { return x+y; } static void Main() { //调用方法并输出结果 Console.WriteLine(Add(10,20)); Console.WriteLine(Add(10,20,30)); Console.WriteLine(Add(5.3,6.6)); } }
注意 :当调用重载的方法时,编译器会根据传入的参数自动进行判断,决定调用哪个方法。
课堂作业: 定义两个 Show 方法,第一个 Show 方法接收整数、第二个 Show 方法接收整型数组,如果接收的是整数则输出该整数,如果接收的是数组则将数组内所有元素取出并输出。
求最大数
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication10 { class Program { public static int Max(int a, int b, int c) { if (a > b && a > c) { return a; } else if (b > a && b > c) { return b; } else { return c; } } public static int Max(int a, int b) { return a > b ? a : b; } public static int Max(params int[] a) { Array.Sort(a); return a[a.Length-1]; } static void Main(string[] args) { Console.WriteLine(Max(5,3,9)); Console.WriteLine(Max(5, 3)); int[] a = {1,4,5,6,0,9,88,98,78,985,-99}; Console.WriteLine(Max(a)); Console.WriteLine(Max(1,4,5,9,6,3,1,2)); Console.WriteLine(Max(1)); Console.WriteLine(Max(200,300,500,100,700,50)); } } }
ASCII编码与转换
//把字符转换成数字 Console.WriteLine(Convert.ToInt32('A')); for (int i = 0; i < 128; i++) { //把数字转换成字符 Console.WriteLine(i+"->"+Convert.ToChar(i)); }
四、字符串类的常用方法
字符串类指的是 System 命名空间的 String 类,但我们平常定义字符串变量时使用的是首字母小
写的 string 类型,这是为什么呢?其实 string 是 c#中的类,String 是 Fra mework 的类,C#的
string 映射为 Fra mework 的 String,也就是说 string 是 String 的别名而已。string 是关键字,
String 不是,也就是说 string 不能作为类、变量、方法的名称,而 String 可以。如果使用 C#,建议
使用 string,比较符合规范 。
这一节中我们主要掌握字符串类的常见属性和方法,详细见下表所示:
Length 获取字符串的字符数即长度
Contains 判断指定字符串是否存在于此字符串中
StartsWith 判断此字符串的开头是否与指定的字符串相同
EndsWith 判断此字符串的末尾是否与指定的字符串相同
Format 将字符串数据格式化成指定的格式
IndexOf 返回字符串中第一次出现某个给定字符串的位置
LastIndexOf 返回字符串中最后一次出现某个给定字符串的位置
Insert 在指定的位置插入指定的字符串
Remove 删除字符串种指定位置、指定数目的字符
Replace 用另一个字符或字符串替换字符串中给定的字符或字符串
Split 在出现指定字符的地方,将字符串拆分为一个子字符串数组
Substring 在字符串中获取给定位置的子字符串
ToCharArray 将字符串转换为字符数组
ToUpper 将字符串转换为大写形式
ToLower 将字符串转换为小写形式
Trim 删除字符串首尾的空白
在列出的这些方法中,除了 Format()方法是静态方法,其它都是实例方法。下面就对这些方法进
行一一介绍,代码如下:
static void Main() { string str = "how are you?"; //获取字符串长度 Console.WriteLine("\"" + str + "\"字符串的长度:" + str.Length); //判断字符串中是否包含子字符串 if (str.Contains("are")) { Console.WriteLine("字符串中包含了are"); } //判断是否以某字符串开头 if (str.StartsWith("how")) { Console.WriteLine("字符串以how开头"); } //判断是否以某字符串结尾 if (str.EndsWith("?")) { Console.WriteLine("字符串以?结尾"); } //查找某字符或子字符串出现的位置,若出现返回下标;若没有出现返回-1; int first_Index = str.IndexOf("o"); int last_Index = str.LastIndexOf("o"); Console.WriteLine("字符o在字符串中第一次出现的下标是{0}", first_Index); Console.WriteLine("字符o在字符串中最后一次出现的下标是{0}", last_Index); //指定位置插入子字符串 string newStr = str.Insert(3, " old"); Console.WriteLine("原字符串:" + str); Console.WriteLine("插入后为:" + newStr); //字符串替换 str = newStr.Replace("old", "tall"); Console.WriteLine("原字符串:" + newStr); Console.WriteLine("替换后为:" + str); //字符串拆分 string[] strs = str.Split(' '); //以空格拆分 Console.WriteLine("第二个子字符串:" + strs[1]); //字符串删除 Console.WriteLine("原字符串:" + str); str = str.Remove(3,5); Console.WriteLine("删除后为:" + str); //字符串截取 string str1 = str.Substring(8); //从指定下标处开始截取到最后 string str2 = str.Substring(0, 3); //从指定下标处开始截取指定长度 Console.WriteLine("str1={0}\nstr2={1}", str1, str2); //转换大小写 string str3 = str.ToUpper(); string str4 = str3.ToLower(); Console.WriteLine("str3={0}\nstr4={1}", str3, str4); //去除前后的空格 string userName = " Tom "; newStr = userName.Trim(); Console.WriteLine("\"{0}\"字符串长度是:{1}",userName,userName.Length); Console.WriteLine("去除收尾空格后字符串的长度是:{0}", newStr.Length); Console.WriteLine(); }
通过上面例子我们发现,字符串类的所有方法都不会改变原来字符串的值,而是会返回一个新的
字符串,所以使用的时候需要注意。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication14 { class Program { static void Main(string[] args) { String str = "hello big world!"; //1求字符串长度 Console.WriteLine(str.Length); //2用于判断字符中是否包含子字符串 if (str.Contains("hello")) { Console.WriteLine("含有hello"); } else { Console.WriteLine("没有hello"); } //3是否以特定字符开头 if (str.StartsWith("ok")) { Console.WriteLine("以ok开头"); } //是否以特定字符结尾 if (str.EndsWith("world!")) { Console.WriteLine("以world!结束"); } //4 子字符串开始位置 Console.WriteLine(str.IndexOf("o")); //5 子字符串结束位置 Console.WriteLine(str.LastIndexOf("o")); //6 插入字符串 "hello good world!" Console.WriteLine(str.Insert(5, " good")); //7替换字符串 Console.WriteLine(str.Replace("o","**")); //8删除从指定位置开始长度的字符 Console.WriteLine(str.Remove(5,4)); //9拆分字符串为数组 hello big world! String[] a=str.Split(' '); foreach (var item in a) { Console.WriteLine(item); } //10截取子字符串 Console.WriteLine(str.Substring(6,3)); //11转大写 Console.WriteLine(str.ToUpper()); //12转小写 Console.WriteLine(str.ToLower()); //13去除字符串首尾空格,注意中间的空格不会去掉 str = " Hello Trim "; Console.WriteLine(str+"!"); Console.WriteLine(str.Trim()+"!"); } } }
课堂作业: 现有一包含了文件路径及名称的字符串"E:\C#编程基础\test.txt",请编写程序只把
文件名取出。
邮箱验证:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication15 { class Program { static void Main(string[] args) { Console.Write("请输入邮箱:"); String mail = Console.ReadLine(); Console.WriteLine(Verify(mail)); } //邮箱是否正确 public static string Verify(String mail) { //1、邮箱必须包含@与. if (!mail.Contains("@") || !mail.Contains(".")) { return "邮箱必须包含@与."; } //2、@与.不能开始与结束 if (mail.StartsWith("@") || mail.StartsWith(".")) { return "邮箱不能以@与.开始"; } if (mail.EndsWith("@") || mail.EndsWith(".")) { return "邮箱不能以@与.结束"; } //3、@必须在.的前面出现 if (mail.IndexOf("@") > mail.IndexOf(".")) { return "@必须在.的前面出现"; } //4、@只能有一个 int at = 0, dot = 0; //88@qq.com foreach (char item in mail.ToCharArray()) { if (item == '@') { at++; } if (item == '.') { dot++; } } if (at != 1) { return "@只能有一个"; } //5、.可以有多个 if (dot < 1) { return ".必须有1个或以上"; } //6、用户名的长度要大于等于3 String name = mail.Substring(0, mail.IndexOf("@")); //取出名字 if (name.Length < 3) { return "用户名的长度要大于等于3"; } return "正确"; } } }五、内部测试
5.1、定义一个方法Add,接收1个整型参数n,方法中将n增大1并返回;在Main方法中调用该方法,输出结果。
5.2、再定义一个Add方法实现重载功能,接收2个整型参数m与n,方法中实现m与n的和并返回;在Main方法中调用该方法,输出结果。
5.3、斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……
定义一个方法Fibonacci,接收整型参数n,方法实现计算出第1-n位的斐波那契数列,如Fibonacci(6),则输出0 1 1 2 3 5;在Main中调用,提示用户输入n