首页 > 编程知识 正文

c语言网,c语言怎么学才能学好

时间:2023-05-04 10:08:48 阅读:117086 作者:4563

最近一直遇到c#的请求,在刚开始看到的云层上,最后用c的函数指针进行类比是醍醐灌顶的。 所以先记载下来。

因为首先接触了c,所以先看c的函数指针,再谈c#的请求。

参见33558www.Sina.com/cprimerplus版本6

函数有地址,函数的地址是存储该机器语言代码的存储器的开始地址。

函数地址:函数名称。 例如,假设Test ()是一个函数,则Test是该函数的地址。 要将函数作为参数传递,必须传递函数名称。

声明函数指针:声明指向某个数据类型的指针时,必须指定指针指向的类型。 同样,声明指向函数的指针时,也必须指定指针指向的函数类型。 例如,函数的原型可能如下:

双钥匙(int; 那么,正确的函数指针声明:

双精度(KL ) ) int; 你看,这两个宣言相似吗? 第一个是函数宣言,第二个其实也相当于函数宣言。 但是,Killer不是函数,(*kl )也是函数,kl是函数指针。 所以,在正确声明kl后,可以将函数地址分配给它:

kl=Killer注意:符号的优先顺序在这里特别重要。 例如:

*kl(int ) /表示kl ) )是返回指针的函数。 ) kl ) ) int ) /表示kl是指向函数的指针。 将函数地址分配给函数指针后,可以使用函数指针调用该函数。

电音。

# includeiostreamusingnamespacestd; 双精度测试(int; 双PAM (int ); voidestimate(intlines,double ) pf (int ); int main () { int代码; cout ' howmanylinesofcodedoyouneed?' ; cincode; cout ' here ' s Betsy ' s estimate :n '; estimate (代码,betsy ); cout ' here ' spam ' s estimate :n '; estimate (代码、pam ); 返回0; }双电池(intl ns ) { return 0.05*lns; }双PAM (intl ns ) { return 0.03*lns 0.004*lns*lns; }voidestimate(intlines,double ) pf (int ) ) { coutlines' lines will take '; cout(pf ) lines ) ) hours ) endl; }

一、c++的函数指针参考博客如下:

3359 docs.Microsoft.com/zh-cn/dot net/cs harp/tour-of-cs harp/delegates

3359 blog.csdn.net/ding Xiaowei 2013/article/details/18428727

3359 blog.csdn.net/Serena haven/article/details/80047622

见c#高级编程第8版

委托概念:在c编程中,只能提取函数地址,并作为一个参数传递。 然而,该方法的缺点在于,在面向对象编程的情况下,很少存在孤立的方法,需要在调用方法之前关联类实例。 因此, NET Framework在语法上不允许使用此直接方法,并且要传递方法,必须将方法详细信息封装为新类型的对象:二、c#的委托。 委托是一种特殊类型的对象,其特殊之处在于,以前定义的所有对象都包含数据,而委托包含一个或多个方法的地址。

emmm,你觉得看不见吗? 没关系。 慢慢继续看,然后再回来读好几遍。

怎么使用委托? 和班级的使用过程一样。 1 .定义请求2 .事例请求

委托的语法如下:

