[藏]图文并茂详解Eclipse断点

本文转自:http://my.oschina.net/colorleaf/blog/176569 这个算说的比较清楚的了,虽然简单但是很有用。收藏一下。 详解Eclipse断点 大家肯定都用过Eclipse的调试的功能,在调试的过程中自然也无法避免要使用断点(breakpoint),但不知是否对Eclipse中各类断点都有所了解。本篇图文并茂地介绍了Eclipse中全部类型的断点,及其设置,希望对大家有所帮助。(2011.11.20) 1. 示例程序 BreakpointDemo是一个臆造的应用程序,只是为了便于讲解Eclipse中各类断点的使用罢了。其代码如下图所示, BreakpointDemo主要包含两个方法: [1]setValue,该方法根据指定的次数(count),对成员变量value进行赋值,值的范围为0-9的随机整数。 [2]printValue,该方法会调用setValue()对value进行赋值,并打印出value的值;但,如果value能被3整除,那么就会抛出IllegalArgumentException异常。 2. Line Breakpoint Line Breakpoin是最简单的Eclipse断点,只要双击某行代码对应的左侧栏,就对该行设置上断点。此处,对第20行代码设置上Line Breakpoint,如下图所示, 可以为Line Breakpoint设置一个条件,那么当程序运行到该断点时,只有满足设定的条件,才会被中断。右键点击第20行的断点,选择"Breakpoint Properties…" 在弹出的属性对话框中,勾选上"Conditional",然后在文本框中输入"count % 2 == 0"。 该条件表示,当程序运行到第20行时,只有当count为偶数时,程序才会被中断。细心地话,你会发现该断点的图标发生了改变,多了一个问号。 3. Watchpoint Line Breakpoint关注于程序运行的"过程",大家也常把使用这种断点的调试称为单步调试。但有时候,我们对程序的运行过程不太了解,可能也不太关心,不能确定在什么地方设置断点比较合适,而可能比较关注某个关键变量的变化或使用。此时,就可以为该变量设置一种特殊的断点–Watchpoint。在此示例,我们最关心的就是成员变量value的值,那么就可以为它设置一个Watchpoint,双击第9行代码对应的左侧栏就可以了。 使用在2中所提及的方法,查看该断点的属性, 默认地,当该变量被访问或它的值被修改时,程序都会被中断。但在本示例中,只希望当对value的值进行修改时程序才需要被中断,所以取消对"Access"的勾选。 这时,我们会发现原来的Watchpoin图标也有变化了。 4. Method Breakpoint 与关注对某个变量的访问与修改一样,我们也可以关注程序对某个方法的调用情况,即,可以设置Method Breakpoint。在此处,设置针对方法setValue的Method Breakpoint。同理,双击第11行代码对应的左侧栏即可。 仍然要查看该断点的属性。默认地,只勾选了"Entry",而没有勾选"Exit"。 这表示,当刚进入该方法(调用开始)时,程序会被中断;而,离开该方法(调用结束)时,程序并不会被中断。在本示例中,需要同时勾选上"Exit"。 点击OK之后,可以看到该断点的图标也有所改变。 根据这里的设置,当程序运行到第20行后会在第12行被中断,尽管这里没有显式的断点,但这就是setValue()方法的入口(Entry)。必须注意地是,程序在运行到第16行时不会被中断,尽管它看起来像是setValue()方法的出口(Exit)。实际上,程序会在第17行被中断,这里才是setValue()调用结束的地方。 5. Exception Breakpoint 如果,我们期望某个特定异常发生时程序能够被中断,以方便查看当时程序所处的状态。通过设置Exception Breakpoint就能达到这一目标。本示例故意在第23行抛出了IllegalArgumentException异常,我们期望程序运行到此处时会被中断。但我们不直接为此行代码设置Line Breakpoint,而是为IllegalArgumentException设置Exception Breakpoint。设置Exception Breakpoint的方法与其它类型断点都不同,它不能通过双击左侧栏的方式在代码编辑器上直接进行设置。点击Breakpoints视图右上角形如Ji的图标, 会弹出如下所示的对话框, 在其中选中IllegalArgumentException,并点击OK,这时一个Exception Breakpoint就设置好了。 当value为3的倍数时,程序会在第23行被中断,这时我们就能使用调试器来看看value具体是等于0,3或6。 **6\. Class Load Breakpoint** 还有一种大家平时可能不太用的断点--Class Load Breakpoint,即当某个类被加载时,通过该断点可以中断程序。 [![15153248_2UA6](/images/8158c897f4e784042063a484c7256901902b6c20.png)](http://leaverimage.b0.upaiyun.com/2013/11/15153248_2UA6.png) 小结 上述的Eclipse断点,我们在现实工作中肯定都有意或无意地使用过其中的几种,只是不一定十分了解内情罢了。使用好Eclipse的各种断点,可以把很好地帮助我们分析程序,定位问题。