delegatevoidintmethodinvoker (intx; //委托定义IntMethodInvoker,指定该委托的每个实例都包含对具有int参数的方法的引用,然后单击voiddelegatedoubletwolongsop (long first,long second ); //委托定义TwoLongsOp,指定该委托的每个实例可以包含对具有两个long参数的方法的引用(双删除字符串geta string ); 为//委托定义GetAString,并指定该委托的每个实例都可以包含对方法的引用,而无需参数。 请注意,此方法是string类型。 类有两个不同的术语,“类”表示更广义的定义,“对象”表示类的实例。 但是,委托只有一个术语。 创建委托实例时,

所创建的委托的实例仍然成为委托。

e.g.   

using System;class MathOperations{public static double MultiplyByTwo(double value){return value * 2;}public static double Square(double value){return value * value;}}namespace Demo{ //定义委托delegate double DoubleOp(double x);class Program{static void Main(){ //实例化一个委托数组,该数组的每个元素都初始化为由MathOperations类实现的不同操作DoubleOp[] operations ={MathOperations.MultiplyByTwo,MathOperations.Square}; //遍历委托数组,调用不同的方法for(int i = 0; i<operations.Length; i++){Console.WriteLine("Using operations[{0}]:",i);ProcessAndDisplayNumber(operations[i],2.0);ProcessAndDisplayNumber(operations[i],7.94);ProcessAndDisplayNumber(operations[i],1.414);Console.WriteLine();}}static void ProcessAndDisplayNumber(DoubleOp action,double value){// 实际上是调用action委托实例  封装的方法,其返回结果存储在result中。 double result = action(value);Console.WriteLine("Value is {0},result of operation is {1}",value,result);}}}

 

在上面的那个程序中:

operations[i]表示“这个委托”。换言之,就是委托表示的方法operations[i](2.0)表示“实际上调用这个方法,参数放在圆括号中”

所以委托、类、方法之间的情况,一定要理解清楚咯。我的理解就是委托其实和类的使用是差不多的,都需要定义和实例化,但是委托和方法又离的很近很近,它可以直接代表方法,并且作为参数使用(这点又和函数指针很像)。

注意:在这里只是申请了委托数组,并不是多播委托。多播委托将在后面讲述。

三、深入c#委托

随着c#的版本更新,出现了更加实用的委托方式。就是Action<T>和Func<T>委托。

Action<T>委托表示引用一个void返回类型的方法,Function<T>委托允许调用带返回类型的方法。

下面以BubbleSorter(冒泡排序)为例,讲解一下委托的优势。

在学习到委托之前,一说到冒泡排序,大脑还没思考,手就开始机械化撸代码了。一般都是这么写的:

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

对吧,这是程序员必修课了基本上,闭着眼也能撸出来。但是有没有想过一个问题,如果要排序的对象不是int呢,是其他类型呢。如果是没有办法直接进行大小比较的类型呢?(其实函数重载也是可以撸出来的哈,但是今天不说这个,其实函数重载也挺麻烦的)

答案就是:能识别该类型的代码必须在委托中传递一个封装的方法,这个方法可以比较。e.g.

class BubbleSorter{static public void Sort<T>(IList<T> sortArray,Func<T,T,bool> comparison){bool swapped = true;do{swapped = false;for(int i=0;i<sortArray.Count-1;i++){if(comparison(sortArray[i+1],sortArray[i])){T temp = sortArray[i];sortArray[i] = sortArray[i+1];sortArray[i+1] = temp;swapped = true;}}}while (swapped);}}

下面就来一个完整的可以运行的代码进行冒泡排序,假设要对员工按照薪水进行排序。e.g.

using System;using System.Collections;using System.Collections.Generic;namespace Demo{class Program{static void Main(){//类实例数组Employee[] employees = {new Employee("Bugs Bunny",2000),new Employee("Elmer Fudd",1000),new Employee("Daffy Duck",2500),new Employee("Wile Coyote",4000),};BubbleSorter.Sort(employees,Employee.CompareSalary);//对排序好的类数组进行遍历foreach(var employee in employees){Console.WriteLine(employee);}}}}class BubbleSorter{static public void Sort<T>(IList<T> sortArray,Func<T,T,bool> comparison){bool swapped = true;do{swapped = false;for(int i=0;i<sortArray.Count-1;i++){if(comparison(sortArray[i+1],sortArray[i])){T temp = sortArray[i];sortArray[i] = sortArray[i+1];sortArray[i+1] = temp;swapped = true;}}}while (swapped);}}class Employee{public Employee(string name,decimal salary){this.Name = name;this.Salary = salary;}public string Name {get;private set;}public decimal Salary {get;private set;}public override string ToString(){return string.Format("{0},{1:C}",Name,Salary);}public static bool CompareSalary(Employee e1,Employee e2){return e1.Salary<e2.Salary;}}

 

委托可以包含多个方法吗?当然可以,这样的委托叫做多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void,否则,就只能得到委托调用的最后一个方法的结果。

在前面的实例中,因为要存储对两个方法对引用,所以实例化了一个委托数组。而用到多播委托,可以直接在同一个多播委托中添加两个操作,e.g.:

Action<double> operations = MathOperations.MultiplyByTwo;operations += MathOperations.Square;

所以刚才讲的例子的程序随时应变,应该变成这样:

using System;class MathOperations{public static void MultiplyByTwo(double value){double result = value * 2;Console.WriteLine("MultiplyByTwo:{0} gives {1}",value,result);}public static void Square(double value){double result = value * value;Console.WriteLine("Square:{0} gives {1}",value,result);}}namespace Demo{class Program{static void Main(){Action<double> operations = MathOperations.MultiplyByTwo;operations += MathOperations.Square;ProcessAndDisplayNumber(operations,2.0);ProcessAndDisplayNumber(operations,7.94);ProcessAndDisplayNumber(operations,1.414);Console.WriteLine();}static void ProcessAndDisplayNumber(Action<double> action,double value){ Console.WriteLine();Console.WriteLine("processAndDisplayNumber called with values = {0}",value);action(value);}}}

四、匿名委托

其实匿名委托是一种更实用的委托方式,按理说应该在三中放的,但是我觉得比较重要,就另起一个部分放在这里了。

先不多说,直接代码:

using System;namespace Demo{class Program{static void Main(){string mid = ", middle part, ";Func<string,string> anonDel = delegate(string param){param += mid;param += " and this was added to the string.";return param;};Console.WriteLine(anonDel("Start of string"));}}}

解释:Func<string,string>委托接受一个字符串参数,返回一个字符串。anonDel是这种委托类型的变量。不是把方法名赋予这个变量,而是使用一段简单的代码:它的前面是关键字delegate,后面是一个字符串参数。

其实匿名就是把方法名给省去了。而在C#3.0以后,开始用Lambda表达式替代匿名方法。

所以以上代码可以改为:

using System;namespace Demo{class Program{static void Main(){string mid = ", middle part, ";Func<string,string> lambda = param =>{param += mid;param += " and this was added to the string.";return param;};Console.WriteLine(lambda("Start of string"));}}}

Lambda云算符号“=>”的左边列出了需要的参数,右边赋予了Lambda变量的方法的实现代码。

暂时就先说到这里。恩。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。