2013-11-16 · 1 min · bystander

Spring3实例入门-Hello World

每次看到hello world,都有一种说不出的赶脚,想起了一个程序员,退休后写毛笔字,取笔研磨铺纸,大笔一挥,写下了“hello world”。 1.使用Maven生成项目结构 mvn archetype:generate -DgroupId=com.mkyong.core -DartifactId=Spring3Example -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false 2.转换成Eclipse项目 mvn eclipse:eclipse 3.添加Spring3.0 依赖 在pom.xml文件里添加Spring 3.0 依赖,然后依赖会从Maven中央仓库自动下载 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mkyong.core</groupId> <artifactId>Spring3Example</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>Spring3Example</name> <url>http://maven.apache.org</url> <properties> <spring.version>3.0.5.RELEASE</spring.version> </properties> <dependencies> <!-- Spring 3 dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies> </project> 4.Spring bean 写个简单的bean package com.mkyong.core; /** * Spring bean * */ public class HelloWorld { private String name; public void setName(String name) { this.name = name; } public void printHello() { System.out.println("Spring 3 : Hello ! " + name); } } 5.Spring bean配置文件 创建一个配置文件,在里面声明所有可用的Spring beans <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="helloBean" class="com.mkyong.core.HelloWorld"> <property name="name" value="Mkyong" /> </bean> </beans> 6.最终的目录结构 7.运行 package com.mkyong.core; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "SpringBeans.xml"); HelloWorld obj = (HelloWorld) context.getBean("helloBean"); obj.printHello(); } } 8.输出 Spring 3 : Hello ! Mkyong 9.Demo下载 Spring3-hello-world-example.zip 

2013-09-20 · 1 min · bystander

委托和事件示例

C#中委托和事件的例子比较多,讲得好的非常好,就不瞎凑热闹了,推荐博客园大牛的一篇: C# 中的委托和事件 ,如果你已经有了相应的基础,但没写过相关的例子,那我这里提供一个,首先看一下规范 .Net Framework的编码规范: 委托类型的名称都应该以EventHandler结束。 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。 事件的命名为 委托去掉 EventHandler之后剩余的部分。 继承自EventArgs的类型应该以EventArgs结尾。 然后描述一下流程: 老板监视时间变动(ComputerOffWorkTime方法),当工作时间满50后,通知员工时间到(OnNotifyOffWork方法,并传递OffWorkEventArgs参数),可以下班了,(OnNotifyOffWork方法内部调用事件NotifyOffWork),正式员工收到通知后,则下班,其他员工则清扫一下办公室 然后给出例子: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; namespace DelegateAndEvent { public class Boss { //表示工作时间 private int virTime; //下班时老板说的话 public String SaidWords { get { return "Boss:时间到,下班了"; } } //委托定义 public delegate void NotifyOffWorkEventHandler(Object sender, OffWorkEventArgs e); //事件 public event NotifyOffWorkEventHandler NotifyOffWork; //事件参数 public class OffWorkEventArgs:EventArgs { public readonly int virTime; public OffWorkEventArgs(int virTime) { this.virTime = virTime; } } //触发事件 protected void OnNotifyOffWork(OffWorkEventArgs e) { if (NotifyOffWork!=null) { NotifyOffWork(this, e); } } //执行操作 public void ComputerOffWorkTime() { for (int i = 1; i <= 50; i++) { virTime = i; if (i>=50) { OffWorkEventArgs e = new OffWorkEventArgs(i); OnNotifyOffWork(e); } } } } //正式员工 public class FormalEmployee { public static void GoHome(Object sender, Boss.OffWorkEventArgs e) { Boss boss = (Boss) sender; Console.WriteLine(boss.SaidWords); Console.WriteLine(e.virTime); Console.WriteLine("FormalEmployee:准备回家"); } } //其他员工 public class OtherEmployee { public static void CleanOffice(Object sender, Boss.OffWorkEventArgs e) { Boss boss = (Boss)sender; Console.WriteLine(boss.SaidWords); Console.WriteLine(e.virTime); Console.WriteLine("OtherEmployee:准备清扫办公室"); } } public class Program { static void Main(string[] args) { Boss boss=new Boss(); //注册事件 boss.NotifyOffWork += FormalEmployee.GoHome; boss.NotifyOffWork += OtherEmployee.CleanOffice; //老板开始计时 boss.ComputerOffWorkTime(); } } }

2013-06-25 · 1 min · bystander

DMP版本修改工具(C#)

最近在使用oracle导入一个dmp文件的时候,由于不知道dmp文件是如何导出的,是使用exp还是expdp导出的,所以纠结了比较长的时间,最后想到是否可以查看dmp文件的一些辅助信息呢,于是有了这个工具。 在使用dmp导入的时候报如下错误 IMP-00010: 不是有效的导出文件,标题验证失败 IMP-00000: 未成功终止导入 据说有两个可能,1个是文件本身损坏,另一个是版本问题,多出现在高版本导出的数据向低版本导入。解决方法就是修改一下dmp文件就行了。dmp文件头部大概9个字节处标识了版本号用来头部验证。对于非常大的dmp我们不能直接用文本编辑器打开,因此找找资料,写个工具。本机一个12GB的文件已测试。 工具使用很简单,选择文件,识别出来版本,按格式改成导入端oracle的版本值,然后即可正常导入11G-10G测试成功。 下载地址:DMP版本修改工具

2013-06-11 · 1 min · bystander

阿里巴巴5月5日综合算法题详解

之前参加了阿里的笔试和电面,让后天那个敏感的日子去参加现场面,就去看了一下那天笔试的最后一道综合题,看着网上清一色最后一道题不知道从哪转的答案,不忍直视,一看代码就是错的,最直接的就是求中位数连奇偶性都不判断,直接处以2..这,另外当在无法整除的情况下,数据结果错误。 这道题的大意是:有一个淘宝商户,在某城市有n个仓库,每个仓库的储货量不同,现在要通过货物运输,将每次仓库的储货量变成一致的,n个仓库之间的运输线路围城一个圈,即1->2->3->4->…->n->1->…,货物只能通过连接的仓库运输,设计最小的运送成本(运货量*路程)达到淘宝商户的要求,并写出代码。 解题思路: 假设n个仓库的初始储货量分别为warehouse[1],warehouse[2],…,warehouse[n] 计算平均储货量 average = (warehouse[1]+warehouse[2]+...+warehouse[n])/n 就算出来了最终的结果中,每个仓库应该有的存量 首先,从仓库1向仓库n运送k; 然后,从1到n-1,依次向下运送某一特定值,使得每一个仓库的余量都为average,剩下的问题就是求总代价的最小值了。 设第0步从1仓库向n仓库(注意因为是圆圈,所以路径长度是1)运出k存量,k可以为负,如果为负数,意味着从n向1运输|k|存量,然后从循环,从(1到n-1),从i仓库向i+1仓库运输,运输的量需要保证i仓库在运输完毕后等于average 第0步(从仓库1向仓库n运送k):花费代价为 |k|, 第1步(确保仓库1的余量为average):需要花费代价为 |warehouse[1]-average-k| 也就是从1向2伙从2向1运输 3. 第2步(确保仓库2的余量为average):代价为 |warehouse[2]+warehouse[1]-average-k-average|=|warehouse[1]+warehouse[2]-2*average-k| … n-1.第n-1步:代价为 |warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k| 此时,仓库n剩下的货物量: (warehouse[n]+k)+warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k=(warehouse[1]+warehouse[2]+...+warehouse[n])-(n-1)*average=average 刚好也满足,其实这里不用推导,因为平均值是算好的,所以最胡一定是刚好完成的。 总的代价为: |k|+|warehouse[1]-average-k|+|warehouse[1]+a[2]-2*average-k|+...+|warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k| 不妨令sum[i] = warehouse[1]+warehouse[2]+…+warehouse[i]-i*average 则,总代价可表示为:|k|+|sum[1]-k|+|sum[2]-k|+…+|sum[n-1]-k| 这个式子可以看成在水平数轴上寻找一个点k,使得点k到点0,sum[1],sum[2],sum[3],…,sum[n-1]的距离之和最小,显然k应该取这n个数的中位数。至此问题解决。 给出详细注释代码: #include "stdafx.h" #include <iostream> #include <algorithm> #include<string> using namespace std; const int X = 100000; double sum[X],warehouse[X]; int n; double Abs(double x) { return max(x,-x); } int _tmain(int argc, _TCHAR* argv[]) { while(true) { double total = 0; double mid=0; cout<<"请输入仓库数目:"; cin>>n; //读入n个仓库的值,并计算总数 for(int i=1;i<=n;i++) { cout<<"请输入第"<<i<<"个仓库的存量:"; cin>>warehouse[i]; total += warehouse[i]; } //计算每个仓库应该最终存储的值 double average = total/n; //计算sum数组 for(int i=1;i<n;i++) sum[i] = warehouse[i]+sum[i-1]-average; //排序后打算去中位数 //sort采用半开半闭区间,所以排序为0~n-1 sort(sum,sum+n); //这个可以自己举个数字就知道了 if(n%2!=0) { mid = sum[n/2]; } else { mid=(sum[n/2]+sum[n/2-1])/2; } cout<<"应该从1开始,运输"<<mid<<"货物,然后依次保证符合条件即可"<<endl; double ans = Abs(mid); for(int i=1;i<n;i++) ans += Abs(sum[i]-mid); cout<<"总成本花费是:"<<ans<<endl; cout<<"----------------------------------------------------------------------"<<endl; } return 0; } 思路借鉴了:http://hi.baidu.com/hujunjiehit/item/54204f01931ee6c49157184c 错误之处欢迎留言指出..

2013-06-02 · 1 min · bystander

[译]反射(Reflection)和动态(dynamic)

反射 当我们需要检查,调用一个程序集的内容的时候,用反射,比如,当VS给智能提示的时候,就应用了反射。 简单用法实例: var myAssembly = Assembly.LoadFile(@"C:\ClassLibrary1.dll"); var myType = myAssembly.GetType("ClassLibrary1.Class1"); dynamic objMyClass = Activator.CreateInstance(myType); // 获取类的类型信息 Type parameterType = objMyClass.GetType(); // 浏览方法 foreach (MemberInfo objMemberInfo in parameterType.GetMembers()) {Console.WriteLine(objMemberInfo.Name);} // 浏览属性. foreach (PropertyInfo objPropertyInfo in parameterType.GetProperties()) {Console.WriteLine(objPropertyInfo.Name);} //开始调用 parameterType.InvokeMember(“Display”,BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Instance,null, objMyClass, null); 实际一点的用处呢: 1.当你也要开发一个类似VS的编辑器的时候,要提供智能提示就需要反射 2.当创建单元测试框架的时候,为了测试需要动态调用方法和属性的时候 3.有时候我们想把类型的属性,方法等全部导出的时候 动态dynamic 编程语言分为强/弱类型,dynamic是弱类型,此关键字会让编译器不做编译时的类型检查,只做运行时的检查。 简单用法示例: dynamic x = "c#"; x++; 所以上面这行代码可以编译通过,但会产生运行时一场。 实际用处: 最多的就是通过互操作来操作Office组件的时候了 没有dynamic的时候 / Before the introduction of dynamic. Application excelApplication = new Application(); ((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name"; Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1]; 有了dynamic之后世界就不一样了 dynamic excelApp = new Application(); excelApp.Cells[1, 1].Value = "Name"; Excel.Range range2010 = excelApp.Cells[1, 1]; 两者的区别和联系呢 1.当我们想要在运行时操作一个对象的时候,就会用到这两个 2.反射可以用来检测对象的元数据,也能在运行时调用对象的方法和属性 3.dynamic是.net 4.0新出的关键字,知道方法被调用的时候,编译器才会晓得这个方法到底有还是没有。 4.dynamic内部是使用反射来实现的,它缓存了方法调用来提高性能 5.反射可以调用公有和私有成员,而dynamic智能调用用公有成员 6.dynamic是实例相关的,无法访问静态成员,这种情况下使用反射吧。 **Reflection** **Dynamic** **Inspect (meta-data) ** Yes No **Invoke public members** Yes Yes **Invoke private members** Yes No **Caching** No Yes **Static class ** Yes No 再来一张图... [![](/images/d0e1ec824f1199a847d9a16237673a4a299e0dce.jpg)](http://leaverimage.b0.upaiyun.com/36512_o.jpg) 译自:[http://www.codeproject.com/Articles/593881/What-is-the-difference-between?utm_source=feedly](http://www.codeproject.com/Articles/593881/What-is-the-difference-between?utm_source=feedly)

2013-05-27 · 1 min · bystander

武汉大学论文参考文献格式生成工具(C#)

每次写论文报告什么的,最头疼的就是参考文献的,本来打算写一个论文格式生成工具的,不过,一想起代码量,就有点吓人,所以分而治之,先写参考文献生成工具. 本工具生成的文献格式符合武汉大学本科生论文的格式要求,因此,放心使用,填写内容都是必填,页码什么的要是不知道就随便填一个..你懂的..有问题请留言反馈。 程序提供8种参考文献类型,第9种电子文献,没有实现,因为感觉在论文中参考文献要是网址的话很难看.而且用的不多..其实主要还是懒..每种文献类型需要填写的信息都不一样,8种…8种… 使用方法: 1.在界面右侧选择参考文献类型,然后填写。添加,左侧将会出现 2.如果填写错误,双击左侧条目,即可删除 3.完成后导出,即可在本目录生成docx文档 下载地址:武汉大学论文参考文献格式生成工具

2013-05-24 · 1 min · bystander

引用和指针(C++)

今天在整理收藏夹的时候,又看到了这两篇非常不错的文章,关于指针和引用的,我就不翻译了,文章很简单,不过把其中我觉得很有意思的两部分结合我的理解希望说的更清楚,假定你读这篇文章之前已经知道指针,但是不是很清楚其中的部分。 首先是关于指针的一个直观的一个认识. #include <iostream> int main() { using namespace std; // 声明并初始化指针. unsigned short int * pPointer = 0; // 定义一个unsigned short int 变量 值为35698 unsigned short int twoInt = 35698; // 定义一个unsigned short int 变量 值为 77 unsigned short int oneInt = 77; // 使用&操作符将twoInt的地址赋给指针 pPointer = &twoInt; // pPointer 现在的值就是twoInt的地址了 // 打印 cout << "pPointer的内存地址:\t\t" << &pPointer << endl; cout << "oneInt的内存地址:\t" << &oneInt << "\t整数值:\t" << oneInt << endl; cout << "twoInt的内存地址:\t" << &twoInt << "\t整数值:\t" << twoInt << endl; cout << "pPointer所指向的地址(也就是pPoint的值):\t" << pPointer << "\t整数值:\t" << *pPointer << endl; return 0; } 上面这段代码,声明了一个指针,和两个整数,指针指向第一个整数,然后输出结果(每个人的输出结果不一样)是: pPointer的内存地址: 0xbff43314 oneInt的内存地址: 0xbff43318 整数值: 77 twoInt的内存地址: 0xbff4331a 整数值: 35698 pPointer所指向的地址(也就是pPoint的值): 0xbff4331a 整数值: 35698 这张图是这几个变量的内存分布图,上面一排是内存地址编号,正对我们的是该处的值 指针pPointer这个变量从最左边0xbff43314这个内存位置开始,占用了四个字节,这个一个指针占四个字节,大家都知道的,这个变量的值是一个地址,也就是他的指向地址。 pPointer 所指向的地址呢,是一个short int 类型的值所在的位置,在这里就是我们的twoint,twoint在内存中呢,是从0xbff4331a开始的,也就是说,我们的pPointer指向了twoint所在的地址, 注意,看一下左边四个方块前面的二进制数,转换成16进制就是0xbff4331a了 因此,取指针所指向的值就是35698了。指针本身的值则是0xbff4331a,指针所在的位置是0xbff43314。 参考文章:C++ : Understanding pointers 另一个呢是关于引用的实现原理 大家都知道,引用就是别名,比如下面这段代码 #include <iostream> using namespace std; int main() { int number = 88; // 定义一个int变量 int & refNumber = number; // 声明并初始化一个引用 // 现在他们都表示了同一个值 cout << number << endl; // 打印number的值 (88) cout << refNumber << endl; // 打印引用的值 (88) refNumber = 99; // 给refNumber重新赋一个值 cout << refNumber << endl; cout << number << endl; // number的值也就变成了 (99) number = 55; // 重新给number赋一个值 cout << number << endl; cout << refNumber << endl; // refNumber也就变成了(55) } 输出结果肯定一目了然,其中的原理想过没 ...

2013-05-22 · 1 min · bystander

一道笔试指针题目详解

看到本题是在搜狗某年的笔试题上,看也没人给出非常详细的讲解,直接给出了答案,我来尝试写一写, 貌似本题来源自<**The C Puzzle Book> ,**搜狗也只是换了一下字符串,直接看题吧 #include <stdio.h> char *c[]={"ENTNG", "NST","AMAZI","FIRBE"}; char** cp[]={c+3, c+2, c+1, c}; char ***cpp= cp; int main() { printf("%s",**++cpp); printf("%s ",*--*++cpp+3); printf("%s",*cpp[-2]+3); printf("%s",cpp[-1][-1]+1); } <span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">请写出程序的执行结果....</span> 首先从左到右看: char *c[]= { "ENTNG", "NST", "AMAZI", "FIRBE" }; *c[] 是一个字符,因此,c[]是指向该字符,c就是一个数组(数组的内容为指向字符的指针),c已经被初始化了. char** cp[]={c+3, c+2, c+1, c}; 再看第二行,**cp[]是一个字符,*cp[]就是一个指针,指向该字符,cp[]就是一个指针,指向该指针,而cp就成为了指针数组,内容是指向字符的指针的指针。并且通过c的元素进行了初始化 char ***cpp= cp; 第三行,***cpp是一个字符,**cpp指向该字符,*cpp指向该指针,cpp就指向该字符的指针的指针. 然后我画一张图表示初始的情况看看 然后对于下面的输出语句,通过操作符优先级使用括号来区分一下: *(*(++cpp)); 这个嘛,就是把cpp后移(注意cpp已经改变了)然后就指向了cp[1],然后两次取其值即可得到AMAZI 推导过程如下: ++cpp -> cp[1] // cp[1] -> c+2 ++cpp = &cp[1] // &(c+2) *++cpp = *(&c+2) // c[2] **++cpp = *&c[2] 然后看第二个 (*(--(*(++cpp))))+3; 加括号后如上,cpp再加一,就指向了cp[2],取一次值(也就是*号)就变成了c[1],然后--c[1]就指向了c[0],取值就成了c[0]的地址,然后地址+3,就是NG了 (*(cpp[-2]))+3; 上面,cpp指向cp[2]了,然后呢,cpp[-2] 相当于*(cpp-2),间接引用cp[2],这样cpp[-2]就指向了cp[0]了,然后,就是FIRBE了,加3就是BE了 最后 (cpp[-1][-1])+1; cpp还是之前的cp[2],cpp[-1][-1]相当于*(*(cpp-1)-1),先减1指向了cp[1],取一次值就是c[2]了,然后c[2]-1就成为c[1]了,然后+1之后就是ST了. 所以,最后输出就是 AMAZINGBEST 错误之处还望指正.

2013-04-17 · 1 min · bystander

模板栈以及中缀表达式求值(C++实现)

栈直接用链表实现,这个比较简单,不多说,不过C++写程序,IDE的错误检测不是很给力。 至于给定一个中缀表达式,如何不转换成后缀表达式,直接求值,方法就是使用两个栈,一个操作符栈,一个操作数栈,然后从左到右扫描表达式,我这里中缀表达式计算实现的很简单,不完整,大家可以扩展。栈的实现是我想写的,思路如下: 1.如何是操作数,压入操作数栈 2.如果是操作符,压入操作符栈 3.如果是左括号,直接忽略 4.如果是有括号,弹出操作符栈栈顶元素,然后弹出操作数栈两个元素,进行操作以后结果压入操作数栈 看个图就好了 最后给出栈顶实现代码 #include "stdafx.h" #pragma region Node定义 template <class T> class Node { template<class T> friend class Stack; private: T m_data; Node *pNextNode; public: Node(); Node(T d); }; template <class T> Node<T>::Node() { m_data=default(T); pNextNode=NULL; } template <class T> Node<T>::Node(T d) { m_data=d; pNextNode=NULL; } #pragma endregion #pragma region Stack定义 template <class T> class Stack { private: Node<T> *m_pTopNode; int m_nNodeCount; public: Stack(); ~Stack(); bool IsEmpty(); bool Push(T e); T Pop(); int Size(); }; template <class T> Stack<T>::Stack() : m_pTopNode(NULL),m_nNodeCount(0) { } template <class T> Stack<T>::~Stack() { while (!IsEmpty()) { Node<T> *pTempNode = m_pTopNode; m_pTopNode = m_pTopNode->pNextNode; delete (pTempNode); pTempNode = NULL; } m_nNodeCount = 0; m_pTopNode = NULL; } template <class T> bool Stack<T>::IsEmpty() { return (m_pTopNode == NULL); } template <class T> bool Stack<T>::Push(T e ) { Node<T> *pNewNode = new Node<T>(e); if (NULL == pNewNode) { return false; } if(! IsEmpty()) { pNewNode->pNextNode = m_pTopNode; } m_pTopNode = pNewNode; m_nNodeCount ++; return true; } template <class T> T Stack<T>::Pop() { if(IsEmpty()) { return T(-1); } T e; e = m_pTopNode->m_data; Node<T> *pNode = m_pTopNode; m_pTopNode = m_pTopNode->pNextNode; delete (pNode); m_nNodeCount--; return e; } template <class T> int Stack<T>::Size() { return m_nNodeCount; } #pragma endregion 然后是main函数代码 ...

2013-04-11 · 2 min · bystander