软考复习资料 134页

  • 465.50 KB
  • 2022-07-30 发布

软考复习资料

  • 134页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档由用户上传,淘文库整理发布,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,请立即联系网站客服。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细阅读内容确认后进行付费下载。
  4. 网站客服QQ:403074932
上学吧http://www.shangxueba.com数据窗口自适应打印纸张大小函数名:f_dw_Zoom  Writtenby Vial.Z  参数:    datawindowdw_print-->要打印的数据窗口    integer   nMinZoom-->极限缩小比例(缩小范围不能太大,否则不清晰)  返回值:    -1  error    0  找不到合适的值    >0 找到的合理值  作用:     纸张大小满足数据窗口的要求,返回100;    当数据窗口宽度太大,无法在一页纸张上打印时,该程序寻找一个最佳缩小比例值,    使得数据窗口的内容恰好能在当前设定的纸张下打印出来。    如窗口缩小到85%可以在一页上打印时,返回值为85-------------------------------------------------------*/ifnotIsValid(dw_print)then return-1endifdw_print.object.datawindow.print.preview=true  /*预览模式必须打开*/dw_print.SetRedraw(FALSE)  /*调整放大比例过程中,停止重绘控件,节省程序时间*/stringls_H_Page     /*水平打印占据的页数*/stringls_zoom      /*设定的缩小百分比整数值*/Integerli_max=100    /*从百分百大小开始测试*/integerli_min    /*极限缩小值,最多缩小到nn%*/Integerli_use      /*当前测试值*/Integerli_OK =0    /*最优可用值*/Integerli_count=0    /*算法循环执行的次数*/li_min=nMinZoom           /*赋最小测试值*/li_use=li_max     /*从原始大小(100)开始测试。逐渐缩小放大比例*/dowhileli_min<=li_max  li_count++  /*调整zoom值,并测试当前宽度打印时横向所占的面数*/  ls_zoom=string(li_use)  dw_print.modify("datawindow.zoom="+上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comls_zoom)  ls_H_Page=dw_print.describe("evaluate('PageCountAcross()',"+string(dw_print.object.datawindow.firstrowonpage)+")" )    ifInteger(ls_H_Page)=1then  /*一页足以打印出来*/   li_OK=li_use        /*记录这个可用的缩小比例*/   li_min=li_use+1  else   li_max=li_use-1  endif        choosecaseli_max-li_min   caseIS<0    exit   case0    li_use=li_min   case1    li_use=li_min   caseelse    li_use=Int((li_max+li_min)/2) /*小于等于的最小整数*/  endchoose     loop/*还原窗口原大小*/ifli_OK<>100then dw_print.modify("datawindow.zoom=100")endifdw_print.object.datawindow.print.preview=false   dw_print.SetRedraw(TRUE)         /*恢复重绘控件*/returnli_OK使用框架跨域运行不丢失session的方法首先说明原理:系统是认一个一个程序范围的,一般来说,一个IE默认为一个程序范围.  框架因为有了跨域的内容,所以它首先默认的是框架程序本身的程序范围,这样使得框架内的程序范围得不到确认.  为了让这个IE默认为框架内的程序范围,所以我使用了多次跳转.上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  首先,跳出本框架,进入一个无框架的需要session值的网站页面(就叫它B服务器的页面),并在这个页面中生成一个session以便系统自动生成一个sessionID,然后又跳回到有框架的页面.因为系统已经为这个IE生成了一个sessionID,所以只要不关掉这个IE,系统一直以为这个IE是本程序范围的.这样,再次生成的session值就得以在这个ID中生存下来.  也就达到了骗过系统的目的.  再补充一点,二次跳转使用了不同的方式,原因是我需要把框架外的信息丢弃,而要保存框架内的信息.  而不同的跳转方式会丢弃或保存跳转前的信息的。  程序实现方式:  文件1:  框架文件:index.htm(运行在服务器A上)        奇豪门业            <body>  <p>此网页使用了框架,但您的浏览器不支持框架。</p>  </body>      文件2:index.asp(运行在服务器B上,作用跳转和生成sessionID)    <%  ifsession("xm2")=""then  session("xm2")="eee"  '上面这一句的目的只是为了使用session,让系统为这个IE生成一个sessionID,并且判断一下是不是已经跳转过,免得引起死循环。  %>    <%  ,上面这一句是回到框架,注意:只能用上面这个跳转的方法,别用下面的跳转方法。  else  Response.Redirect"index2.asp"  '上面一句才是真正地跳转运行服务器B上的程序!注意:也只能用这方法跳!  endif%>  经过以上的跳转,本IE已经有了服务器B上的sessionID,也就是说,框架虽然是在服务器A上的主框架运行,但它可以确保服务器B上的session不丢失,达到跨域运行的目的。使用MD5变换算法防穷举(冲撞)破译密码 MD5是在Web应用程序中最常用的密码加密算法。由于MD5是不可逆的,因而经过MD5计算得到后的密文,不能通过逆向算法得到原文。  回顾在Web应用程序中使用MD5加密文本密码的初衷,就是为了防止数据库中保存的密码不幸泄露后被直接获得。但攻击者不但拥有数据量巨大的密码字典,而且建立了很多MD5原文/密文对照数据库,能快速地找到常用密码的MD5密文,是破译MD5密文的高效途径。然而,MD5密文数据库所使用的是最常规的MD5加密算法:原文-->MD5-->密文。因此,我们可以使用变换的MD5算法,使现成的MD5密文数据库无所作为。  下面演示一些变换算法的例子      当然,在其它的Web开发语言中,也大同小异,完全能得到相同的结果。变换一:循环MD5  最容易理解的变换就是对一个密码进行多次的MD5运算。自定义一个函数,它接受$data和$times两个形参,第一个是要加密的密码,第二个是重复加密的次数。实现这种变换有两种算法—— 0) {        $data = md5($data);        $times--;        return md5_1_2($data, $times); //实现递归    } else {        return $data;    }}?>变换二:密文分割MD5  尽管用户的密码是不确定的字符串,但是只要经过一次MD5运算后,就会得到一个由32个字符组成的字符串,这时可以再针对这个定长字符串变换。有点BT的算法是,把这段密文分割成若干段,对每段都进行一次MD5运算,然后把这堆密文连成一个超长的字符串,最后再进行一次MD5运算,得到仍然是长度为32位的密文。当然,这种密文分割的具体算法是数之不尽的,比如可以把原密文分割成16段每段两字符、8段每段4字符,或者每一段的字符数不相等……变换三:附加字符串干涉   在加密过程的一个步骤中,附加一个内容确定的字符串(比如说用户名),干涉被加密的数据。不可以用随机字串,因为这样会使原算法无法重现。这种算法在某些情况下是很具有优势的,比如说用于大量的用户密码加密,可以把用户名作为附加干涉字串,这样攻击者就算知道你的算法,也很难从他们手中的字典中一下子生成海量的对照表,然后大量地破译用户密码,只能有针对性的穷举为数不多的用户。变换四:大小写变换干涉  由于PHP所提供的md5()函数返回的密文中的英文字母全部都是小写的,因此我们可以把它们全部转为大写,然后再进行一次MD5运算。变换五:字符串次序干涉  把MD5运算后的密文字符串的顺序调转后,再进行一次MD5运算。变换六、变换七、变换八……  MD5变换算法是数之不尽的,甚至无须自己再去创造,就用上面的五个互相组合就可以搞出很BT的算法。比如说先循环加密后再分割,并在每一段上附加一个字符串再分别加密,然后变换大小写并颠倒字符串顺序后连成一个长字符串再进行MD5运算……  如果真的很不幸,由于某些漏洞,比如说SQL Injection或者文件系统中的数据库被下载而异致用户密码数据暴露,那么MD5变换算法就能大大地增加破译出密码原文的难度,首先就是使网上很多的MD5原文/密文对照数据库(要知道,这是破译MD5最高效的方法)没有用了,然后就是使攻击者用常规算法去穷举一串由变换算法得到的密文而搞得焦头烂额。当然,MD5变换算法特别适合用于非开源的Web程序使用,虽说用在开源的程序中优势会被削弱(大家都知道算法),但是也能抑制MD5原文/密文对照数据库的作用。要进行这些复杂的变换运算,当然就要花费的更多的系统开销了,然而对于安全性要求很严格的系统来说,多付出一些来换取高一点的安全性,是完全值得的。使用Java范型需要注意的地方1、静态方法要想范化,需要指定其类型参数2、非范化类型中的实例方法要想范化,也需要制定其类型参数。  3、范化类型中的实力方法可以直接使用其类型本身的类型参数。  上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com4、范型不是协变的,即List不是List的子类。  5、不能实例化范型类型的数组,即newList[3]是不合法的,提示除非类型参数是一个未绑定的通配符,即newList<?>[3]是合法的。  6、构造延迟,在代码编写时我们不能通过类型参数来构造一个该类型的实例,原因是我们不知道如何构造,类型参数的实际类型是在运行时确定的。  7、对于注意5所描述的问题我们有一个解决方法是Listlist=(List[])newObject[3];但是如果是运行时建立数组呢,类型信息是运行时确定的,那就换种写法T[]tarray=(T[])newObject[3];  8、上面的数组构造是不被推荐的,最好的方法是将类型信息传递到方法中,如method(Classtype){V[]array=(V[])Array.newInstance(type,length);},可以参考ArrayList类的toArray(T[]a)方法的实现。  9、构造通配符引用,如果set是一个Set<?>类型,则Set<?>set2=newHashSet<?>(set);是不合法的,改成Set<?>set2=newHashSet(set);就合法了。使用C#编写查询IP段功能的程序本文将通过一个实例来向大家讲解如何使用C#来编写一个具备查询IP段功能的小程序。  主要功能:查询一个IP所有的IP段.  关键:从Byte数组到ulong的转换出来的数字和IPAddress.Address返回值的是不一样的.  以下是引用片段:  using System;  using System.Collections.Generic;  using System.Text;  using System.Net;  namespace IPUtility  {  class Program  {  static void Main(string[] args)  {  IPRangeManage irm = new IPRangeManage();  irm.Add(new IPRange("石家庄", "219.148.24.0", "219.148.63.255"));  irm.Add(new IPRange("石家庄", "222.222.0.0", "222.222.63.255"));  irm.Add(new IPRange("唐山", "219.148.64.0", "219.148.79.255"));  irm.Add(new IPRange("保定", "219.148.20.0", "219.148.23.255"));  Console.WriteLine(irm.Search("219.148.56.3").Name);上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  Console.ReadLine();  }  }  public class IPRange  {  private string _Name = string.Empty;  private ulong _BeginIP = 0;  private ulong _EndIP = Int32.MaxValue;  /**////   /// IP段名称  ///   public string Name  {  get { return _Name; }  set { _Name = value; }  }  /**////   /// ?始IP  ///   public ulong BeginIP  {  get { return _BeginIP; }  set { _BeginIP = value; }  }  /**////   /// ?束IP  ///   public ulong EndIP  {  get { return _EndIP; }  set { _EndIP = value; }  }  /**////   /// 此IP段的范?  ///   public ulong Range  {  get  {  return EndIP - BeginIP; }  }  public IPRange(string name, string ipBegin, string ipEnd)上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  {  this.Name = name;  this.BeginIP = IP2A(ipBegin);  this.EndIP = IP2A(ipEnd);  }  public static ulong IP2A(string ip)  {  byte[] bytes = IPAddress.Parse(ip).GetAddressBytes();  ulong ret = 0;  foreach (byte b in bytes)  {  ret <<= 8;  ret |= b;  }  return ret;  }  public static int Compare(IPRange x, IPRange y)  {  if(x.Range == y.Range)  return 0;  else if(x.Range > y.Range)  return 1;  else return -1;  }  }  public class IPRangeManage  {  public IPRangeManage()  { }  private List< IPRange> _IPRangeList = new List< IPRange>();  private bool _NeedSort = true;  public void Add(IPRange ipRange)  {  _IPRangeList.Add(ipRange);  _NeedSort = true;  }  private void Sort()  {  if (_NeedSort)  {  _IPRangeList.Sort(new Comparison(IPRange.Compare));  }  }上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  public IPRange Search(string ipString)  {  ulong ip = IPRange.IP2A(ipString);  this.Sort();  foreach (IPRange ir in _IPRangeList)  {  if (ir.BeginIP <= ip && ir.EndIP >= ip)  {  return ir;  }  }  return null;  }  }  }设计模式不是什么很高深的东西,有了这些知识大胆地学习吧。很多人说,看了很多设计模式的文章,为什么就是看不懂呢?我觉得原因可能有两个,第一就是你没有花时间认真看,第二就是看的文章不适合作为切入点。不管学习什么,切入点非常重要,如果切入点不是那么平易近人的话很可能会把你拒之门外,对于初学者来说从实例切入最合适。最好是能碰到自己做过的项目的实例作为切入点,这样你一比较就知道为什么设计模式好了。如果要把设计模式的学习境界分一下级的话,我这么分:l        第一重:能看懂设计模式的文章l        第二重:能自己写一个设计模式的骨架l        第三重:能自己编一个新的运用设计模式的例子l        第四重:能在写代码的时候想到似乎有设计模式适合,在翻阅资料后找到了这种设计模式l        第五重:在理解项目的需求后就能意识到哪里可以使用哪种设计模式进行优化l        第六重:完全掌握了设计模式的精髓,灵活使用各种设计模式以及其变种不管怎么样,多看多做多替换才是学习的办法,别人举例十个都不及自己做一个例子,被动十个原则都不及自己体会出一个原则。每一种设计模式虽然都有一个骨架,但是也不必过于强调这个形式,很多时候根据自己的需求简化一点,改变一点,或者混杂一些其它的设计模式,只要能实现目的了,也是一个不错的选择。很多人会觉得这么多种设计模式没有几种能用得上。我觉得这不是什么问题,用不上那就用不上,这些设计模式是大师经历无数大型项目后的精华,如果能在自己做的一个小项目中用上两三个就很不错了,用上二三十个的项目绝对是怪胎。用不上千万别强求,否则既不利于项目的可维护性又增加了工作量。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com还有很多人会觉得这些设计模式很多都是相似的。而且每个人的感觉还不一样,有人觉得A和B很相似,有人却觉得A和B很好区分,但是B和C却很相似啊。感觉很好区分,说明你看准设计模式的着重点的,感觉一样说明你看到的还是它的形。双胞胎虽然形一样,但是神肯定不一样的,只要认准设计模式解决的问题,就不会看错。 关于本系列文章 本来这些内容都是用来进行公司内部每周知识分享活动的,既然有一些内容了,想想不妨就整理一下贴出来吧。也正由于这个原因,文章中的一些例子都基于团队内部成员所能理解的一些项目,可能这些项目对大家来说比较陌生,不过好处是例子相对比较贴近实际一点。本系列一共有20篇左右,除了介绍23种GOF设计模式中常用的一部分之外(一些设计模式的思想在C#语言中有了更简单的实现,一些设计模式不是很常用)还可能会介绍一些其它有用的设计模式。在这些文章中,我不会过多去说一些理论上的东西,也不会有结构图(这些内容网上到处都是),所有的内容都是围绕相对实际例子展开。我想,只有这样才能更快的吸收设计模式的神而不是其形。在看文章的时候建议你结合《设计模式》一书以及博客园的其它设计模式相关文章一起看,这样才能对设计模式理解的全面和充分一点。每一篇文章都会有以下部分:l        意图:抄设计模式一书的,因为意图实在是太重要,所以不得不首先列出。l        场景:以一个实际的场景来说明为什么要引入设计模式。使用C#编写DES加密程序的framework这个例子中演示了如何使用c#中的加密包进行DES算法加密,由于NGWNET中带的帮助实在是简单,和没有一样,呵呵,不过大家可以借助这个例子一窥DES加密的用法。  des_demo.cs代码如下:  usingSystem;  usingSystem.Security.Cryptography;  usingSystem.IO;  usingSystem.Text;  publicclassEncryptStringDES{  publicstaticvoidMain(String[]args){  if(args.Length<1){  Console.WriteLine("Usage:des_demo",args[0]);  return;  }  //使用UTF8函数加密输入参数  UTF8Encodingutf8Encoding=newUTF8Encoding();  byte[]inputByteArray=utf8Encoding.GetBytes(args[0].ToCharArray());  //方式一:调用默认的DES实现方法DES_CSP.  DESdes=DES.Create();  //方式二:直接使用DES_CSP()实现DES的实体  //DES_CSPDES=newDES_CSP();上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  //初始化DES加密的密钥和一个随机的、8比特的初始化向量(IV)  Byte[]key={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};  Byte[]IV={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef};  des.Key=key;  des.IV=IV;  //建立加密流  SymmetricStreamEncryptorsse=des.CreateEncryptor();  //使用CryptoMemoryStream方法获取加密过程的输出  CryptoMemoryStreamcms=newCryptoMemoryStream();  //将SymmetricStreamEncryptor流中的加密数据输出到CryptoMemoryStream中  sse.SetSink(cms);  //加密完毕,将结果输出到控制台  sse.Write(inputByteArray);  sse.CloseStream();  //获取加密数据  byte[]encryptedData=cms.Data;  //输出加密后结果  Console.WriteLine("加密结果:");  for(inti=0;icscdes_demo.cs  Microsoft(R)C#CompilerVersion7.00.8905[NGWSruntime2000.14.1812.10]  Copyright(C)MicrosoftCorp2000.Allrightsreserved.  运行实例:  D:\csharp>des_demo.exe使用C#编写DES加密程序的framework  加密结果:  3D2264C657D1C4C3CF77CE2FD0E1782A4DED7AA883F90E14E1BA上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com38  7B06418DB5E93F000DC328D1F96D174B6EA7416840  解密后数据:  使用C#编写DES加密程序的framework使用ASP重启服务器 大家知道直接使用ASP是不能够重启服务器的,这时我们需要制作一个组件来实现功能,ASP通过这个组件调用系统API,然后按照不同的重启和关机方式进行操作!        下面先说COM的制作,在VB中新建一工程,当然是AceiveXdll的!    1)先修改工程属性,在工程属性窗口将工程名称改为system,在类模块窗口将模块名称改为contral,保存工程;    2)然后添加一个模块,用来声明需要使用的API和常数!下面是模块中的内容!    DeclareFunctionExitWindowsExLib"user32"(ByValuFlagsAsLong,ByValdwReservedAsLong)AsLong    3)在类模块中输入下列代码:    PublicFunctionreboot(atypeAsVariant)    t&=ExitWindowsEx(1,atype)    EndFunction    该函数需要传入一个参数,用来控制启动方式,这个参数是从ASP程序中传入的,等一下就可以看到具体的使用方法!        编写完上面的代码,保存工程,将工程编译为system.dll。下面就写ASP程序!        ASP中的代码非常简单:    <%    atype=request("atype")    setsys=server.CreateObject("system.contral")    sys.reboot(atype)    %>    其中atype可以使用0、1、2、4,0、1和4均为关机,2用来重启。写完后执行ASP就可以了! JAVA6.0之后,其中JDK自带有个轻量级的webservice服务器。如果你比较细心一定发现在你安装java的路径下,有javawebservice的示例代码。  java开发过webservice,但是当初用了一个apache下axis开源项目。如果axis夜进化了,不过java自带有何必舍近求远呢。最简单javawebservice范例过程记录下来,上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  netbeans6,首先建立一个java应用程序工程,名为WebServices。建立一个服务端程序。  packageWebServices;  importjavax.jws.*;  importjavax.xml.ws.Endpoint;  /**  *@authorhecm  */  @WebService(targetNamespace="http://www.blogjava.net/JAVA-HE",  serviceName="HelloService")  publicclassWSProvider  {  //@WebResult(name="Greetings")//自定义该方法返回值在WSDL中相关的描述  @WebMethod(action="sayHi",operationName="sayHi")  publicStringsayHi(@WebParam(name="MyName")Stringname)  {  return"Hi,"+name;//@WebParam是自定义参数name在WSDL中相关的描述  }  @Oneway//表明该服务方法是单向的,既没有返回值,也不应该声明检查异常  @WebMethod(action="printSystemTime",operationName="printSystemTime")  //自定义该方法在WSDL中相关的描述  publicvoidprintTime()  {  System.out.println(System.currentTimeMillis());  }  publicstaticvoidmain(String[]args)  {  ThreadwsPublisher=newThread(newWSPublisher());  wsPublisher.start();  }  privatestaticclassWSPublisherimplementsRunnable  {  publicvoidrun()  {  //发布WSProvider到http://localhost:8888/hechangmin/WSProvider这个地址,之前必须调用wsgen命令  //生成服务类WSProvider的支持类,命令如下:  //wsgen-cp.WebServices.WSProvider  Endpoint.publish("http://localhost:8888/JAVA-HE/WSProvider",newWSProvider());  }  }  }上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com实战JDK6.0自带webservice 当然建立对应的包,就不用说了。  然后编译文件。  进入命令提示符下,进入classes目录,运行:wsgen-cp.WebServices.WSProvider  可以看到将刚才的class生成了几个java文件和class文件。  现在要做的是发布ws到http://localhost:8888/chinajash/WSProvider  而实际上的动作就是:Endpoint.publish("http://localhost:8888/chinajash/WSProvider",newWSProvider());  当然直接运行WSProvider。  然后输入http://localhost:8888/JAVA-HE/WSProvider?wsdl  就已经查看到生成的wsdl(webservice描述语言)。  也就是服务端就OK了。  保持运行。编写一个测试客户端:  首先选择项目,右键新建web服务客户端。其中wsurl填入刚才生成的wsdl地址:  http://localhost:8888/JAVA-HE/WSProvider?wsdl  (实际上:和wsimporthttp://localhost:8888/JAVA-HE/WSProvider?wsdl一样的效果)  产生一个效果:在classes下按照之前指定的名字空间产生的包下(目录结构)生成了7个帮助class。  然后我们建立一个包client建立测试文件:  /*  *Tochangethistemplate,chooseTools|Templates  *andopenthetemplateintheeditor.  */  packageclient;  importnet.blogjava.java_he.*;  /**  *  *@authorhecm  */  publicclassTest{  publicstaticvoidmain(Stringargs[])  {  HelloServicehs=newHelloService();  WSProviderws=hs.getWSProviderPort();  System.out.println(ws.sayHi("hechangmin"上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com));  ws.printSystemTime();  }  }  运行这个测试类:  Hi,hechangmin  输出了。顺利完成! 提示:一发布的地址最好写成可配置。还有就是wsdl中会严格按照你指定的url来访问,比如你指定的127.0.0.1那么你用本机IP的时候也许并不能顺利访问。实现基于IDEA算法的加密工具/*-文件名:idea.c*/  /*-*/  /*-功能:利用idea加密算法实现文件的加密*/  /*-*/  /*-说明:*/  /*-这是利用IDEA算法实现的文件加密工具可以在法律允许范围内以非商*/  /*-业形式自由使用,该程序的所有权利由作者吴真保留*/  /*-*/  /*-版本号:1.0.0(2002.6)*/  /*-*/  #include  #include  #include  #include  #include  #include"idea.h"  typedefintINT32;  typedefcharINT8;  typedefunsignedcharULONG8;  typedefunsignedshortULONG16;  typedefunsignedlongULONG32;  #defineSUCCESS0  #defineFAIL-1  #defineWZ_COMMEND_NUM4  #defineWZUSEHELPNUM7  #defineREADFILESIZE512/*一次从文件中读取多少字节,可以根据内存的大小调节*/  INT32file_enc(FILE*readfile,FILE*writefile,ULONG8*key);/*加密文件*/  INT32file_dec(FILE*readfile,FILE*writefile,ULONG8*key);/*解密文件*/  INT32hextofile(ULONG8*buf,FILE*writefile,ULONG32length);/*以16进制写入文件*/  INT32encodehex(ULONG8*tobuf,ULONG8*frombuf,ULONG32len);/*16进制解码*/  voidwz_printhelp();/*打印帮助*/  INT8*WZ_Commend_Help[]=  {  "基于IDEA的加密解密工具v1.0",/*0*/  "追求卓越,勇于创新",  "----著者:吴真---",  "上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com"  };  INT8*WZ_USE_HELP[]={  "输入5个参数:",  "\t1.可执行文件名*.exe",  "\t2.操作类型1:加密;2:解密;",  "\t3.读出数据的文件名*.txt",  "\t4.写入数据的文件名*.txt",  "\t5.密钥(32字节)",  "******************************"  };  voidmain(INT32argc,INT8*argv[])  {  INT8*FILENAME1,*FILENAME2;  FILE*fp,*fp2;  ULONG8key[33]={0};/*密钥容器*/  if(argc!=5)  {  wz_printhelp();  return;  }  FILENAME1=argv[2];  FILENAME2=argv[3];  if((fp=fopen(FILENAME1,"r+b"))==NULL||(fp2=fopen(FILENAME2,"w+b"))==NULL)  {  printf("Can'topenfile\n");  return;  }  memcpy(key,argv[4],strlen(argv[4]));/*取得密钥*/  switch(atoi(argv[1]))  {  case1:/*加密操作*/  file_enc(fp,fp2,key);  printf("\n\tIDEA加密完毕,密文存于%s文件\n",FILENAME2);  break;  case2:  /*解密*/  file_dec(fp,fp2,key);  printf("\n\tIDEA解密完毕,明文存于%s文件\n",FILENAME2);  break;  default:  printf("请选择是加密|解密plesechoose上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comencrypt|deencrypt\n");  break;  }  fclose(fp);  fclose(fp2);  }  INT32hextofile(ULONG8*buf,FILE*writefile,ULONG32length)  {  ULONG32writelen=0;  /*以16进制形式写入文件*/  while(writelen0)  {  /*如果从文件中读出的长度不等于0,那么肯定有8个字节以上的空间  文件长度存在最后8个字节中*/  totalfilelen+=filelen;  memcpy(&readbuf[READFILESIZE-8],(ULONG8*)&totalfilelen,4);  for(i=0;i0)/*最后一块有多余的元素*/  {  filelen=fread(sendbuf,sizeof(INT8),READFILESIZE*2,readfile);  encodehex(readbuf,sendbuf,READFILESIZE);  for(i=0;iGetCount();  通过IShellWindows接口的方法Item  可以得到每一个实例对象  IDispatchPtrspDisp;  _variant_tva(i,VT_I4);  spDisp=m_spSHWinds->Item(va);  然后我们可以判断实例对象是不是  属于IE浏览器对象,通过下面的语句实现:  SHDocVw::IWebBrowser2PtrspBrowser(spDisp);  assert(spBrowser!=NULL)在得到了IE浏览器对象以后,我们可以调用IWebBrowser2Ptr接口的方法来得到当前的文档对象的指针:MSHTML::IHTMLDocument2PtrspDoc(spBrowser->GetDocument());然后我们就可以通过这个接口对这个文档对象进行操作,比如通过Gettitle得到文档的标题。我们在浏览网络的时候,一般总会同时开很多IE的实例,如果这些页面都是很好的话,我们可能想保存在硬盘上,这样,我们需要对每一个实例进行保存,而如果我们采用上面的原理,我们可以得到每一个IE的实例及其网页对象的接口,这样就可以通过一个简单的程序来批量的保存当前的所有打开的网页。采用上面介绍的方法实现了对当前IE实例的遍历,但是我们希望得到每一个IE实例所产生的事件,这就需要通过DLL的机制来实现。 3.和IE相绑定的DLL的实现我们介绍一下如何建立和IE进行绑定的DLL的实现的过程。为了和IE的运行实例进行绑定,我们需要建立一个能够和每一个IE实例进行绑定的DLL。IE的启动过程是这样的,当每一个IE的实例启动的时候,它都会在注册表中去寻找这个的一个CLSID,具体的注册表的键位置为:HKEY_LOCALL_MACHINE\SOFTWARE\Microsoft\Windows  \CurrentVersion\Explorer\BrowserHelperObjects上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com当在这个键位置下存在CLSIDs的时候,IE会通过使用CoCreateInstance()方法来创建列在该键位置下的每一个对象的实例。注意对象的CLSIDs必须用子键而非名字值的形式表现,比如{DD41D66E-CE4F-11D2-8DA9-00A0249EABF4}就是一个有效的子键。我们使用DLL的形式而非EXE的形式的原因是因为DLL和IE实例运行在同一个进程空间里面。每一个这种形式的DLL必须实现接口IObjectWithSite,其中方法SetSite必须被实现。通过这个方法,我们自己的DLL就可以得到一个指向IECOM对象的IUnknown的指针,实际上通过这个指针我们就可以通过COM对象中的方法QueryInterface来遍历所有可以得到的接口,这是COM的基本的机制。当然我们需要的只是IWebBrowser2这个接口。实际上我们建立的是一个COM对象,DLL只不过是COM对象的一种表现形式。我们建立的COM对象需要建立和实现的方法有:1.IOleObjectWithSite接口的方法SetSite必须实现。实际上IE实例通过这个方法向我们的COM对象传递一个接口的指针。假设我们有一个接口指针的变量,不妨设为:CComQIPtrm_myWebBrowser2;我们就可以在方法SetSite中把这个传进来的接口指针赋给m_myWebBrowser2。2.在我们得到了指向IECOM对象的接口后,我们需要把自己的DLL和IE实例所发生的事件相关连,为了实现这个目的,需要介绍两个接口:  (1)IConnectionPointContainer。这里使用这个接口的目的是用来根据它得到的IID来建立和DLL的一个特定的连接。比如我们可以进行如下的定义:CComQIPtr  spCPContainer(m_myWebBrowser2);然后,我们需要把所有IE中发生的事件和我们的DLL进行通讯,可以使用IConnectPoint。(2)IConnectPoint。通过这个接口,客户可以对连接的对象开始或者是终止一个advisory循环。IConnectPoint有两个主要的方法,一个为Advice,另一个为Unadvise。对于我们的应用来说,Advise是用来在每一个IE发生的事件和DLL之间建立一个通道。而Unadvise就是用来终止以前用Advise建立的通知关系。比如我们可以定义IConnectPoint接口如下:CComPtrspConnectionPoint;  然后,我们要使所有在IE实例中发生的事件和我们的DLL相关,可以使用如下的方法:hr=spCPContainer->FindConnectionPoint(DIID_DWebBrowserEvents2,&spConnectionPoint);然后我们通过IConnectPoint接口的方法Advice使每当IE有一个新的事件发生的时候,都能够让我们的DLL知道。可以用如下的语句实现:hr=spConnectionPoint->Advise(  (IDispatch*)this,&m_dwIDCode);在把IE实例中的事件和我们的DLL之间建立联系以后,我们可以通过IDispatch接口的Invoke()方法来处理所有的IE的事件。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com3.IDispatch接口的Invoke()方法。IDispatch是从IUnknown中继承的一个接口的类型,通过COM接口提供的任何服务都可以通过IDispatch接口来实现。IDispatch::Invoke的工作方式同vtbl幕后的工作方式是类似的,Invoke将实现一组按索引来访问的函数,我们可以对Invoke方法进行动态的定制以提供不同的服务。Invoke方法的表示如下:STDMETHOD(Invoke)(DISPIDdispidMember,REFIID  riid,LCIDlcid,WORDwFlags,  DISPPARAMS*pdispparams,VARIANT*pvarResult,  EXCEPINFO*pexcepinfo,UINT*puArgErr);其中,DISPID是一个长整数,它标识的是一个函数。对于IDispatch的某一个特定的实现,DISPID都是唯一的。IDispatch的每一个实现都有其自己的IID,这里dispidMemeber实际上是可以认为是和IE实例所发生的每一个事件相关的方法,比如:DISPID_BEFORENAVIGATE2,DISPID_NAVIGATECOMPLETE2等等。这个方法中另外一个比较重要的参数是DISPPARAMS,它的结构如下:typedefstructtagDISPPARAMS  {  VARIANTARG*rgvarg;  //VARIANTARG是同VARAIANT相同的,可以在  //OAIDL.IDL中找到。所以实际上rgvarg是一个参数数  //组  DISPID*rgdispidNameArgs;//命名参数的DISPID  unsignedintcArgs;//表示数组中元素的个数  unsignedintCnameArgs;//命名元素的个数  }DISPPARAMS要注意的是每一个参数的类型都是VARIANTARG,所以在IE和我们DLL之间可以传递的参数类型的数目是有限的。只有那些能够被放到VARIANTARG结构中的类型才可以通过调度接口进行传递。比如对于事件DISPID_NAVIGATECOMPLETE2来说:第一个参数表示IE在访问的URL的值,类型是VT_BYREF|VT_VARIANT。注意DISPID_NAVIGATECOMPLETE2等DISPID已经在VC中被定义,我们可以直接进行使用。如上说述,我们在方法Invoke中可以得到所有IE实例所发生的事件,我们可以把这些数据放到文件中进行事后的分析,也可以放到一个列表框中实时的显示。  4.微软的HTML文档对象模型和应用分析  下面我们来看如何得到网页文档的接口:网页文档的接口为IHTMLDocument2,可以通过调用IECOM对象的get_Document方法来得到网页的接口。使用如下的语句:hr=m_spWebBrowser2->get_Document(&spDisp);  CComQIPtrspHTML;  spHTML=spDisp;上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com这样我们就得到了网页对象的接口,然后我们就可以对网页进行分析,比如通过IHTMLDocument2提供的方法get_URL我们可以得到和该网页相关的URL的地址值,通过get_forms方法可以该网页中所有的Form对象的集合。实际上W3C组织已经制定了一个DOM(DocumentObjecModel)标准,当然这个标准不仅仅是针对HTML,同时还是针对XML制定的。W3C组织只是定义了网页对象的接口,不同的公司可以采用不同的语言和方法进行具体的实现。按照W3C组织定义的网页对象被认为是动态的,即用户可以动态的对网页对象里面所包含的每一个对象进行操作。这里的对象可以是指一个输入框,也可以是图象和声音等对象。同时按照W3C的正式文档的说明,网页对象是可以动态增加和删除的。事实上,很少有厂商实现了DOM定义的所有功能。微软对网页对象的定义也基本上是按照这个标准实现的。但是当前的接口还不支持动态的增加和删除元素,但是可以对网页中的基本元素进行属性的修改。比如IHTMLElementCollection表示网页中一些基本的元素的集合,IHTMLElement表示网页中的一个基本的元素。而象IHTMLOptionElement接口就表示一个特定的元素Option。基本的元素都有setAttribute和geAttribute方法来动态的设置和得到元素的名称和值。较为常见的一个应用是我们能够分析网页中是否有需要填写的Forms,如果这个网址的Forms以前已经填写过而且数据我们已经保存下来的话,我们就可以把数据自动放到和该URL下的Forms的相关的位置中去。另外,我们可以总结网页上需要填写的Form的数据项,先对这些数据项进行赋值,以后碰到有相同的数据项的时候就自动把我们赋值的内容填写进去。实际上Form是对象,Form中包含的元素,比如INPUT,OPTION,SELECT等类型的输入元素都是对象。另外一个可以想到的应用是自动对网页中的文本进行翻译,因为我们可以修改网页中任何对象的属性,所以我们可以把里面不属于本国语言的部分自动翻译成本国语言,当然真正的实现还要靠自然语言理解方面技术的突破,但是IE浏览器的接口和对象的形式使我们能够灵活的控制整个IE,无论是从事件对象还是到网页对象。  5.小结  上面我们分析了如何得到所有IE的实例,同时介绍了和IE实例相捆绑的DLL的详细的实现机制,同时对网页的对象化进行了分析。并且介绍了几个相关的应用和实现的方法及存在的技术问题。IE是一个组件化的以COM为基础的浏览器,它具有强大的功能,同时为应用开发者留下了广阔的空间,当然它也存在体积比较大,速度相对比较慢的缺点。但是它的体系结构代表了微软先进的创新的技术,因此具有强大的生命力。十个糟糕的程序员的行为 1)情绪化的思维  如果你开始使用不同颜色的眼光来看待这个世界的话,那么你可能会成为一个很糟糕的程序员。情绪化的思维或态度很有可能会把自己变成一个怪物。相信你经常可以看到很多很糟糕的程序会使用下面的这些语句:上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  我的程序不可能有这种问题。  Java就是shit。  我最恨的就是使用UML做设计。  需求怎么老在变,没办干了。  受不了这些人,他们到底懂不懂啊。  …………  这些带着情绪化的思维和态度,不但可以让你成为一个很糟糕的程序员,甚至可以影响你的前途。因为,情绪化通常都是魔鬼,会让你做出错误的判断和决定,错误码率的判断和决定直接决定了你的人生。  2)怀疑别人  糟糕的程序总是说:“我的代码一定是正确的,我怀疑编译器有问题”,“我这应该没有问题吧,STL库怎么这么难用啊”。我曾经见过有程序员这样使用STL类:map,当他发现这样放入字符串后却取不出来,觉得那是STL库的BUG,然后自己写了一个map!我的天啊!  某些时候,过早的下结论是一个很不好的习惯,任何事情都有其原因,只有知道了原因,你才能知道是谁的问题。一般来说,总是自己出的问题。  3)过多关注实现,陷入问题细节  有些时候,当我们面对一个问题或是一个需求的时候,糟糕的程序员总是会马上去找一个解决方案或是实现,这是一个很不好的习惯。设计模式告诉我们,“喜欢接口,而不是实现”就是告诉我们,认清问题的本质和特性要比如何实现更重要。  对于一个客户的问题来说,首先应该想到的是如何先让用户正常工作,如何恢复正在“流血”的系统,而不是把用户放在一边而去分析问题的原因和解决方案。  对于解决一个bug来说,重现bug,了解原来程序的意图是首先重要的事,而不是马上去修改代码,否则必然会引入更多的BUG。  对于一个需求来说,我们需要了解的需求后面的商业背景,usecase和真实意图,而不是去讨论如何实现。只有了解了用户的真实意图,实际使用的方式和案例,你才能真正如果去做设计。  糟糕的程序总是容易陷入细节,争论于如何实现和实现难题,以及问题的根本原因,而忽略了比这些更重要的东西。只有看懂了整个地图,我们才知道要怎么去走。  4)使用并不熟悉的代码  糟糕的程序员最好的朋友是Ctrl-C和Ctrl-V,有些时候,他们并不知道代码的确切含义,就开始使用它,有证据表明,由拷贝粘贴引发的bug占了绝大多数。因为,代码总是只能在特定的环境下才能正常地工作,如果代码的上下文改变了,很有可能使得代码产生很多你不知道的行为,当你连代码都控制不住了,你还能编出什么好的程序呢?上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  5)拼命工作而不是聪明的工作  对于糟糕的程序员,我们总是能看到他们拼命地修正他们的bug,总是花非常多时间并重复地完成某一工作。而好的程序可能会花双倍的时间来准备一个有效的开发环境,工具,以及在开发的时候花双倍甚至10倍的时间来避免一些错误。好的程序员总是会利用一切工具或手段来让自己的工作变得更有效率,总是为在开发的时候尽可能得不出错。后期出错的成本将会是巨大的,而且那时改正错误的压力也是巨大的。所以,糟糕的程序通常会让自己进入一种恶性循环,他们看上去总是疲惫的,总是很辛苦的,所以更没有时间来改善,越没有时间来改善,就有越多的问题。所以,拼命工作有些时候可能表明你不是一个好的程序员。  6)总是在等待、找借口以及抱怨  当需求不明确的时候,当环境不是很满意的时候,他们总是在等待别人的改善。出现问题的时候,总是在找借口,或是抱怨这也不好,那也不好,所以自己当然就没有做好。糟糕的程序员总是希望自己的所处的环境是最好的,有明确的需求,有非常不错的开发环境,有足够的时间,有不错的QA,还有很强的teamleader,以及体贴自己的经理,有足够的培训,有良好的讨论,有别人强有力的支持……,这是一种“饭来张口,衣来伸手”的态度,这个世界本来就不完美,一个团队需要所有人去奋斗,况且,如果什么都变得完美了,那么,你的价值何在吗?drivinginsteadofwaiting,leadinginsteadoffollowing。7)滋生办公室政治  有句话叫“丑女多作怪”,意思是说如果一个自己没有真实的能力的话,那么他一定会在其它方面作文章。糟糕的程序员也是这样,如果他们程序编不好的话,比不过别人的话,他们通常会去靠指责别人,推脱责任,或是排挤有能力的人,等等不正常的手段来保全自己。所以,糟糕的程序通常伴随着办公室政治。  8)说得多做得少  糟糕的程序员总是觉得自己什么都懂,他们并不会觉得自己的认识和知识都是有限的。这就是所谓的夸夸其谈,是的,什么都做不好的程序员能靠什么混日子呢?就是吹啊吹啊。  另一个表现方式是他们在评论起别人的程序或是设计,总是能挑出一堆毛病,但自己的程序写得也很烂。总是批评抱怨,而没有任何有建设性的意见,或是提出可行的解决方案。  这些糟糕的程序员,总是喜欢以批评别人的程序而达到显示自己的优秀。{#pag#}  9)顽固  当你给出一打证据说明那里有一个更好的方案,那里有一个更好的方向的时候,他们总是会倔强的认为他们自己的做法才是最好的。一个我亲身经历的事例就是,当我看到一个新来的程序员在解决一个问题的时候走到了错误的方向上时,我提醒他,你可能走错了,应该是另外那边,并且我证明了给他看还有一个更为简单的方法,有。然而,这位程序员却告诉我,“那是我的方法,我一定要把之走下去,不然我会非常难受”,于是,在三天后的代码评审中,在经过顽固地解释以及一片质疑声中,他不得不采用了我最先告诉他的那个方法。  这些程序员,从来不会去想,也不会去找人讨论还有没有更好的方法,而是坚持自己的想法,那怕是条死路都一往直前,不撞南墙永不回头。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  10)写“聪明”的代码  他们写出来的代码需要别的同事查看程序语言参考手册,或是其程序的逻辑或是风格看上去相当时髦,但却非常难读。代码本应该简洁和易读,而他们喜欢在代码中表现自己,并尝试另类的东西,以显示自己的才气。是的,只有能力有问题的程序员才需要借助这样的显示。  记得以前的一个经历,一位英语很不错的程序员加入公司,本来对我们这些英语二把刀来说,我们喜欢看到的是简单和易读的英文文档,然后,那位老兄为了展示他的英语如何牛,使用了很多GRE中比较生僻的短语和词汇。让大家阅读得很艰苦。最有讽刺意味的是,有一位native的美国人后来在其邮件中询问他某个单词的意思。呵呵。  你是一个糟糕的程序员吗?欢迎你分享你的经历。深入了解C语言——函数的使用(实例)C语言生成的代码在执行效率上比其它高级语言都高。现在让我们来看看C语言生成的代码具体是什么样子的。当你看完本文对于C语言的了解一定会更深一步了。  本文通过一个个实际案例程序来讲解C语言。  研究案例一  工具:TurbocCv2.0,Debug,MASMv5.0,NASM  实例C程序:  /*example1.c*/  charch;  inte_main()  {  e_putchar(ch);}  目标内容:C语言调用函数的方法与细节我们使用的C编译器是16位的TurbocCv2.0,它生成的是16位的代码,比较简单,方便我们来研究。同时我们也需要用到DOS下的DEBUG来进行反汇编。由于我们很多案例中的程序并不是完整的C程序,所以Turboc下的Tlink并不能为我们生成目标程序,所以我将使用MASM中的link.exe,同时里面的exe2bin.com也可以为我们把exe文件转换成bin文件。这个程序没有main函数,我们用e_main来代替main函数.这样我们能避开C语言对main函数进行一系列处理的代码.同样,我们也用e_putchar()来代替我们平常使用的putchar().这里"e"的意思就是"example"。没有了main函数,我们的C程序就没有了入口,所以在开始编译这段C代码之前,我还得写几行简单的汇编代码,通过它来作为我们程序的入口。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com;C程序的入口start.asm  [BITS16]  [globalstart]  [extern_e_main]  start:  call_e_main按照C语言的习惯,所以C总的名词都要自动在前面加一个"_"下划线.所以,我们在C中的e_main函数,如果要在汇编中调用,就变成了_e_main函数.这段汇编代码只有一句:call_e_main,就是调用我们在C中的e_main函数。  这段代码我将用nasm来进行编译.生成start.obj  nasmw-fobj-ostart.objstart.asm  下面我们用TurbocC来编译这段C代码:  TCC-mt-oexample1.obj-cexample1.c  linkstart.objexample1.obj,example1.exe,,,  exe2binexample1.exe  这样,我们就得到了这段C代码编译出来的机器代码文件(example1.bin)了。  下面我们用DEBUG这个老DOS的工具来对example1.bin进行反汇编。DEBUG  -nexample1.bin  -l0  -u0  xxxx:0000CALL0003  xxxx:0003MOVAX,000B  xxxx:0006PUSHAX  xxxx:0007CALL0020  xxxx:000APOPCX  这里看到蓝色的代码就是我们整个C程序的所生成的代码了。  最开始的第一句CALL0003是我们用nasm编译的start.asm所生成的代码。我们主要目标是研究蓝色的C语言的代码,第一句start.asm所生成的代码太简单,就是调用e_main函数。而我们的e_main函数就是蓝色代码部分。从C源程序中我们看到,我们在e_main做的就是一件事情:调用e_putchar(ch);其中ch是传给出e_putchar的参数。MOVAX,000B  000B就是我们的全局变量ch所在内存的地址。C语言会把所有的全局变量在另一块内存区.C代码先把ch的地址传给AX,然后通过  PUSHAX  把AX的值,也就是ch的地址压入堆栈。然后再  CALL0020上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  而0020就是e_putchar代码的地址。通过这跳语句,计算机就跳到e_putchar的代码部分去执行了.我在这里并不给出e_putchar的代码,因为我们这个案例只是研究C语言中如何传递参数给其它函数的,并不管e_putchar如何取参数。下在一个案例中,我们将研究函数如何取参数。在这里我得把CALL指令解释清楚,因为在下个研究函数如何取参数的部分中大家可能会迷惑.CALLXXXX指令简单地或就是  PUSHIP  JMPXXXX  它首先把当前的执行地址IP压入堆栈,然后跳转到要CALL的地址去。CALL和RET指令是配套的。RET指令等同于  POPIP  也就是回复CALL前的执行地址IP。  正因为这样,所以你一旦使用了CALL指令,你的堆栈指针SP就会自动减2。POPCX  是每个函数调用完毕后都有的必备操作。在这里它不起任何作用。可能唯一的作用就是与CALL0020前的PUSHAX像对应.这样堆栈指针SP才能回原。  好了,简单的第一个案例研究结束了。虽然就这4跳指令,但是我们已经可以看出C语言传递参数方法了。总结起来就是通过"MOVAX,参数地址"把参数的地址传到AX,然后"PUSHAX"把参数的地址压入堆栈。最后"CALL函数地址"转向执行要调用的函数。最后调用完后,"POPCX",恢复堆栈指针SP。 研究案例二  工具:TurbocCv2.0,Debug,MASMv5.0,NASM,TASM  实例C程序:  /*example1.c*/  charch;  externvoide_putchar(charc);  inte_main()  {  ch=0x44;  e_putchar(ch);}  实例汇编程序:  ;eio.asm  _TEXTsegmentbytepublic'CODE'  DGROUPgroup_TEXT  assumecs:_TEXT,ds:DGROUP,ss:DGROUP  public_k_putchar  _k_putcharproc上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comnear  pushbp  movbp,sp  movah,0eh  movbx,7h  moval,byteptr[bp+4]  int10h  popbp  ret  _k_putcharendp 目标内容:C语言中函数使用参数的方法这一节我们将使用TASM用汇编来写个标准的C函数。这一节的内容大家可能在很多汇编的书籍上都看到过。讲的是C语言和汇编语言的连接方法。可能你会奇怪,我们这里已经有了MASM,NASM两个汇编编译器了,为什么还要使用TASM另外一个汇编编译器.我不知道MASM是否可以和我们的TurbocC配合,但是TASM是肯定可以和TurbocC完全配合的.毕竟它们都是Borland公司的产品,而且TurbocC中用-S生成的汇编代码是完全按照TASM中的语法而定的。这足以见TurbocC和TASM之间"亲密的"关系了。这个案例中我们主要并不研究C代码了.而是研究那个用汇编写的C函数。  pushbp  movbp,sp  movah,0eh  movbx,7h  moval,byteptr[bp+4]  int10h  popbp  ret  其中byteptr[bp+4]就是我们传给e_putchar()的参数值。  前一个案例中我们一直知道了C语言是把参数的地址压入堆栈的方式传给函数。所以在标准的C函数中,都是通过取堆栈里的值来读参数。标准的C函数前两行都是  pushbp  movbp,sp  首先保存BP的值,然后把当前的堆栈指针传递给BP,我们访问传递给该函数的参数就是通过BP。而第一个参数值就放在BP+4的地址中,第二个参数值就放在BP+6,...,这样依此对应每个参数的地址.BP就是CALL调用前的IP的值.因为CALL执行的时候,系统会自动把当前的IP压入堆栈。关于这个前面一个案例中已经给出介绍。  别看这个C函数是用汇编语言写的,它可是个完完整整的C函数。  好了,让我们编译出来看看。  TASMeio.asm上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comeio.obj  TCC-mt-oexample1.obj-cexample1.c  linkstart.objeio.objexample1.obj,example1.exe,,,  exe2binexample1.exe好了,该是我们总结的时候了。  C语言中函数访问参数的方法就是先通过"PUSHBP"保存BP,"MOVBP,SP"把当前的堆栈指针传递给BP。第一个参数的地址就在BP+4,第二个参数的地址就在BP+6,...比如"MOVAX,WORDPTR[BP+4]"就可以把第一个参数值传给AX寄存器。而需要留意的是C/C++传递参数的顺序是和其它语言相反的。C语言是把参数的地址从右到左压入堆栈,所以越后面的参数,在堆栈中的地址越靠前。深入讲解JSP2.0下的动态内容缓存技术内容缓存是Web应用中最普通的优化技术之一,例如,可以使用一个自定义地JSP标签——我们将之命名为<jc:cache>——由<jc:cache>和</jc:cache>将每一个需要被缓存的页面片段封装起来。任何自定义标签可以控制它所包含部分(也即预先封装的页面片段)在何时执行,并且动态输出结果可以被捕获。<jc:cache>标签使得JSP容器(例如Tomcat)只生成内容一次,作为应用程序范围内的JSP变量,来存储每一个缓存片段。每次JSP页面被执行时,自定义标签将缓存页面片段载入而无需再次执行JSP代码来生成输出结果。作为Jakarta工程的一个部分,标签库的开发使用了这项技术。当被缓存内容无需被每一个用户或者请求所定制的时候,它工作的十分良好。这篇文章对上面描述的技术做了改进,通过使用JSP2.0表达式语言(EL),允许JSP页面为每一个请求和用户定制缓存内容。缓存页面片段可以包含未被JSP容器赋值的JSP表达式,在每一次页面被执行时,由自定义标签来确定这些表达式的值。因此,动态内容的建立被最优化,但是缓存片段可以含有部分由每一个请求使用本机JSP表达式语言产生的内容。通过JSP2.0ELAPI的帮助,Java开发者可以用表达式语言来使之成为可能。  内容缓存VS数据缓存内容缓存不是唯一的选择。例如,从数据库中提取的数据同样可以被缓存。事实上,由于存储的信息中不包含HTMLmarkup,以及要求较少的内存,数据缓存可能更加高效率。然而在很多情况下,内存缓存更容易实现。假设在某个案例总,一个应用由大量事务对象,占用重要的CPU资源,产生复杂的数据,并且用JSP页面来呈现这些数据。工作一切良好,直到某天突然地服务器的负载增加,需要一个紧急解决方案。这时在事务对象和呈现表达层之间建立一个缓存层,时一个非常不错和有效的方案。但是必须非常快速和流畅地修改缓存动态内容的JSP页面。相对于简单的JSP页面编辑,应用程序的业务逻辑变化通常要求更多的工作量和测试;另外,如果一个页面从多个复合源聚合信息时,Web层仅有少量的改变。问题在于,当缓存信息变得失去时效时,缓存空间需要被释放,而事务对象应该知道何时发生这种情况。然而,选择实现内容缓存还是数据缓存,或者其他的优化技术,有很多不得不考虑的因素,有时是所开发的程序所特殊要求的。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com数据缓存和内容缓存没有必要互相排斥,它们可以一起使用。例如,在数据库驱动的应用中;从数据库中提取出来的数据,和呈现该数据的HTML分别被缓存起来。这与使用JSP实时生成的模板有些相似。这篇文章中讨论的基于ELAPI技术说明如何使用JSPEL来将数据载入到呈现模板中。  使用JSP变量缓存动态内容每当实现一个缓存机制是,都需要一个存储缓存对象的方法,在这篇文章中涉及的是String类型的对象。一种选择是使用一个对象——缓存框架结构,或者使用Javamaps来实现自定义的缓存方案。JSP已经拥有了称为“scopedattributes”或“JSPvariables”来提供ID——object映射,这正是缓存机制所需要的。对于使用page或者requestscope,这是没有意义的,而在应用范围内,这是一个很好的存储缓存内容的位置,因为它被所有的用户和页面共享。当每一个用户需要单独缓存时,Sessionscope也可以被使用,但这不是很有效率。JSTL标签库可以被是与那个来缓存内容,通过使用JSP变量正如下例所示: <%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%><c:iftest="${emptycachedFragment}">  <c:setvar="cachedFragment"scope="application">  ...  </c:set></c:if>  缓存页面片段用下列语句输出结果: ${applicationScope.cachedFragment}    当缓存片段需要被每一个请求所定制的时候,到底发生了什么?  例如,如果希望包含一个计数器,需要缓存两个片段:  <%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%><c:iftest="${sessionScope.counter==null}">  <c:setvar="counter"scope="session"value="0"/></c:if><c:setvar="counter"value="${counter+1}"scope="session"/><c:iftest="${emptycachedFragment1}">  <c:setvar="cachedFragment1"scope="application">  ...  </c:set></c:if><c:iftest="${emptycachedFragment2}">  <c:setvar="cachedFragment2"scope="application">  ...  </c:set></c:if>      可以使用下面语句输出缓存内容:${cachedFragment1}${counter}${cachedFragment2}上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com 通过专门的标签库的帮助,需要定制的页面片段的缓存变得异常容易了。上面已经提及,缓存内容可以被开始标签(<jc:cache>)和结尾标签(</jc:cache>)封装起来。而每一个定制可以使用另一个标签(<jc:dynamicexpr="..."/>)输出一个JSP表达式(${...})来表现。动态内容用JSP表达式缓存并在每一次缓存内容被输出时赋值。在下面的部分可以看到这是如何实现的。Counter.jsp缓存了一个包含计数器的页面片段,当每一次用户刷新这个页面的时候计数器会自动+1。<%@taglibprefix="c"uri="http://java.sun.com/jsp/jstl/core"%><%@taglibprefix="jc"uri="http://devsphere.com/articles/jspcache"%><c:iftest="${sessionScope.counter==null}">  <c:setvar="counter"scope="session"value="0"/></c:if><c:setvar="counter"value="${counter+1}"scope="session"/><jc:cacheid="cachedFragmentWithCounter">  ...<jc:dynamicexpr="sessionScope.counter"/>  ...</jc:cache>JSP变量易于使用,对于简单的Webapps,这是一个不错的内容缓存方案。然而,如果应用程序产生大量的动态内容,没有对缓存大小的控制无疑是一个问题。一种专用的缓存框架结构能够提供一个更加有力的方案,允许对缓存的监视,限制缓存大小,控制缓存策略,等等……  使用JSP2.0表达式语言APIJSP容器(例如Tomcat)对应用ELAPI的JSP页面中的表达式予以赋值,并且可以被Java代码所使用。这允许在Web页面外应用JSPEL作开发,例如,对XML文件、基于文本的资源以及自定义脚本。当需要控制何时对Web页面中的表达式进行赋值或者书写与之相关的表达式时,ELAPI同样是有用的。例如,缓存页面片段可以包含自定义JSP表达式,并且当每一次缓存内容被输出时,ELAPI将用来给这些表达式赋值或者重新赋值。文章提供了一个例子程序(参见文末资源部分),这个应用程序包含了一个Java类(JspUtils)和类中包含一个方法eval(),这个方法有三个参数:JSP表达式、表达式的期望类型和一个JSPcontext对象。Eval()方法从JSPcontext中取得ExpressionEvaluator并且调用evaluate()方法,通过表达式、表达式的期望类型、和一个从JSPcongtext中获得的变量。JspUtils.eval()方法返回表达式的值。packagecom.devsphere.articles.jspcache;  importjavax.servlet.jsp.JspContext;  importjavax.servlet.jsp.JspException;  importjavax.servlet.jsp.PageContext;  上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comimportjavax.servlet.jsp.el.ELException;  importjavax.servlet.jsp.el.ExpressionEvaluator;  importjava.io.IOException;publicclassJspUtils{  publicstaticObjecteval(  Stringexpr,Classtype,JspContextjspContext)  throwsJspException{  try{  if(expr.indexOf("${")==-1)  returnexpr;  ExpressionEvaluatorevaluator=jspContext.getExpressionEvaluator();  returnevaluator.evaluate(expr,type,  jspContext.getVariableResolver(),null);  }catch(ELExceptione){  thrownewJspException(e);  }  }  ...}  注意:JspUtils.eval()主要封装了标准的ExpressionEvaluator。如果expr不包含${,JSPELAPI不被调用,因为没有JSP表达式。创建标签库描述符(TLD)文件JSP标签库需要一个标签库描述符(TLD)文件来自定义标签的命名,它们的属性,以及操作该标签的Java类。jspcache.tld描述了两个自定义标签,<jc:cache>拥有两个属性:缓存页面片段的id和JSPscope—JSP页面总需要被储存的内容范围。<jc:dynamic>只有一个属性,即JSP表达式必须在每一次缓存片段被输出时被赋值。TLD文件将这两个自定义标签映射到CacheTag和DynamicTag类,如下所示:<?xmlversion="1.0"encoding="UTF-8"?><taglibxmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2eeweb-jsptaglibrary_2_0.xsd"  version="2.0">  <tlib-version>1.0</tlib-version>  <short-name>jc</short-name>  <uri>http://devsphere.com/articles/jspcache</uri>  <tag>  <name>cache</name>  上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com<tag-class>com.devsphere.articles.jspcache.CacheTag</tag-class>  <body-content>scriptless</body-content>  <attribute>  <name>id</name>  <required>true</required>  <rtexprvalue>true</rtexprvalue>  </attribute>  <attribute>  <name>scope</name>  <required>false</required>  <rtexprvalue>false</rtexprvalue>  </attribute>  </tag>  <tag>  <name>dynamic</name>  <tag-class>com.devsphere.articles.jspcache.DynamicTag</tag-class>  <body-content>empty</body-content>  <attribute>  <name>expr</name>  <required>true</required>  <rtexprvalue>false</rtexprvalue>  </attribute>  </tag></taglib>  TLD文件包含在Web应用描述符文件(web.xml)中,这五个文件同样包含一个初始参数指出cache是否可用。<?xmlversion="1.0"encoding="ISO-8859-1"?><web-appxmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2eeweb-app_2_4.xsd"  version="2.4">  <context-param>  <param-name>com.devsphere.articles.jspcache.enabled</param-name>  <param-value>true</param-value>  </context-param>  <jsp-config>  <taglib>  <taglib-uri>http://devsphere.com/articles/jspcache</taglib-uri>  <taglib-location>/WEB-INF/jspcache.tld</taglib-location>  </taglib>  </jsp-config></web-app>  理解<jc:cache>的工作机理上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comJSP容器为JSP页面中的每一个<jc:cache>标签创建一个CacheTag实例,来对其处理。JSP容器负责调用setJsp()、setParent()和setJspBody()方法,这是CacheTag类从SimpleTagSupport继承而来。JSP容器同事还为所操作标签的每一个属性调用setter方法。SetId()和setScope()方法存储属性值到私有域,这个值已经用CacheTag()构造函数用缺省值初始化。packagecom.devsphere.articles.jspcache;  importjavax.servlet.ServletContext;  importjavax.servlet.jsp.JspContext;  importjavax.servlet.jsp.JspException;  importjavax.servlet.jsp.PageContext;  importjavax.servlet.jsp.tagext.SimpleTagSupport;  importjava.io.IOException;importjava.io.StringWriter;  publicclassCacheTagextendsSimpleTagSupport{  publicstaticfinalStringCACHE_ENABLED  ="com.devsphere.articles.jspcache.enabled";  privateStringid;  privateintscope;  privatebooleancacheEnabled;  publicCacheTag(){id=null;scope=PageContext.APPLICATION_SCOPE;  }publicvoidsetId(Stringid){this.id=id;  }  publicvoidsetScope(Stringscope){this.scope=JspUtils.checkScope(scope);  }...}setScope()方法调用JspUtils.checkScope()来校验已经从String转换为int类型的scope的属性值。  ...publicclassJspUtils{  ...  publicstaticintcheckScope(Stringscope){  if("page".equalsIgnoreCase(scope))  returnPageContext.PAGE_SCOPE;  elseif("request".equalsIgnoreCase(scope))  returnPageContext.REQUEST_SCOPE;  elseif("session".equalsIgnoreCase(scope))  returnPageContext.SESSION_SCOPE;  elseif("application".equalsIgnoreCase(scope))  returnPageContext.APPLICATION_SCOPE;  上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comelse  thrownewIllegalArgumentException(  "Invalidscope:"+scope);  }}  一旦CacheTag实例准备对标签进行操作,JSP容器调用doTag()方法,用getJspContext()来获得JSPcontext。这个对象被造型为PageContext,从而可以调用getServletContext()方法。servletcontext用来获取初始化参数的值,这个值标明缓存机制是否被启用。如果缓存被启用,doTag()尝试使用id和scope属性值来获得缓存页面片段。如果页面片段还没有被缓存,doTag()使用getJspBody().invoke()来执行由<jc:cache>和</jc:cache>封装的JSP代码。由JSPbody产生的输出结果缓冲在StringWriter并且被toStirng()方法获得。这样,doTag()调用JSPcontext的setAttribute()方法新建一个JSP变量,这个变量控制可能包含JSP表达式(${…})的缓存内容。这些表达式在用jspContext.getOut().print()输出内容前,被JspUtils.eval()赋值。只有当缓存被启用的时候,这些行为才发生。否则,doTag()只是通过getJspBody().invoke(null)执行JSPbody并且输出结果不被缓存。...publicclassCacheTagextendsSimpleTagSupport{...publicvoiddoTag()throwsJspException,IOException{  JspContextjspContext=getJspContext();  ServletContextapplication  =((PageContext)jspContext).getServletContext();  StringcacheEnabledParam=application.getInitParameter(CACHE_ENABLED);  cacheEnabled=cacheEnabledParam!=null  &&cacheEnabledParam.equals("true");  if(cacheEnabled){  StringcachedOutput=(String)jspContext.getAttribute(id,scope);  if(cachedOutput==null){StringWriterbuffer=newStringWriter();  getJspBody().invoke(buffer);  cachedOutput=buffer.toString();  jspContext.setAttribute(id,cachedOutput,scope);  }      StringevaluatedOutput=(String)JspUtils.eval(  cachedOutput,String.class,jspContext);  jspContext.getOut().print(evaluatedOutput);  上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com}else  getJspBody().invoke(null);  }  ...}注意一个单独的JspUtils.eval()调用给所有的${…}表达式赋值。因为一个包含了大量的${…}结构的text也是一个表达式。每一个缓存片段都可以被当作一个复杂的JSP表达式来进行处理。    IsCacheEnabled()方法返回cacheEnabled的值,这个值已经被doTag()初始化。IsCacheEnabled()方法返回cacheEnabled的值,这个值已经被doTag()初始化。...publicclassCacheTagextendsSimpleTagSupport{...  publicbooleanisCacheEnabled(){  returncacheEnabled;  }}  <jc:cache>标签允许页面开发者自主选择缓存页面片段的ID。这使得缓存一个页面片段可以被多个JSP页面共享,当需要重用JSP代码时,这是很有用处的。但是仍然需要一些命名协议来避免可能的冲突。通过修改CacheTag类来在自动ID内部包含URL可以避免这种副作用。 理解<jc:dynamic>在做什么  每一个<jc:dynamic>被一个DynamicTag类的实例处理,setExpr()方法将expr属性值存储到一个私有域。DoTag()方法创建JSP表达式,在expr属性值加上${前缀和}后缀。然后,doTag()使用findAncestorWithClass()来查找含有<jc:dynamic>标签元素的<jc:cache>的CacheTaghandler。如果没有查找到或者缓存被禁用,JSP表达式被JspUtils.eval()赋值并且值被输出。否则,doTag()输出无值表达式。packagecom.devsphere.articles.jspcache;  importjavax.servlet.jsp.JspException;  importjavax.servlet.jsp.tagext.SimpleTagSupport;  importjava.io.IOException;  publicclassDynamicTagextendsSimpleTagSupport{  privateStringexpr;  publicvoidsetExpr(Stringexpr){this.expr=expr;  }  publicvoiddoTag()throwsJspException,IOException上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com{Stringoutput="${"+expr+"}";  CacheTagancestor=(CacheTag)findAncestorWithClass(  this,CacheTag.class);  if(ancestor==null||!ancestor.isCacheEnabled())  output=(String)JspUtils.eval(  output,String.class,getJspContext());  getJspContext().getOut().print(output);  }}  分析上面的代码,大家可以注意到<jc:cache>和<jc:dynamic>合作来实现一个尽可能有效率的方案。如果缓存可用,页面片段和由<jc:dynamic>生成并被CacheTag赋值的JSP表达式一起放入缓冲器。如果缓存被禁用,缓冲变得没有意义,<jc:cache>只是执行其JSPbody部分,而让DynamicTag给JSP表达式赋值。禁用缓存有时候是必要的,特别是在开发过程期间出现内容的改变和JSP页面被重新编译的时候。当然,在开发完毕的成品环境中缓存必须被启用。  总结  内容缓存是一种非常易用的改善Web应用性能的方法。这篇文章集中讨论了使用JSP表达式语言来为每一个用户或者请求定制缓存内容。贯穿全文的简单介绍的标签库适合小型Webapps并且可以提升中等应用的性能。对于开发大型企业级应用,则应当考虑使用支持更好的缓存机制的框架结构,而不仅仅局限于使用JSP变量。软考程序员辅导:字符串查找算法BM算法 字符串查找算法中,最著名的两个是KMP算法(Knuth-Morris-Pratt)和BM算法(Boyer-Moore)。两个算法在最坏情况下均具有线性的查找时间。但是在实用上,KMP算法并不比最简单的c库函数strstr()快多少,而BM算法则往往比KMP算法快上3-5倍。  但是,最坏的情况下,BM的时间复杂度貌似也是n×n。  具体就不说了,BM算法是通过往后跳动主文本字符串来实现快速非回溯查找的,跳动的算法就是用程序中的这句来实现的,下面:  i=i+m-min(j,1+last(p,T[i]));  而last是一个求文本字符串中的字符在查找字符串里面出现的最后位置。  这个算法很麻烦,呵呵,可以的话百度一下。  整个代码如下:  #include  intlast(char*p,charc){//考试,大提示找到c在p中最后匹配的位置,没有就返回-1  intlength=strlen(p),count=0;  char*pp=p+length上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com-1;  while(pp>=p)  {  if(*pp==c)  {  returnlength-count-1;  }  pp--;  count++;  }  return-1;  }  intmin(inta,intb){  return(a<=b)?a:b;  }  intBM_index(char*T,char*p){  intn=strlen(T);  intm=strlen(p);  inti=m-1,j=m-1;  while(i<=n-1)  {  if(T[i]==p[j])  {  if(j==0)  {  returni;  }  else  i--,j--;  }  else{  i=i+m-min(j,1+last(p,T[i]));//往后跳,取决于最后一次匹配的字符的位置  j=m-1;  }  }  return-1;  }  int_tmain(intargc,_TCHAR*argv[])  {  char*p="woainizz!izzzzzz--zzzzut";  inta=BM_index(p,"zzzzut");//结果18,没有问题  return0;  }上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com软考程序员辅导:数据结构(Stack栈) classNode  {inta;  publicNode(inta)  {this.a=a;}  publicintA  {get{returna;}set{a=value;}}  publicNodenext;  }  classLinkedList  {protectedNodeheader;  publicvoidGenerate(intx)  {if(header==null)  header=newNode(x);  else  {Noden=newNode(x);  n.next=header;  header=n;  }  }  publicvoidOut()  {Nodetmp=header;  while(tmp!=null)  {Console.WriteLine(tmp.A);  tmp=tmp.next;  }}}  classStack:LinkedList  {publicvoidPush(intx)  {this.Generate(x);}  publicintPop()  {if(this.header==null)  return-1;//emptystack  intn=header.A;  header=header.next;  returnn;  }  }  classTest  {staticvoidMain()  {Stackss=new上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comStack();  ss.Push(7);  ss.Push(78);  ss.Push(9);  ss.Push(2);  inti=ss.Pop();  while(i!=-1)  {Console.WriteLine(i);  i=ss.Pop();  }}}}如何在程序中使用自己的库单元用过VB的人都知道,可以在工程中增加类模快来存放共用方法,而在delphi中如何也能与VB一样存放自己的类呢?通过下面的讲解,我想你一定会有所收获的。  一、在工程中增加一个库单元  单击菜单的顺序为File->New->Unit这样就为你的工程增加了一个库单元。新增加的库单元内容如:unitglobal;//库单元的名字interface          file://<---这里加入选择性库单元列表implementationend.  二、在库单元中增加自己的类  在ObjectPascal中,用关键字Class来声明类。使用如下语法:Type    CTestclass=class file://定义一个类,命名规律自己看一看delphi相关的命名规律end;  当然,这段代码,没有什么实际用途,只是仅仅声明了一个空类,而类在没有任何的数据和*作,在下面我们可以向类中添加数据和方法。Type    CTestclass=class    Tmessage:String;    ProcedureSetText(text:String);    FunctionGetText:String;end;  类的函数成员和过程成员成为类的方法。他们的说明和定义方法与普通的函数和过程相似,唯一的区别是要在函数名和过程名前面加类名和句点。Procdeure上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comCTestclass.SetText(text:String);BeginTmessage:=text;end;FunctionCTestclass.GetText:String;Begin    GetText:=Tmessage;end;  这样一个简单的类就编写完成了,你可以按下面所讲的步骤进行调用。将上面的代码整理一下,这个库单元的完整代码如下:unitglobal;//库单元的名字interfacefile://接口部分uses             windows;//需要引用的其它库单元列表Typefile://接口类型定义    CTestclass=class    Tmessage:String;    ProcedureSetText(text:String);    FunctionGetText:String;end;implementationProcdeureCTestclass.SetText(text:String);BeginTmessage:=text;end;FunctionCTestclass.GetText:String;Begin    GetText:=Tmessage;end;end.如何在Win9x/2k下建立共享目录在Windows中建立一个共享目录,通常是使用NetShareAdd函数.但是在Win2k和Win9x下,这个函数分别是包含在Netapi32.dll和Svrapi.dll中.那么如果直接在程序中使用Netapi32.lib或Svrapi.lib,在不同的操作系统下运行时会发生找不到xxx函数的输出错误.解决的办法就是通过GetProcAddress动态获取NetShareAdd.正好ccrun在csdn回答一位网友的问题,顺便写了些代码,在这里贴出来.注:  1.以下代码已在Win2kADVServer和Win9x上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comSE中通过测试.编译时不需要包含lm.h或Svrapi.h,如果包含的话,会引起数据类型重名的错误.  2.请使用BorlandC++Builder编译器.如果您用VC,个别参数需要改动代码如下:typedefDWORD(WINAPI*NETSHAREADD2K)(LPWSTR,DWORD,LPBYTE,LPDWORD);  typedefDWORD(WINAPI*NETSHAREADD9X)(constcharFAR*,short,constcharFAR*,unsignedshort);  NETSHAREADD2KNetShareAdd2k;  NETSHAREADD9XNetShareAdd9x;boolbWinNT;//操作系统标志  HINSTANCEhDll;//DLL文件句柄#defineNNLEN80//共享名的长度  #defineLM20_NNLEN12//LM2.0共享名的长度  #defineSHPWLEN8//共享密码的长度  #defineSTYPE_DISKTREE0//磁盘共享  #defineSHI50F_FULL0x0002  #defineNERR_Success0//操作成功#defineNERR_BASE2100  #defineNERR_DuplicateShare(NERR_BASE+18)//共享名称已经存在  #defineNERR_RedirectedPath(NERR_BASE+17)//重定向资源的操作非法  #defineNERR_UnknownDevDir(NERR_BASE+16)//设备或目录不存在typedefstruct_share_info_50//用于Win9x  {  charshi50_netname[LM20_NNLEN+1];//共享名  unsignedcharshi50_type;//  unsignedshortshi50_flags;//  charFAR*shi50_remark;//ANSI备注  charFAR*shi50_path;//共享的资源,也就是共享的目录  charshi50_rw_password[SHPWLEN+1];//可读写的密码  charshi50_ro_password[SHPWLEN+1];//只读密码  }share_info_50;typedefstruct_SHARE_INFO_2//用于Win2k  {  LPWSTRshi2_netname;  DWORDshi2_type;  LPWSTRshi2_remark;  DWORDshi2_permissions;  DWORDshi2_max_uses;  DWORDshi2_current_uses;  LPWSTRshi2_path;  LPWSTRshi2_passwd;  }SHARE_INFO_2,*PSHARE_INFO_2,*LPSHARE_INFO_2;上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com//---------------------------------------------------------------------------  bool__fastcallInitApi()//根据操作系统的不同,从Dll中获取API  {  //判断系统平台  OSVERSIONINFOinfo;  info.dwOSVersionInfoSize=sizeof(info);  GetVersionEx(&info);  bWinNT=(info.dwPlatformId==VER_PLATFORM_WIN32_NT)?true:false;if(bWinNT)  {  hDll=LoadLibrary("Netapi32.dll");//win2k  if(hDll)  {  NetShareAdd2k=(NETSHAREADD2K)GetProcAddress(hDll,"NetShareAdd");  return(NetShareAdd2k!=NULL);  }  else  returnfalse;  }  else  {  hDll=LoadLibrary("Svrapi.dll");//win9x  if(hDll)  {  NetShareAdd9x=(NETSHAREADD9X)GetProcAddress(hDll,"NetShareAdd");  returnNetShareAdd9x!=NULL;  }  else  returnfalse;  }  }  //---------------------------------------------------------------------------  String__fastcallMyPathToNetShare(  StringstrPath,//共享目录  StringstrNetName,//共享名  StringstrPassword,//密码  StringstrRemark)//共享目录的注释  {  if(!InitApi())  return"函数获取错误!";/文档标题:如何在Win9x/2k下建立共享目录  //作者:ccrun(老妖)信箱:info@ccrun.com  //为防止不负责任的转载者遗漏作者信息,故在此插入此信息,请见谅.  //欢迎访问C++Builder研究上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comhttp://www.ccrun.com    if(!bWinNT)//操作系统是win9x  {  charFAR*pszServerName=NULL;  shortnLevel=50;  structshare_info_50*pBuf=NULL;  unsignedshortcbBuffer;  DWORDnStatus;  cbBuffer=sizeof(structshare_info_50);  pBuf=(share_info_50*)malloc(cbBuffer);  if(pBuf==NULL)  return"内存分配失败!";//Assignvaluestotheshare_info_50structure.  strcpy(pBuf->shi50_netname,strNetName.c_str());  pBuf->shi50_type=STYPE_DISKTREE;  pBuf->shi50_flags=SHI50F_FULL;  pBuf->shi50_remark=strRemark.c_str();  pBuf->shi50_path=strPath.c_str();  strcpy(pBuf->shi50_rw_password,strPassword.c_str());//Nopassword  strcpy(pBuf->shi50_ro_password,strPassword.c_str());//Nopassword    //CalltheNetShareAddfunctionspecifyinginformationlevel50.  nStatus=NetShareAdd9x(pszServerName,  nLevel,  (charFAR*)pBuf,  cbBuffer);    //释放分配的内存  if(pBuf!=NULL)  free(pBuf);  //  FreeLibrary(hDll);    if(nStatus==NERR_Success)  return("添加成功!");  else  returnString("有错误发生,返回码:"+String(nStatus));  }  else//操作系统是Win2k  {  HANDLEhToken;  TOKEN_PRIVILEGES上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comtk;    //首先提升本进程的调试级别  OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken);  LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tk.Privileges[0].Luid);  tk.PrivilegeCount=1;  tk.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;  AdjustTokenPrivileges(hToken,FALSE,&tk,0,(PTOKEN_PRIVILEGES)NULL,0);    DWORDnas;  SHARE_INFO_2p;  DWORDdwParamErr=NULL;  p.shi2_path=StringToOleStr(strPath);  p.shi2_remark=StringToOleStr(strRemark);  p.shi2_netname=StringToOleStr(strNetName);  p.shi2_passwd=StringToOleStr(strPassword);  p.shi2_type=STYPE_DISKTREE;//diskdrive  p.shi2_permissions=0;  p.shi2_max_uses=-1;  p.shi2_current_uses=0;  nas=NetShareAdd2k(NULL,2,(LPBYTE)&p,&dwParamErr);    FreeLibrary(hDll);    switch(nas)  {  caseNERR_Success:return"设置成功!";  caseERROR_ACCESS_DENIED:return"拒绝访问!";  caseERROR_INVALID_LEVEL:return"非法的级别!";  caseERROR_INVALID_NAME:return"非法的名称!";  caseERROR_INVALID_PARAMETER:return"参数非法!";  caseNERR_DuplicateShare:return"共享重名!";  caseNERR_RedirectedPath:return"重定向路径!";  caseNERR_UnknownDevDir:return"未知的驱动路径!";  default:return"未知错误!";  }  }  }  //调用举例  //---------------------------------------------------------------------------  void__fastcallTForm1::Button1Click(TObject*Sender)  {  ShowMessage(MyPathToNetShare("C:\\ccrun\\123","MyShare","","共享目录的注释"));  }上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com如何在RichEdit中实现上标下标近来有好多朋友在csdn问如何在RichEdit中实现上标下标,查了好多资料都没找到。今天无意间在Delphi区闲逛,看到一份实现上下标的文章,于是整理成CB语言的贴出来。  以下代码已测试通过。在Form中放置一个RichEdit,两个Button,完整代码如下://---------------------------------------------------------------------------typedefenum{   CFM_Superscript,//上标   CFM_Subscript,  //下标   CFM_Normal      //普通文本}TCharacterFormat;voidMySetCharFormat(TRichEdit*RichEdit,TCharacterFormatCharacterFormat){   //ccrun(老妖)根据Delphi超级猛料中的资料修改而成   //欢迎光临C++Builder研究http://www.ccrun.com   TCharFormatFormat;   Format.cbSize=sizeof(Format);   Format.dwMask=CFM_OFFSET;   //Characteroffset,intwips,fromthebaseline.   //Ifthevalueofthismemberispositive,   //thecharacterisasuperscript;   //ifitisnegative,thecharacterisasubscript.   switch(CharacterFormat)   {       caseCFM_Superscript:           Format.yOffset=60;           break;       caseCFM_Subscript:           Format.yOffset=-60;           break;       caseCFM_Normal:           Format.yOffset=0;           break;       default:           break;   }   //TheEM_SETCHARFORMATmessagesetscharacterformattinginaricheditco上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comntrol.   //SCF_SELECTION:Appliestheformattingtothecurrentselection   RichEdit->Perform(EM_SETCHARFORMAT,SCF_SELECTION,Longint(&Format));}//---------------------------------------------------------------------------//先选中Richedit中的部分文本,然后点击此按钮,选中文本将变成上标void__fastcallTForm1::Button1Click(TObject*Sender){   //上标   MySetCharFormat(RichEdit1,CFM_Superscript);}//---------------------------------------------------------------------------//先选中Richedit中的部分文本,然后点击此按钮,选中文本将变成下标void__fastcallTForm1::Button2Click(TObject*Sender){   //下标   MySetCharFormat(RichEdit1,CFM_Subscript);}如何成为一名优秀的程序员中国的信息技术发展迅速,由它所带来的浪潮已经渗入到了人们生活的每一个角落,而程序员们成为了这场信息化浪潮的见证者之一,更是其中的主要参与者,这是时代赋予每个程序员的机会和责任。信息技术的更新速度是惊人的,程序员的职业生涯则是一个要求不断学习的过程,如何才能成为一名合格的程序员,一名合格的程序员需要掌握哪些技能呢?为此天天招生网  采访到几位孳生的程序工作人员,就如何做好一名成功的程序员谈出了自己的经验。熟练掌握开发工具做为一名程序员至少熟练掌握两到三种开发工具的使用,这是程序员的立身之本,其中C/C和JAVA是重点推荐的开发工具,C/C以其高效率和高度的灵活性成为开发工具中的利器,很多系统级的软件还是用C/C编写。而JAVA的跨平台和与WEB很好的结合是JAVA的优势所在,而JAVA即其相关的技术集JAVAOne很可能会成为未来的主流开发工具之一。其次,能掌握一种简便的可视化开发工具,如VB,PowerBuilder,Delphi,CBuilder,则更好,这些开发工具减小了开发难度,并能够强化程序员对象模型的概念。另外,需要掌握基本的脚本语言,如shell,perl等,至少能读懂这些脚本代码。  熟知数据库上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com为什么数据库是如此重要?作为程序员,他们自然有自己的理由:很多应用程序都是以数据库的数据为中心,而数据库的产品也有不少,其中关系型数据库仍是主流形式,所以程序员至少熟练掌握一两种数据库,对关系型数据库的关键元素要非常清楚,要熟练掌握SQL的基本语法。虽然很多数据库产品提供了可视化的数据库管理工具,但SQL是基础,是通用的数据库操作方法。如果没有机会接触商业数据库系统,可以使用免费的数据库产品是一个不错的选择,如mySQL,Postgres等。  对操作系统有一定的了解当前主流的操作系统是Windows,Linux/Unix,熟练地使用这些操作系统是必须的,但只有这些还远远不够。要想成为一个真正的编程高手,需要深入了解操作系统,了解它的内存管理机制、进程/线程调度、信号、内核对象、系统调用、协议栈实现等。Linux作为开发源码的操作系统,是一个很好的学习平台,Linux几乎具备了所有现代操作系统的特征。虽然Windows系统的内核实现机制的资料较少,但通过互联网还是能获取不少资料。只有对操作系统有一定的了解后,你会发现自己上了一个新的台阶。  懂得网络协议TCP/IP在互联网如此普及的今天,如果您还没有对互联网的支撑协议TCP/IP协议栈有很好的掌握,就需要迅速补上这一课,网络技术已改变了软件运行的模式,从最早的客户/服务器结构,到今天的WEBServices,再到未来的网格计算,这一切都离不开以TCP/IP协议栈为基础的网络协议支持,所以,深入掌握TCP/IP协议是非常必要的。至少,你需要了解ISO七层协议模型,IP/UDP/TCP/HTTP等常用协议的原理和三次握手机制。  明白DCOM/CORBA/XML/WEBServices存在的意义随着技术的发展,软件与网络的无缝结合是必然趋势,软件系统的位置无关性是未来计算模式的重要特征之一,DCOM/CORBA是当前两大主流的分布计算的中间平台,DCOM是微软COM(组件对象模型)的扩展,而CORBA是OMG支持的规范。程序员需要做的不仅仅是利用商业的开发平台来开发软件,而是要理解这些技术的初衷,即为什么需要这项技术,如果你能理解了这一点,再回头看这些技术的具体实现,就如庖丁解牛,迎刃而解。XML/WebServices重要性不言而喻,XML以其结构化的表示方法和超强的表达能力被喻为互联网上的“世界语”,是分布计算的基石之一。  不要将软件工程与CMM分开现代大型软件系统的开发中,工程化的开发控制取代个人英雄主义,成为软件系统成功的保证,一个编程高手并不一定是一个优秀的程序员,一个优秀的程序员是将出色的编程能力和开发技巧同严格的软件工程思想有机结合,编程只是软件生命周期中的其中一环,优秀的程序员应该掌握软件开发各个阶段的基本技能,如市场分析,可行性分析,需求分析,结构设计,详细设计,软件测试等。一句话可以概括我的看法:“创意无限,流程保证”。  拥有强烈的好奇心什么才是一个程序员的终极武器呢,那就是强烈的好奇心和学习精神。没有比强烈的好奇心和学习精神更好的武器了,它是程序员们永攀高峰的源泉和动力所在。  如果您正为如何成为一名合格的程序员而发愁的话,希望以上文字能为您排除一些顾虑和问题。如果您想获得更多有关程序员的信息,那么请随时关注天天招生网,我们将在最短的时间内提供最真实,最准确的相关信息。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com惹恼程序员的十件事程序员是一个比较特殊的群体,他们因为长期和电脑打交道所养成的性格和脾气也是比较相近的。当然,既然是人,当然是会有性格的,也是会有脾气的。下面,让我来看看十件能把程序惹毛了的事情。一方面我们可以看看程序员的共性,另一方面我们也可以看看程序员的缺点。无论怎么样,我都希望他们对你的日常工作都是一种帮助。  第十位程序注释  程序注释本来是一些比较好的习惯,当程序员老手带新手的时候,总是会告诉新手,一定要写程序注释。于是,新手们当然会听从老手的吩咐。只不过,他们可能对程序注释有些误解,于是,我们经常在程序中看到一些如下的注释:  r=n/2;//r是n的一半  //循环,仅当r-n/r不大于t  while((r-n/r)<=t){  ……  r=0.5*(r-n/r);//设置r变量  }  每当看到这样的注释——只注释是什么,而不注释为什么,相信你一定会被惹火,这是谁写的程序注释啊?不找来骂一顿看来是不会解气了。程序注释应该是告诉别人你的意图和想法,而不是告诉别人程序的语法,这是为了程序的易读性和可维护性,这样的为了注释而注释的注释,分明不是在注释,而是在挑衅,惹毛别人当然毋庸置疑。  第九位打断  正当程序沉浸于编程算法的思考,或是灵感突现正在书写程序的时候,但却遭到别人的打断,那是一件非常痛苦的事情,如果被持续打断,那可能会让人一下子就烦躁起来。打断别人的人在这种情况下是非常不礼貌的。被打断的人就像函数调用一下,当其返回时,需要重新恢复断点时的现场,当然,人不是电脑,恢复现场通常是一个很痛苦的过程,极端的情况下可能需要从头开始寻找思绪,然后一点一点地回到断点。  因此,我看到一些程序员在需要安静不被打扰的时候,要么会选择去一个没人找得到的地方,要么会在自己的桌子上方高挂一个条幅以示众人——“本人正执行内核程序,无法中断,请勿骚扰,谢谢!”,可能正在沉浸于工作的程序被打断是多么大的开销。自然,被打断所惹毛了的人也不在少数了。  第八位上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com需求变化  这个事情估计不用多说了。只要是是程序员,面对需求变化的时候可能总是很无奈的。一次两次可能还要吧接受,但也顶不住经常变啊。据说敏捷开发中有一套方法论可以让程序员们享受需求的变化,不知道是真是假。不过,今天让你做一个书桌,没有让你把书桌改成餐桌,后天让你把餐桌改成双人床,大后天让你把床改成小木屋,然后把小木屋再改成高楼大厦。哎,是人都会被惹毛了的。那些人只用30分钟的会议就可以作出任何决定,但后面那几十个程序员需要搭上几百个小时的辛苦工作。如果是我,可能我也需要神兽草泥马帮助解解气了。  不过,这也正说明了,程序员并不懂得怎么和用户沟通,而用户也不懂得和程序员沟通,如果一个项目没有一个中间人(如:PM)在其中协调的话,那么整个项目可能就是“鸡同鸭讲”,用户和程序员都会被对方所惹毛了。如果要例举几个用户被惹毛的事情,估计程序员的那种一根筋的只从技术实现上思考问题的方法应该也能排进前5名。  第七位经理不懂技术  外行领导内行的事例还少吗?领导一句话,无论对不对,都是对的,我们必需照做,那怕是多么愚蠢多么错误的决定,我们也得照做。程序员其实并不怕经理不懂技术,最怕的就是不懂技术的经理装着很懂技术。最可气的是,当你据理力争的挑站领导权威的时候,领导还把你视为异类。哎,想起这样的领导别说是骂人了,打人的冲动都有了。  其实,经理只不过是一个团队的支持者,他应该帮助团队,为团队排忧解难。而不是对团队发号施令。其实管理真的很简单,如果懂的话,就帮着做,如果不懂的话,就相信下属,放手让下属做。最怕的就是又不懂技术,还不信任下属的经理了。哎,这真是程序员的痛啊。  第六位用户文档  用户文档本来不应该那么的令人害怕。这些文档记录了一切和我们所开发的软件有关的一些话题。因为我们并不知道我们所面对的用户的电脑操作基础是什么样的,所以,在写下这样的文档的时候,我们必需假设这个用户什么也不懂。于是,需要用最清楚,最漂亮的语言写下一个最丰富的文档。那怕一个拷贝粘贴的操作,可能我们都要分成五、六步来完成,那怕是一个配置IP地址的操作,我们也要从开始菜单开始一步一步的描述。对于程序员来说,他们在开发过程中几乎天天都在使用自己开发的软件,到最后,可能都有得有点吐了,但还得从最简单的部份写这些文档,当然容易令他们烦燥,让程序员来完成这样的文档可能效果会非常不好。所以,对于这样的用户文档,应该由专门的人来完成和维护。  第五位没有文档  正如上一条所说的,程序员本来就不喜欢写文档,而因为技术人员的表达能力和写作能力一般都不是太好,所以,文档写的也很烂。看看开源社会的文档可能就知道了。但是,我们可爱的程序员另一方面最生气的却是因为没有文档。当然,让面说是的用户的文档,这里我们说的是开发方面的文档,比如设计文档,功能规格,维护文档等等。不过,基本上都是一样的。反正,一方面,我们的程序员不喜欢写文档,另一方面,我们的程序又会被抱怨没有文档,文档太少,或者文档看不懂。呵呵。原来在抱怨方面也有递归啊。据说,敏捷开发可以降低程序开发中的文档,据说他们可以把代码写得跟文档和示图似的,不知道是真是假。不过,我听过太多太多的程序员抱怨没文档太少,文档太差了,这个方面要怪还是怪程序员自己。  第四位上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com部署环境  虽然,程序员们开发的是软件,但是我们并不知道我们的程序会被部署或安装在什么样的环境下,比如,网络上的不同,RAID上的不同,BIOS上的不同,操作系统的不同(WinXP和Win2003),有没有杀毒软件,和其它程序是否兼容,系统中有流氓软件或病毒等等。当然,只要你的软件出现错误,无论是你的程序的问题,还是环境的问题,反正都是你的问题,你都得全部解决。所以,程序员们并不是简单地在编程,很多时候,还要当好一个不错系统管理员。每当最后确认问题的原因是环境问题的时候,可能程序员都是会心生怨气。  第三位问题报告  “我的软件不工作了”,“程序出错了”,每当我们听到这样的问题报告的时候,程序员总是感到很痛苦,因为这样的问题报告等于什么也没有说,但还要程序员去处理这种错误。没有明确的问题描述,没有说明如果重现问题,在感觉上,当然会显得有点被人质问的感觉,甚至,在某些时候还掺杂着看不起,训斥的语气,当然,程序员基本上都是很有个性的,都是软硬不吃的主儿,所以,每当有这样的语气报告问题的时候,他们一般也会把话给顶回去,当然,后面自己然发生一些不愉快的事情。所以,咱们还是需要一个客服部门来帮助我们的程序员和用户做好沟通。  第二位程序员自己  惹毛程序员的可能还是程序员自己,程序员是“相轻”的,他们基本上都是持才傲物的,总是觉得自己才是最牛的,在程序员间,他们几乎每天都要吵架,而且一吵就吵得脸红脖子粗。在他们之间,他们总是被自己惹毛。  技术上的不同见解。比如Linux和Win,VC++和VB,Vi和Emacus,Java和C++,PHP和Ruby等等,等等。什么都要吵。  老手对新手的轻视。总是有一些程序员看不起另一些程序员,说话间都带着一种傲慢和训斥。当新手去问问题的时候,老手们总是爱搭不理。  在技术上不给对方留面子。不知道为什么,程序员总是不给对方留面子,每当听到有人错误理解某个技术的时候,他们总是喜欢当众大声指证,用别人的“错误”来表明自己的“博学”,并证明他人的“无知”。  喜好鄙视。他们喜好鄙视,其实,这个世界上没有一件事是完美的,有好就有不好,要挑毛病太容易了。程序员们特别喜欢鄙视别人,无论是什么的东西,他们总是喜欢看人短而不看人长。经常挂在他们嘴上的口头禅是“太差”、“不行”等等。  程序员,长期和电脑打交道,编写出的代码电脑总是认真的运行,长期养成了程序员们目空一切的性格,却不知,这个世界上很多东西并不是能像电脑一样,只要我们输入正确的指令它就正确地运行这么简单。程序员,什么时候才能变成成熟起来……  第一位上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com程序员的代码  无论你当时觉得自己的设计和写的代码如何的漂亮和经典,过上一段时间后,再回头看看,你必然会觉得自己的愚蠢。当然,当你需要去维护他人的代码的时候,你一定要在一边维护中一边臭骂别人的代码。是否你还记得当初怎么怎么牛气地和别人讨论自己的设计和自己的代码如何如何完美的?可是,用不了两年,一刚从学校毕业的学生在维护你的代码的过程当中就可以对你的代码指指点点,你的颜面完全扫地。呵呵。当然,也有的人始终觉得自己的设计和代码就是最好的,不过这是用一种比较静止的眼光来看问题。编程这个世界变化总是很快的的,很多事情,只有当我们做过,我们才熟悉他,熟悉了后才知道什么是更好的方法,这是循序渐进的。所以,当你对事情越来越熟悉的时候,再回头看自己以前做的设计和代码的时候,必然会觉得自己的肤浅和愚蠢,当然看别人的设计和代码时,可能也会开始骂人了。强制弹出页面+自动最小化广告代码这个弹窗代码,效果很好,不过有点复杂!请细看!  这里涉及三个页面:  弹窗页:1.htm放置弹窗代码的页面  中间页:2.htm中间过度页面  弹出页:3.htm被弹出的页面  在1.htm放入代码如下:主要是通过对话框强制弹出2.htm,大小为0,0    focusid=setTimeout("focus();window.showModelessDialog('2.htm','','scroll:1;status:1;help:1;toolbar=1;resizable:1;dialogWidth:0px;dialogHeight:0px')",3000)    在2.htm里放置代码如下:自动关闭对话框页面2.htm,同时弹窗3.htm      setTimeout('window.close();',0);    在3.htm里放置代码:弹出后自动最小化  在body标签里加入:  以下代码加入区域          上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com浅谈ASP程序实现自动采集程序及入库<%'声明取得目标信息的函数,通过XML组件进行实现。FunctionGetURL(url)SetRetrieval=CreateObject("Microsoft.XMLHTTP")WithRetrieval.Open"GET",url,False.SendGetURL=bytes2bstr(.responsebody)'对取得信息进行验证,如果信息长度小于100则说明截取失败iflen(.responsebody)<100thenresponse.write"获取远程文件"&url&"失败。"response.endendifEndWithSetRetrieval=NothingEndFunction'二进制转字符串,否则会出现乱码的!functionbytes2bstr(vin)strreturn=""fori=1tolenb(vin)thischarcode=ascb(midb(vin,i,1))ifthischarcode<&h80thenstrreturn=strreturn&chr(thischarcode)elsenextcharcode=ascb(midb(vin,i+1,1))strreturn=strreturn&chr(clng(thischarcode)*&h100+cint(nextcharcode))i=i+1endifnextbytes2bstr=strreturnendfunction'声明截取的格式,从Start开始截取,到Last为结束FunctionGetKey(HTML,Start,Last)filearray=split(HTML,Start)filearray2=split(filearray(1),Last)GetKey=filearray2(0)EndFunctionDimSoftid,Url,Html,Title上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com'获取要取页面的IDSoftId=Request("Id")Url="http://www3.skycn.com/soft/"&SoftId&".html"Html=GetURL(Url)'以截取天空软件的软件名为例子Title=GetKey(Html,"","")'打开数据库,准备入库dimconnstr,conn,rs,sqlconnstr="DBQ="+server.mappath("db1.mdb")+";DefaultDir=;DRIVER={MicrosoftAccessDriver(*.mdb)};"setconn=server.createobject("ADODB.CONNECTION")conn.openconnstrsetrs=server.createobject("adodb.recordset")sql="select[列名]from[表名]where[列名]='"&Title&"'"rs.opensql,conn,3,3ifrs.eofandrs.bofthenrs("列名")=Titlers.updatesetrs=nothingendifsetrs=nothingResponse.Write"采集完毕!"%>朴素(Naive)字符串匹配算法代码 作为最原始的字符串匹配算法,它的时间复杂度是O((n-m+1)m)  #include\"stdio.h\"  //计算字符串的长度  intLength(char*s)  {  intcount=0;  while(*s++!=\’\\0\’)  count++;  returncount;  }  //字符串匹配  voidNaiveStringMatching(char*t,char*p)  {  intn=Length(t);  int上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comm=Length(p);  if(n\");  Stringline=in.readLine();  StringBufferbuf=newStringBuffer(line);  for(inti=0;i4millionboardevaluations).AninterestingquoteillustratingthecomputationalintensityofGOgamesonafull19×19boardisthat“thenumberofpossibleGOgamesfarexceedsthenumberofatomsintheuniverse”(moredetailsandderivationhere)InterestingFacts:LowerboundonnumberofpossibleGOgameson19×19boardisabout10^(10^48).Upperboundis10^(10^171).  我们选择蒙特卡罗算法的原因之一是围棋中应用极小极大算法(MinimaxAlgorithm,一种在棋类中常用的选择“最佳”的下一步着法的算法,参考这里)来计算2步或3步之后的着法产生的计算量就非常巨大(在9x9的棋盘上计算4步着法就需要做81^4(大于4百万)次盘面估值)。有一句非常形象的话来形象围棋(19x19)的计算复杂度:远大于宇宙中所有原子的个数(参考这里)。实际上围棋(19x19)的计算下限的10^(10^48),上限是10^(10^171)。  Soanotherwayweusedtoevaluatehow“good”amoveiswastousetheMonteCarlomethod.WhattheMonteCarlomethoddoesinthiscasetoestimatehowgoodorbadacertainmoveisforagivenboardpositionistoplay“virtualgames”illustratingwhatwouldhappeniftwoRandomAIs(AIsplayingcompletelyrandomly)playedoutthosemoves.Thewayitdoesthisistostartfromthisboardpositionandplayeachoftheviablemovesinafixednumberofgameswithallsubsequentmovesbeingcompletelyrandom.Thenafterallofthe”virtualgames”arefinished,wewouldaveragethetotalscoresofeachgameandletitrepresentthe“goodness”oftheoriginalmovewhichspawnedthatgame.Finallybychoosingthemovewiththehighestaveragescore,theMonteCarloAIwouldthenplaythismoveintheactualgameitself,basedontheassumptionthatthemoveswhichscorebetteroveralargenumberofrandomgameswouldbe“better”movesingeneral.上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  因此我们使用蒙特卡罗算法来评估一个着法有多好(差)。蒙特卡罗算法评估某一着法有多好(差)的方法是由两个随机AI(选择的着法完全随机)对一个给定的盘面下若干盘“虚拟棋”。从一个给定的盘面开始,然后对每一可行着法计算指定数量的后续着法完全随机的“虚拟棋”。之后,我们统计所有可行走法的平均值,以反映出“好”的着法。最后是选择有着最高的平均值的着法,蒙特卡罗AI在真正的棋局中应用这一着法。这是基于假设这一高分着法通常比其它的选择产生的结局都要好来做的。  Forourproject,weletourAIplayabout500virtualgamesforeachmove,whichonslowercomputersactuallycantakeawhile,butitisstillfarfasterthantryingtousetheMinimaxAlgorithmtolookaheadjust4moves(justover1millionevaluationscomparedto4million+).Inaddition,theresultsoftheMonteCarloAIareprettygoodasitcangenerallydefeatmostofourotherAIs(MinimaxAIlooking2or3movesaheadandRandomAIs),anditevenputupadecentfightagainstsomebeginnerhumanplayersaswell.  在我们的项目中,我们让AI对每一个着法下500局“虚拟棋”。这也有不小的计算量,如果机器比较“破落”,可能需要计算挺长的一段时间。但它仍然比用极小极大算法向前计算4步(计算量大约是9x9棋盘计算4步(约需评估4百多万个盘面,见前文)的1百万倍)要快得多。蒙特卡罗AI的效果很好,它通常能够打败极大极小算法AI(计算2或3步)和随机AI,这样的棋力跟初学围棋的人类差不多。本文最初发表于赖勇浩(恋花蝶)的博客,http://blog.csdn.net/lanphaday,如蒙转载,敬请保留全文完整,未经许可,不得用以商业用途。  WorthnotingisthatoneveryimportantfactorforhowwelltheMonteCarlomethodworksinthiscaseisthescoringfunctionwhichyouusetodecideaplayer’sscoregivenacertainboardposition.Theoneweusedwhichisverystraightforwardandrelativelysimpleinthatitjustassignsanemptyspottowhoeverhasthecloseststonestothatspot,withtiesbeingbrokenbynumberofstonesnearit.Thisisn’tthemostaccurateoreffectivescoringmethod,butitworkeddecentlywellenoughforourpurposes.  值得注意的是蒙特卡罗算法依赖于一个很重要的因素,那就是对特定盘面的估值函数。我们用了一个简单的函数:把空的点归属于最近的棋子,如果有多个棋子,则平分。它可能不够准确和高效,但对于我们来说,已经足够。  TheAIwedeveloppedusingMonteCarlomethodswasoneofthebetterAIswemade,butitisstillnowherenearthecapabilitiesofadecentlyexperiencedamateurhumanplayer.Especially,theAIstartslosingoutneartheendgamewhentacticsmeanalotmorethanoverallstrategy(whichMonteCarloandMinimaxseemtodowellat).Andthefactthatweareusingrandommovestoplayeach“virtualgame”meansthatwecangetverydifferentresultseachtimeweplayit,especiallyneartheendgamewhereresultsofmovesreallydependonthequalityofsubsequentmoves,whichinthiscasearecompletelyrandom.上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  我们开发的蒙特卡罗算法AI是我们开始的AI中较好的一个,但它与训练有素的棋手仍然相距甚远。尤其在游戏将结束时,战术比策略显得更为重要,AI就容易输棋(蒙特卡罗算法和极小极大算法都有这种问题)。我们使用随机着法来下每一个局“虚拟棋”,所以我们每一次都会得到不同的结果。在将近结局的时候,最后的结果依赖于后续着法的质量,而在这里后续着法是完全随机的,所以效果差强人意。  GOisconsideredbymanytobethemostcomplicatedgameweknowoftodate,anditisveryunlikelythatwewillbeabletocomeevenmarginallyclosetosolvingthegameanytimesoon(wanttoeventrywritingout10^(10^48)?).Butitseemsequallyunlikelythatpeoplewillgiveupontryinganytimesooneither,ashasbeenprovenbyhumantenacityinthefaceofother“insurmountable”oddsinthepast(landingontheMoon…).  围棋被认为是目前为止最复杂的游戏,而且我们不可能在很近的将来解决它。但大家都不会放弃,因为已经证明人类在面对“不可逾越”的问题上是坚忍不拔的(例如登月)。  NOTE:whenIsaid“random”inthispost,Inaturallymeanthepseudorandomnumbergeneratorscomputersuse,whichisn’treallyrandom,butwasmorethancloseenoughforourproject.  注意:本文中的“随机”是指计算机使用的伪随机数,而非真随机,但从项目中来看已经不错了。每一位中国程序员都应该精通英语Cnprog是程序技术问题问答网站Stackoverflow的中文克隆(就像Solidot是技术社区Slashdot的中文克隆),英语是全世界事实上的通用语言,也是软件开发中的标准语言,但是问题是“每一位程序员都应该精通英语吗”?  一位在上海生活了9年的工程师和高管JonHancock认为他们必须掌握,他说,“如果你等待文档所用的语言,工具和库都被翻译到本地语言,那么你将永远是一位边缘程序员。”他以个人经历为例,“无论何时提出技术文档选用何种语言之类问题时候,(中国)官员毫无例外的要求只用英文。他们想让程序员们强迫学习英文。他们理解一个面向全球市场的技术社区所使用的语言肯定是英语。如果语言不统一,那么尝试去传达功能和传达技术要求就变得几乎不可能。在这一点上,英语保留下了选择。但这是对于要求和最终产品而言。如果学习和基本知识交流呢?”在上海举行的BarCamps会议上,所有与会者都是使用英语。但是当中国人使用自己的语言,交流就会更迅速和更深入。作者称虽说世界是平的,但其实并不平坦,保留中文选择也是必要的。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com猫吃老鼠的STL实现方法一、看到猫吃老鼠问题,感觉如果用STL将更加简单。在实现时将问题稍作修改,变成总共n个老鼠,每隔m个吃一个,求最后剩下哪一个,并用STL实现。  二、代码  #include  #include  usingnamespacestd;  inteat(constinttotal,constintspace)  {  if(total<=0||space<=0)  {  return-1;  }  vectorv;  vector::iteratorit;  //初使化向量  for(inti=1;i<=total;++i)  {  v.push_back(i);  }  intj=1;  it=v.begin();  while(v.size()>1)  {  //如果数到第m个,则删除它,并且从头开始数  //迭代器不需要后移,因为删除之后自动就指向下一个元素  if(space==j)  {  v.erase(it);  j=1;  }  else  {  ++it;  ++j;  }  //如果到最后了,让迭代器指向第一个元素  if(it>=v.end())  {  it=上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comv.begin();  }  }  //现在只有一个元素了,那么第一个元素就是我们需要的  return(*v.begin());  }  voidmain(void)  {  inttotal;  intspace;  total=5;  space=1;  cout<<\"总共:\"<sckClosedThen.sckServer.Close  .sckServer.Accept(requestID) EndWithEndSub   下面我们来建立客户端程序:新建一个工程,名为Client,把窗体名为Client,在上面加入一个winsock控件,名为sckClient,协议为TCP/IP协议。再加一个按钮cmdConnect在窗体模块中加入代码:PrivateSubform_Load() WithMe  .sckClient.RemoteHost="127.0.0.1"'设置远程IP,本例设为本机。  .sckClient.RemotePort=88917'远程端口,就为server中的设置一样. EndWithEndSubPrivatesubcmdConnect_Click() SckClient.ConnectEndsub   至此,单击Connect按钮我们的两个工程已经可以进行通信了,但看不见,你可以在Client中的sckClient_Connect事件中加入代码:debug.print“Connetionsuccessful!”来查看。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  这仅是第一步,一点工作也做不了,下面我们来为它们添加功能。为了简单,本文章只实现一点小小的功能―――关机,重启,注销。好,开始吧!  在Server工程中新建一个模块,Name为modApi,这个模快为一些API函数,添加如下API函数:PublicDeclareFunctionExitWindowXXXLib"user32"Alias"ExitWindowXXX"(ByValuFlagsAsLong,ByValdwReservedAsLong)AsLongPublicConstEWX_LOGOFF=0PublicConstEWX_REBOOT=2PublicConstEWX_SHUTDOWN=1PublicDeclareFunctionClipCursorLib"user32"Alias"ClipCursor"(lpRectAsAny)AsLongPublicTypeRECT LeftAsLong TopAsLong RightAsLong BottomAsLongEndType   注:在两个socket中编程中,进行通信的重要事件是DataArrival事件,用于接收远程数据。利用C#实现分布式数据库查询 本文提出了在.Net环境下使用一种新的开发语言C#结合ADO.Net数据访问模型来开发分布式数据库系统,大大简化了开发过程……  随着传统的数据库、计算机网络和数字通信技术的飞速发展,以数据分布存储和分布处理为主要特征的分布式数据库系统的研究和开发越来越受到人们的关注。但由于其开发较为复杂,在一定程度上制约了它的发展。基于此,本文提出了在.Net环境下使用一种新的开发语言C#结合ADO.Net数据访问模型来开发分布式数据库系统,大大简化了开发过程。  1分布式数据库系统就其本质而言,分布式数据库系统的数据在逻辑上是统一的,而在物理上却是分散的。与集中式数据库相比它有如下主要优点:  ·解决组织机构分散而数据需要相互联系的问题。  ·均衡负载。负载在各处理机间分担,可避免临界瓶颈。  ·可靠性高。数据分布在不同场地,且存有多个副本,即使个别场地发生故障,不致引起整个系统的瘫痪。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com·可扩充性好。当需要增加新的相对自主的组织单位时,可在对当前机构影响最小的情况下进行扩充。分布式数据库系统虽然有诸多优点,但它同时也带来了许多新问题。如:数据一致性问题、数据远程传递的实现、通信开销的降低等,这使得分布式数据库系统的开发变得较为复杂。幸运的是,微软的.Net开发环境为我们提供了C#开发语言和ADO.Net数据访问模型,结合两者来开发分布式数据库系统能够大大简化开发工作。  2远程处理框架和ADO.Net  开发分布式数据库系统需要解决的两个重要问题是:各场地间的数据通信以及对数据库的操作及管理。使用C#结合ADO.Net能够高效、可靠地解决这两方面的问题。具体表现为,在C#中通过使用.Net远程处理框架能够方便地解决数据、命令远程传递问题;C#通过ADO.Net对数据库进行操作,使分布式数据库系统中对数据库的各种操作变得高效、可靠,同时易于解决数据一致性问题。  2.1.Net远程处理框架实现数据和命令的远程传递有三种方式。第一种是使用报文或消息的方式,把要传送的数据转化为流格式,再通过套接字编程用报文的形式发送到远程主机。此种方法麻烦,不易实现。第二种是使用WebService,即各远程主机提供一个数据库查询服务的WebService。这种方式只能对单个场地进行查询,无法实现多场地的联合查询。第三种是使用.Net远程处理框架(.NetRemotingFramework)技术,它将远程调用的技术细节隐藏起来,服务程序只需通过简单的设置就可以把本地对象变成为远程提供服务的远程对象,客户端可以像访问本地对象一样透明地访问远程对象,所有的消息、报文等都交给.NetRemoting对象处理,大大简化了开发。远程处理的一般过程如图1所示:首先,服务器端创建一个服务器类的实例,远程处理系统创建一个表示该类的代理对象,并向客户端对象返回一个对该代理的引用。当客户端调用方法时,远程处理基础结构连接检查类型信息,并通过信道将该调用发送到服务器进程。侦听信道获得该请求并将其转发给服务器远程处理系统,服务器远程处理系统查找(或在必要时创建)并调用被请求的对象。然后,此过程将反向进行,服务器远程处理系统将响应捆绑成消息并由服务器信道发送到客户端信道。最后,客户端远程处理系统通过代理将调用的结果返回给客户端对象。  2.2ADO.NetADO.Net以XML为核心,是.Net数据库应用程序的解决方案。它使用离线数据结构,数据源中的数据被缓存到数据集(DataSet)对象中,用户无须锁定数据源,数据以XML格式保存。  2.2.1ADO.Net管理数据一致性在分布式数据库系统中,很可能出现多个用户同时访问和修改数据的情况,因此,对于分布式数据库系统,数据一致性是不可或缺的。ADO.Net通过使用乐观一致性方案来控制数据一致性(实际上DataSet对象被设计成支持使用乐观一致性控制上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com机制),即数据行只有在数据库中真正被更新时才会被锁定,而在悲观一致性方案中,数据行在从被提取出来到在数据库中更新这段时间内一直被锁定。因此,使用ADO.Net能够在更少的时间内响应数量巨大的用户。另外,在分布式数据库系统中,还会经常遇到当用户修改自从提取出来以来已经被修改的行时,违反一致性原则。对此问题ADO.Net也作了很好地解决,即使用DataSet对象为每一条修改过的记录维护两个版本:原始版本和更新版本,在更新的记录被写回数据库之前,先要把数据集中记录的原始版本与数据库中的当前版本进行比较,如果两个版本匹配,就在数据库中更新记录;否则,就会出现违反一致性原则的错误。3实例开发一个家用电器连锁店设有一个总部和许多分店,总部和分店以及各分店之间经常需要进行各种信息的查询(如:商品当日价目表、各店销售状况和库存信息等),对此组织机构建立分布式数据库查询系统,可实现总部和各店信息的共享,便于统一管理。3.1系统设计  3.1.1系统结构图总部和各分店都配置了一台具有固定IP的服务器,其它电脑通过集线器与服务器相连,总部和各分店的服务器通过通信网络联接起来。  3.1.2系统实现步骤系统实现分为三个主要步骤。首先,为总部和各分店设计数据库。由于数据量较大,故采用SQLServer为每个分店创建销售和库存数据库,同时为总部创建员工数据库、整个连锁店的存货数据库、信用卡客户数据库以及供应商信息数据库等。其次,需要建立一个提供数据库服务(DbServer)的动态链接库(dll),将查询时所要用到的一些服务(如:远程对象的发布和获取等)和函数(如:本地异地数据表的查询、数据表的远程创建和删除、表间的连接和合并等)置入该dll中,各分店都需要使用这个dll,以便查询时对一些服务和函数进行调用。最后,根据实际需要开发客户端查询界面。3.2系统实现的关键技术  3.2.1远程对象的发布与获取系统运行后所要做的第一个工作是发布本地的远程对象并获取其它各店所发布的远程对象。发布远程对象时,首先要设置一个网络端口号,然后创建并注册一个通道,最后发布该服务器端的激活对象。其它场地的服务器根据IP地址和网络端口号即可方便地获取所发布的远程对象。实现远程对象发布和获取的关键代码如下:  远程对象的发布:  //创建一个通道实例,port为指定的网络端口号  TcpChannelMyChannel=newTcpChannel(Int32.Parse(port));  //注册通道  ChannelServices.RegisterChannel(MyChannel);  //发布该服务器端激活对象  RemotingConfiguration.RegisterWellKnownServiceType(typeof(DbServer),"STORE",上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comWellKnownObjectMode.Singleton);  远程对象的获取:  //根据IP地址和端口号获取相应的远程对象  try  {myDbServer=(DbServer)Activator.GetObject(typeof(DbServer),"tcp://"+ip+":"+p+"/STORE");}  //捕捉异常  catch(NullReferenceExceptionnullExp)  {MessageBox.Show("指定的url地址不可到达"+nullExp.Message);}  catch(RemotingExceptionremExp)  {MessageBox.Show("指定获得的对象定义不对"+remExp.Message);} 3.2.2数据库的访问  通过ADO.Net访问数据库,可以方便地连接数据库,将数据源中的数据导入DataSet对象中,在DataSet对象中可对数据表进行各种操作,而且DataSet对象本身也可远程传递。这为开发分布式数据库系统带来极大方便。实现数据库访问的关键代码如下所示:   //建立数据库的连接  stringSqlConn="InitialCatalog=Store;DataSource=Localhost;Userid=sa;Password=;";  SqlConnectionConn=newSqlConnection  (SqlConn);  Conn.Open();//打开数据库  //将数据源中的数据导入到数据集对象  try{  DataSetds=newDataSet();  DataTabledt=newDataTable("Result");  SqlDataAdapteradapter=newSqlDataAdapter();  SqlCommandmySqlDataSetCmd=newSqlCommand  (CmdString,Conn);//CmdString为要执行的命令  adapter.SelectCommand=mySqlDataSetCmd;  adapter.Fill(dt);  ds.Tables.Add(dt);}  finally  {Conn.Close();//关闭数据库的连接}  3.2.3查询分布式数据库系统中的查询一般分为三类:本地查询、远程查询和联合查询。本地查询和集中式数据库的查询没什么区别;对于远程查询,只要获取远程对象后,调用查询函数,即可方便地实现;最复杂的是联合查询,涉及到多场地之间数据的查询、表的远程创建、传递、连接、合并等技术。下面以实例介绍联合查询的实现。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com第二连锁店要查询离其较近的第三、第四连锁店中所有北京的供应商所供应的空调的库存信息以便调货,可通过以下步骤实现。首先,获取总部以及第三、第四连锁店所发布的远程对象。接着,通过远程对象在总部创建一临时数据表t1,将查询到的所有北京的供应商信息存放在t1表中(各分店只有供应商名,并不知其所在地,只有总部才有供应商的详细信息),再将t1表保存到第三和第四连锁店。然后让t1表分别与两店的库存表作连接,找出所有北京供应商所供应的空调库存信息(如空调名称、型号、个数、价格等信息),并将连接结果t2和t3数据表返回到第二连锁店。最后对t2和t3两表进行合并,并使用DataGrid控件显示出来。上述实现中,包含了不同场地之间数据表的复制、传递、连接等,所用到的一些函数(如:远程创建数据表、表与表间的远程连接、合并等)都放在dll中,可以方便地调用。  4结束语  利用C#的.NetRemoting技术能够方便地解决各场地间数据的通信问题。另外,C#通过ADO.Net访问数据库,使得对数据库的操作及管理变得更加高效、可靠。这两种技术的使用,有效地解决了开发分布式数据库系统的主要问题,大大减轻了系统开发工作量,并且提高了系统的可靠性和安全性。利用ASP发送和接收XML数据的处理方法因为要做移动梦网WAP的一些接口,所以要用到这种方式,接下来会有ASP.net版本的,这个是ASP版本的,利用了MSXML2.XMLHTTP对像。  request.asp  dimHttps  setHttps=server.createobject("MSXML2.XMLHTTP")  '定义一个XMLHTTP对像  Https.open"POST","http://127.0.0.1/testpost/response.asp",false  Https.send"echo  123456987654  1111122222"  ifHttps.readystate=4then  response.write"提交成功"  'readstate读取状态为4则成功,继续后面的,不成功当然就不用继续处理了  dimobjstream  setobjstream=Server.CreateObject("adodb.stream")  '定义一个stream,因为读过来的直接拿出来是乱码的,所以得处理一下  objstream.Type=1  objstream.Mode=3  objstream.Open  objstream.WriteHttps.responseBody  objstream.Position=0  objstream.Type=2上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  objstream.Charset="GB2312"  html=objstream.ReadText  '转好码,就放到html里,好关闭这些对像  objstream.Close  setobjstream=nothing  sethttps=nothing  endif  response.writehtml  response.asp  '创建DOMDocument对象  Setxml=Server.CreateObject("msxml2.DOMDocument")  xml.async=False  '装载POST数据  xml.LoadRequest  Ifxml.parseError.errorCode<>0Then  response.write"不能正确接收数据"&"Description:"&xml.parseError.reason&"<br>Line:"&xml.parseError.Line  EndIf  setblogchild=xml.getElementsByTagName("misc_command")  'the_text=blogchild.item(0).childnodes(1).text  'the_text=blogchild.item(0).text  'fori=0toblogchild.length-1  response.writethe_text  利用这种方法,ASP里调用Servlet或WebService都是很轻松的!利用ASP+JMAIL进行邮件群发的新思路背景:    Email地址存于MSSql一用户信息表中,数量上万。    公司自有服务器,集SMTP,POP3,WWW,FTP,MSSql,DNS等多种服务于一身。    JMAIL有MailMerge对象,但是免费版不能用  要求:    用ASP+JMAIL,利用公司SMTP向所有用户发送EMAIL  思路:    直接读取数据库,多次循环发送,会对本来配置不高的服务器造成很大压力。最好能对EMAIL分批发送,每批发送间隔一段时间,以此来缓解对服务器造成的压力。  实现:  上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  对EMAIL分批    读出记录到recordset,利用常见的分页程序,将所有记录分页,每页作为一批,有多少页就分多少批    间隔延迟    在每页执行完毕后用来延迟跳转    减少执行时间:    在循环的过程中,循环添加收件人,而不要循环发送,即  fori=1tors.pagesize  msg.AddRecipientrs("Email")  rs.movenext  next  msg.Send("smtp.abc.com")  减小邮件大小  循环添加收件人,会造成一封Email的收件人很多,这样一封Email的就会很大。  所以,在以上代码的基础上改进一下,在循环内做个判断,当收件人Email数量到达  20的时候就发送一次。即:  fori=1tors.pagesize  msg.AddRecipientrs("Email")    ifimod20=0then         ’每20个收信人作为一封Email发送一次     msg.Send("smtp.abc.com")     msg.ClearRecipients        ’清除已发送的收信人    endif  rs.movenext  next  msg.Send("smtp.abc.com")        ’发送余下的  页面  Mail.asp    包含邮件主题、正文的表单,;一个iframe页面,  SendMail.asp  包含后台发送程序,循环,延迟跳转等。  缺点:    发送过程中不能离开该页面    发送的时间较长,与设置的每批发送数量、网络带宽、SMTP服务器性能有关  改进:    可以在Mail.asp中包含多个iframe页面,每个页面从不同的page开始发,相当于多线程发送,对smtp服务器压力会增大,但能缩短发送时间.可考虑在不同的page中采用不同的smtp服务器,例如包含多个iframe页面,在偶数页用smtp.abc.com,在奇数页用smtp.123.com。这样既减轻服务器压力,也达到多线程发送缩短发送时间的目的。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com快速排序算法:Python研究Python中,写一个快速排序练练手:  '''  qsort.py  Quicksort  CreatedonJun18,2009  @author:Liao  '''  fromrandomimportRandom  defquick_sort(arr):  iflen(arr)>1:  qsort(arr,0,len(arr)-1)  defqsort(arr,start,end):  base=arr[start]  pl=start  pr=end  whilepl=base:  pr-=1  ifpl==pr:  break  else:  arr[pl],arr[pr]=arr[pr],arr[pl]  whileplstart:  qsort(arr,start,pl-1)  ifpr+1""Then  后面的回车去掉(这个地方微软写错了)  2.5)配置iis,设置“自定义错误页面”,将500;100的类型设为URL,同时URL设为/500-100.asp  2.6)将500-100.asp另存为utf-8编码将个性化进行到底VB中打造个性进度条VB的第三方控件ccrpProgressBar是一个进度条的控件,可以有多种形态供选择。比起VB中自带的进度条控件ProgressBar更有个性。使用实例:  用ccrpProgressBar制作各式各样的进度条  在VB中自带了一个进度条控件ProgressBar,但功能简单。我向大家推荐一个VB的第三方进度条控件ccrpProgressBar。该控件功能强大,有多种形态供选择,而且只需要简单的设置控件的属性就能实现,非常的好用。下面通过一个例子向大家介绍该控件的用法。  (1)加载控件  启动VisualBasic6.0,创建一个工程并保存为"工程1.vbp",同时产生一个名为"Form1"的窗口。在工具箱的空白处单击鼠标右键,从弹出的快捷菜单中启动"部件"窗口,如图1所示。  点击"浏览"按钮,从存放ccrpProgressBar控件的文件夹中找到ccrpprg.ocx文件。  点击"应用"后ccrpProgressBar控件就添加到工具箱中。如图2。  (2)设计窗体和控件  向窗体中添加9个ccrpProgressBar控件和一个Timer控件。如图3。  Timer控件属性页的设置如图4所示。Interval的值设置为100,与ccrpProgressBar控件的默认值一致。Enabled设置为False。  (3)ccrpProgressBar控件的主要属性  ·Max:最大值。默认100。  ·Min:最小值。默认0。  ·Value:进度条的当前值。  ·Alignment:显示表示进度的文字的位置。分别为vbCenter(中间),vbLeftJustify(左边),vbRightJustify(右边)。  ·Appearance:进度条的3种外观。分别为prgFlat(平面),prg3D(立体)上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comprg3Draised(立体凸起)。  ·BackColor:进度条的背景色。  ·FillColor:进度条的颜色。  ·ForeColor:表示进度文字的字体颜色。  ·Picture:进度条可用图片表示进度,从这里选择需要的图片。  ·Shape:进度条的形状。有prgRectangle(默认),prgEllipse和prgRoundedRect三种。  ·Smooth:是否平滑显示进度。True为平滑显示进度。  ·Vertical:是否垂直显示进度条。True为垂直显示。  ·Style:进度条的风格。当选ChkGraphical时为用图片表示进度。  ·AutoCaption:表示进度的"文字提示"所采用的表现形式。CcrpPercentage为百分比的形式,ccrpValueOfMax为类似1of100的表现形式。Value为数字的表现形式。  (4)本例中ccrpProgressBar控件属性的具体设置  本例中共使用了9个ccrpProgressBar控件,每个ccrpProgressBar控件的具体设置如下:  1.CcrpProgressBar1:保持属性各项不变。  2.CcrpProgressBar2:Appearance的值设置为prg3D(表示用立体外观)。  3.CcrpProgressBar3:Appearance的值设置为prg3Draised(立体凸起),AutoCaption设为ccrpPercentage(百分比的形式表示进度),Alignment设为vbLeftJustify(表示进度的文字靠左)。  4.CcrpProgressBar4:BorderStyle设置为ccrpFixedSingle,AutoCaption设为ccrpPercentage(百分比的形式表示进度),Alignment设置为vbCenter(表示进度的文字在中间)  5.CcrpProgressBar5:Style设置为chkGraphical(用图片来表示进度)。单击"Picture"属性,选择你准备好的图片。同样,AutoCaption也设为百分比的形式表示进度,不过这次Alignment的值设置为vbRightJustify(进度文字靠右)。6.CcrpProgressBar6:Shape设置为prgEllipse(椭圆型),AutoCaption设为ccrpValueOfMax(文字以类似1of100的表现形式)  7.CcrpProgressBar7:Shape设置为prgRoundedRect(圆角矩形),AutoCaption设为ccrpValue(数字形式)。  8.CcrpProgressBar8:Vertical设置为True,表示垂直显示进度条。Smooth设置为True,表示平滑显示进度。  9.CcrpProgressBar9:Vertical属性同8的设置,不过这回给它加上百分比显示,AutoCaption设为ccrpPercentage。  上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com然后再分别调整好9个CcrpProgressBar控件的FillColor和ForeColor属性,搭配好颜色。使界面更协调。  (5)编写代码  设置好控件的属性后,在程序中加入以下代码,完成进度条的功能。DimiAsIntegerPrivateSubForm_Load() Timer1.Enabled=True '2个垂直显示的进度条的位置 WithccrpProgressBar8  .Left=5280  .Top=360  .Height=3800  .Width=396 EndWith WithccrpProgressBar9  .Left=6200  .Top=360  .Height=3800  .Width=396 EndWithEndSubPrivateSubTimer1_Timer() Ifi=100Then  End EndIf ccrpProgressBar1.Value=i ccrpProgressBar2.Value=i ccrpProgressBar3.Value=i ccrpProgressBar4.Value=i ccrpProgressBar5.Value=i ccrpProgressBar6.Value=i ccrpProgressBar7.Value=i ccrpProgressBar8.Value=i ccrpProgressBar9.Value=i i=i+1'变量i自增EndSub   运行程序,运行中的效果如图5所示。将SSH与PHP相连接确保传输数据的安全上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comSSH可以通过将联机的封包加密的技术进行资料的传递;使用SSH可以把传输的所有数据进行加密,即使有人截获到数据也无法得到有用的信息。同时数据经过压缩,大大地加快了传输的速度。总之,通过SSH的使用,可以确保资料传输比较安全并且传输效率较高。不过,并非所有人知道PHP可以与SSH连接的特性以及与执行远程命令的能力,不过这方面却非常有用。由于我们可以在很多不同的方面利用PHP,因此它有很多设置选项来控制其行为。一组庞大的可选参数能够保证您可以将PHP用于许多不同的目的,但这同时也意味着这些参数和服务端配置的组合会带来一些安全问题。笔者一直在PHPCLI应用程序中使用SSH,笔者是从cronjobs中使用它的,不过一开始并非十分简单,可以说颇费周折。关于安全使用Shell2函数的手册也不是十分实用,笔者进行了多次试验之后才有了今天这篇小文章,愿您读了之后能为您配置PHP节省一点儿时间。  在这篇文章中,笔者需要假设:  你正在运行的操作系统是Debian/Ubuntu。如果你运行的不是Debian/Ubuntu,你可能需要用你的Linux发行版本提供的数据包管理器来替换本文对应内容。  你运行的是PHP5.如果你运行的不是PHP5,可用PHP4代替之。  你对PHP和服务器管理有基本的了解。  你已经安装了PHP。  先决条件  安装程序包  首先,让我们安装下面的程序包:  sudoaptitudeupdate  sudoaptitudeinstallphp5-devphp5-cliphp-pearbuid-essential\  openssl-devzlib1g-dev  安装完成进入下一步。  编译libssh2  在从sourceforge网站下载了Libssh2之后,我们需要编译它,不过不要担心,你只需要按照如下的方法操作:  cd/usr/src  wgethttp://surfnet.dl.sourceforge.net/sourceforge/libssh2/libssh2-0.14.tar.gz  tar-zxvflibssh2-0.14.tar.gz  cdlibssh2-0.14/  ./configure  makeallinstall  如果你想检查是否有了一个新版本,可以查看SF.NET.不过,0.14这个版本就足够了。  安装  安装ssh2.so  下一步,我们需要将libssh和PHPr链接起来。有一个PECL模块可以完成这个功能。我们可以使用PEAR安装它。  pearinstall-fssh2  -f参数确保SSH2被安装,即使并没有一个稳定的选择对象。你还可以使用如下的包名称:ssh2-beta来强行运行。  现在你需要确保我们这个新的SSH2.SO模块被PHP加载。编辑你的php.ini文件(对于CLI实用程序:/etc/php5/cli/php.ini,对于Apache实用程序:/etc/php5/apache2/php.ini)上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  extension=ssh2.so  这应该放在“DynamicExtensions”的下面,大约在第515行左右。  PHP支持SSH编写代码  你刚刚在PHP中启用了SSH2。那么现在应该如何利用它呢?有两个选择。SSH支持:  1.执行方法:  这告诉你的服务器的操作系统来执行什么东西,并且通过管道传回到你的脚本。  2.外壳方法:这种方法在操作系统中打开一个实际的外壳,这正像通过终端应用程序登录时所操作的那样。有一些路由器并没有一个完全的POSIX一致性实施过程,而是在你登录时立即运行其自身的应用程序。这时你就需要这种方法。  下面我们分别详述之:  第一种方法:执行  你最好为下面的代码创建函数或者是一个类,不过本文仅仅起到一个为您提供基本观念的作用,所以说你可以如此开始:  if(!function_exists("ssh2_connect"))die("functionssh2_connectdoesn'texist")  //loginatserver1.example.comonport22  if(!($con=ssh2_connect("server1.example.com",22))){  echo"fail:unabletoestablishconnection\n";  }else{  //trytoauthenticatewithusernameroot,passwordsecretpassword  if(!ssh2_auth_password($con,"root","secretpassword")){  echo"fail:unabletoauthenticate\n";  }else{  //allright,we'rein!  echo"okay:loggedin...\n";  //executeacommand  if(!($stream=ssh2_exec($con,"ls-al"))){  echo"fail:unabletoexecutecommand\n";  }else{  //collectreturningdatafromcommand  stream_set_blocking($stream,true);  $data="";  while($buf=fread($stream,4096)){  $data.=$buf;  }  fclose($stream);  }  }上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com第二种方法:外壳  同样道理,你也可以为如下的代码编写函数或者一个类。不过,本文仅仅提供基本观念:  if(!function_exists("ssh2_connect"))die("functionssh2_connectdoesn'texist")  //loginatserver1.example.comonport22  if(!($con=ssh2_connect("server1.example.com",22))){  echo"fail:unabletoestablishconnection\n";  }else{  //trytoauthenticatewithusernameroot,passwordsecretpassword  if(!ssh2_auth_password($con,"root","secretpassword")){  echo"fail:unabletoauthenticate\n";  }else{  //allright,we'rein!  echo"okay:loggedin...\n";  //createashell  if(!($shell=ssh2_shell($con,'vt102',null,80,40,SSH2_TERM_UNIT_CHARS))){  echo"fail:unabletoestablishshell\n";  }else{  stream_set_blocking($shell,true);  //sendacommand  fwrite($shell,"ls-al\n");  sleep(1);  //&collectreturningdata  $data="";  while($buf=fread($shell,,4096)){  $data.=$buf;  }  fclose($shell);  }  }  }  小提示:有时服务器忙碌,或者一个连接出错,缓冲区没有数据,PHP脚本就会停止从一个命令输出(即使命令并没有完成!)中收集数据。你可以为此进行如下的操作:  ssh2_exec($con,'ls-al;echo"__COMMAND_FINISHED__"');  现在,在你不断地检查缓冲区的循环中,只需要看一下COMMAND_FINISHED。因为你就可以知道你拥有了所有的数据。为了避免无限循环(死循环),可以用一个10秒的超时限制:  $time_start=time();  $data="";  while(true){  $data.=fread($stream,4096);上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  if(strpos($data,"__COMMAND_FINISHED__")!==false){  echo"okay:commandfinished\n";  break;  }  if((time()-$time_start)>10){  echo"fail:timeoutof10secondshasbeenreached\n";  break;  }  }  在上面的例子中,你最好将stream_set_blocking设为false。  通过SSH发送文件  ssh2_scp_send($con,"/tmp/source.dat","/tmp/dest.dat",0644);  如果不能正常工作  请检查如下的几个方面:  依照本文检查你操作的每一步  在服务器端,在sshd_config中必须启用“PasswordAuthenticationyes”。在大多数服务器上默认值是yes,不过有些情况下,你可能需要将下面的一行加入到文件中,即亲自动手打开这个功能:  /etc/ssh/sshd_config:  #Changetoyestoenabletunnelledcleartextpasswords  PasswordAuthenticationyes  如果作了改变,就需要重新启动SSH:  /etc/init.d/sshrestart将Java应用注册为后台服务上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com项目中有一个java应用程序,交付后用户要求要把这个程序做成后台服务程序,即:系统启动后该程序可以自动启动,并且在前台不要出现运行窗口,维护人员只要在“服务管理”(Windows)中选择启动或停止即可.解决办法如下:Linux在Linux中注册后台服务程序相对容易,只需编辑/etc/init.d/boot.local文件,在boot.local文件里加上下面这句脚本:/iapappserver/MessageServer2.1/run.sh其中run.sh是java应用的运行脚本Windows在Windows下的情况较为复杂,需要使用Windows提供的两个工具:instsrv.exe(下载)和Srvany.exe(下载).instsrv: 这个工具是把win32程序变成系统服务。基本用法: instsrv [服务名] [应用程序绝对路径] (增加服务)instsrv [服务名] REMOVE  (删除服务)但是并不是所有程序都适合做系统服务的,注册成系统服务后就是无法启动的,这时就需要用到srvany.srvany: 这个工具就是用来解决上面的工具中的问题,你注册的时候把它当作你要的服务,在用它来启动你的应用程序。基本用法: instsrv [服务名] [srvany的绝对路径]具体步骤如下:1.注册服务: path\instsrv 服务名 path\srvany.exe2.regedit打开注册表3.进入HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\服务名4.右键-新建-项 填入 Parameters5.打开Parameters,右键-新建-字符串值 Application6.双击Application 填入 应用程序的绝对路径,如: D:\workspace\app\main.exe7.右键-新建-字符串值AppDirectory 8.双击AppDirectory 填入 应用程序的工作目录,如: D:\workspace\app\9.启动服务。在Parameters里还可以添加很多键值:  AppDirectory 工作目录  AppParameters 你的应用程序的参数。  AppEnvironment 运行环境变量。建一个XMLHttpRequest对象池 在ajax应用中,通常一个页面要同时发送多个请求,如果只有一个XMLHttpRequest对象,前面的请求还未完成,后面的就会把前面的覆盖掉,如果每次都创建一个新的XMLHttpRequest对象,也会造成浪费。解决的办法就是创建一个XMLHttpRequset的对象池,如果池里有空闲的对象,则使用此对象,否则将创建一个新的对象。  下面是我最近写的一个简单的类:/** * XMLHttpRequest Object Pool *上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com * @author    legend  * @link      http://www.ugia.cn/?p=85 * @Copyright www.ugia.cn */     var XMLHttp = {    _objPool: [],        _getInstance: function ()    {        for (var i = 0; i < this._objPool.length; i ++)        {            if (this._objPool[i].readyState == 0 || this._objPool[i].readyState == 4)            {                return this._objPool[i];            }        }            // IE5中不支持push方法        this._objPool[this._objPool.length] = this._createObj();            return this._objPool[this._objPool.length - 1];    },        _createObj: function ()    {        if (window.XMLHttpRequest)        {            var objXMLHttp = new XMLHttpRequest();            }        else        {            var MSXML = [’MSXML2.XMLHTTP.5.0’, ’MSXML2.XMLHTTP.4.0’, ’MSXML2.XMLHTTP.3.0’, ’MSXML2.XMLHTTP’, ’Microsoft.XMLHTTP’];            for(var n = 0; n < MSXML.length; n ++)            {                try                {                    var objXMLHttp = new ActiveXObject(MSXML[n]);                    break;                }                catch(e)上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com                {                }            }         }                      // mozilla某些版本没有readyState属性        if (objXMLHttp.readyState == null)        {            objXMLHttp.readyState = 0;                objXMLHttp.addEventListener("load", function ()                {                    objXMLHttp.readyState = 4;                        if (typeof objXMLHttp.onreadystatechange == "function")                    {                        objXMLHttp.onreadystatechange();                    }                },  false);        }            return objXMLHttp;    },  // 发送请求(方法[post,get], 地址, 数据, 回调函数)    sendReq: function (method, url, data, callback)    {        var objXMLHttp = this._getInstance();            with(objXMLHttp)        {            try            {                // 加随机数防止缓存                if (url.indexOf("?") > 0)                {                    url += "&randnum=" + Math.random();                }                else                {                    url += "?randnum=" + Math.random();                }                    open(method, url, true);上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com                    // 设定请求编码方式                setRequestHeader(’Content-Type’, ’application/x-www-form-urlencoded; charset=UTF-8’);                send(data);                onreadystatechange = function ()                {                    if (objXMLHttp.readyState == 4 && (objXMLHttp.status == 200 || objXMLHttp.status == 304))                    {                        callback(objXMLHttp);                    }                }            }            catch(e)            {                alert(e);            }        }    }};  示例: function test(obj){    alert(obj.statusText);}    XMLHttp.sendReq(’GET’, ’http://www.ugia.cn/wp-data/test.htm’, ’’, test);XMLHttp.sendReq(’GET’, ’http://www.ugia.cn/wp-data/test.htm’, ’’, test);XMLHttp.sendReq(’GET’, ’http://www.ugia.cn/wp-data/test.htm’, ’’, test);XMLHttp.sendReq(’GET’, ’http://www.ugia.cn/wp-data/test.htm’, ’’, test);    alert(’Pool length:’ + XMLHttp._objPool.length); 建立数据仓库:入门的八个诀窍 当使用SQL上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comServer技术建立一个数据仓库时,你可能会面临一些挑战。我将给你一些建议来克服它们。当然,每个环境可能会给建立数据仓库所面临的挑战增添自己的难度,但是这些建议大多数都是通用的,足以应用于许多公司着手构建商业智能(BI)应用。  1.管理部门的支持。这是你必须要克服的第一个,也是最重要的挑战。它困扰着技术人员(当然包括你),因为它涉及政治而不是软件。但是让我们记住是谁签发你的薪水。如果管理部门不相信他们需要一个数据仓库,那你的所有技能都是无用的。  不幸的是上层管理人员至今仍经常认为数据仓库是另一个系统,他们需要投资却不能立即获得回报。你的工作就是使他们确信他们不会是在购买一些无用的东西——数据仓库会通过使企业中分散的数据关联起来,从而帮助他们做出更好、更明智的决定。在采用了数据仓库之后组织运行方式完全改变是并不罕见的。有时它会帮助建立一个概念证明模型(POC)项目来证明商业智能的力量。POC数据仓库将只包含所有数据的一小部分,并将只显示给一小部分人,以便测试。即使你并没有获准采用POC,你也应该证明数据仓库的某些部分将有益于你的用户,这么做使他们有兴趣并确信这个系统将帮助他们使他们的工作更有效。  2.数据可用性。数据仓库将不一定明显或不一定容易获得的多个数据源的数据结合起来。根据公司的规模不同,你可能需要到多个办公室和许多雇员谈话来弄清楚你可以从哪获得那些用于生成你的用户想要的分析视图的必要的数据。再次,根据你的公司的政治氛围的不同,你可能发现要获得所有的必要数据元素很困难。因为你用的数据可能包含机密和高敏感性的细节。此外,一些数据可能只能通过一个外部实体所提供的报告访问,而他不会给你他们的数据源的访问权限。  你怎么克服这个挑战?首先,一定要说服每个人你不会取代他们的工作。数据仓库是用来补充的而不是取代任何已存在的系统。如果有管理层站在你这边,你就不会有太多内部员工的问题。但是如果你不能访问数据源——因为不可预见的原因——那么你可能就需要用创造性来解决这一问题了。如果数据只能通过报告屏幕或纸上来获得,那么你可能需要找到个方法来捕获这个数据,可能通过抓取报告屏幕或扫描文档。  3.数据源的复杂性。有时你很幸运,你需要的所有的数据元素都在你选择的数据库管理系统(DBMS)中。更多时候,数据是分散在多个数据库管理系统中的,电子表格、电子邮件系统、电子文档,甚至纸张上。是的,我们是在21世纪,但是记住我的话——还是有一些其它的公司是把某些数据只保存在纸上的。这是你的工作,找出怎样从分散的数据源获得数据并转化为共同的形式,然后录入到你的数据仓库中去的方法。  4.数据质量。许多交易处理应用通常是由对其使用的工具具有有限的知识或经验的人利用快速发展的技术放到一起的。这并没有贬低的意思;一个人必然要从某一处开始,而初级程序员是公司可以使用的最实惠的资源。麻烦的是如果这个应用没有验证数据那你很可能发现字符串类型的数据是缩写的、拼错了或完全遗漏了。对于交易级别的报告,这可能不是什么大问题,但是当你试图给数据分组并提供给你的用户作做决定的能力时,数据质量就是至关重要的了。  例如,看一下下面的用户姓名:  a.ACMEBootOutlet  b.ACMEbt上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comoutlt  c.A.C.M.E  d.Boots(ACME)  e.Acmebootstore(outlet)  人眼可以很容易的辨识出上面的每一个都是指同一个事务实体。但是对于计算机程序来说,每一个值代表一个不同的用户。不幸的是利用集成服务(或者数据转移服务)包没有容易的方法来校正所有的不好的数据。SQLServer2005集成服务提供了模糊查询转化,它可以大大简化你的数据清理工作。但即使如此,你可能还是需要文职人员帮忙修正数据。  5.你的用户数目和技术领悟力。帮助一些用户获得他们所需的数据以便作出决策并不是一件容易的事。过去,数据仓库是给高层管理人员使用的。但是慢慢的,数据仓库转向了大多数人群。看到不一定做决策的用户使用数据仓库和商业智能应用是很平常的。  一旦你的用户看到了数据仓库的强大力量,他们将会想从数据访问到获取交易级报告等任何事情都使用数据仓库。你的用户群越大,保证每个人都满意并培训他们恰当使用你的应用程序就越困难。如果使用恰当,商业智能应用可以发挥很大的作用,但它并不是适合所有的商业需求。你经常得传送不好的消息,那就是数据仓库并不是满足你的用户期望的功能的可选工具。  6.维度慢慢改变。你的应用必须反映出移植到仓库中的数据源所发生的数据变化。维表中的数据特别容易变化。但你怎么维护记录的历史变化呢?  第一个也是最简单的方法是重写现有的记录而不跟踪变动。幸运的是,这个方法被许多维度所接受。例如,如果一个部门名称从“财务”变为“财务和会计”,你很可能并不需要记录这种历史变化。但是,从客户和学生的角度看,常常有必要保持跟踪姓名、婚姻状态、教育程度和其它属性的变化——你的应用必要能够获得当前的以及历史的数值。  管理维度慢慢改变的第二个方法是数值发生变化时创建一个新的记录,并将旧的记录标记为旧记录。  第三个也是最后的一个方法是维护在维表的同一行中不同列的变化域的历史数值。  到此,我们已经介绍了如何处理数据仓库维度中的值的变化。但是分析服务维度怎么处理呢?要反映属性值的变化你必须重新处理维度。但是如果你完全处理维度,你就不得不也重新处理多维数据集,如果你的多维数据集包含大量数据,那这就可能不太现实了。幸运的是你可以经常使用渐进式更新(过程更新)选项来避免重新处理多维数据集。  7.事实变化。通常人们认为事实表中的记录是静态的——一旦这条记录录入到了仓库中你的工作就结束了,是吗?不幸的是这个回答是“它取决于。”在某些情况下像在一个数据仓库跟踪病人的住院情况,所有的记录通常都是静态的。如果你从1月1日到2月5日住院,那这条记录不太可能改变。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  但是考虑到零售行业,所有的销售都不是最终的——我肯定你知道有些人经常将它们购买的货物因为各种原因而退回商店。一些公司管理这种交易为一系列信用和负债来结算每笔交易。但在其它的情况下你必须更新或删除事实表记录,甚至在它们添加到了数据仓库之后。例如,如果一个股票交易记录不正确,用一个相反的交易来结算是不能接受的。还有另一个问题要考虑:你可能不希望你的客户知道你的交易系统中存在的问题。甚至你希望他们只在数据被修正后才看到数据。  处理事实变化的一个方法是将数据放在暂存区域直到它经过了质量检查,然后将其移植到仓库中。然而有时甚至是最全面的测试也无法捕获数据源中的所有错误,你可能需要通过处理这些包含错误数据的部分来更新多维数据集。这就是为什么有必要保持你的分析服务部分尽可能的小以便处理可以相对快一些。  另一个处理这个挑战的方法是采用一个回写分区。采用多维数据集回写,你没有真的改变关系数据仓库中的数据;而是在一个单独的分区中添加了一条记录。当用户查询一个特殊的测量值组时,分析服务将只读分区的数据和回写分区的数据结合起来,然后显示结果。当然,执行这样的查询计算会额外增加分析服务器的执行时间,并会造成性能下降。  8.实现安全。就像任何其它的商业应用一样,必须保护对你的数据仓库和多维数据集的访问。每个用户可能只被允许看到数据仓库的一小部分,这取决于他们的工作职务或责任范围。分析服务通过可以与分析服务角色相关联的Windows帐户来保证安全。你可以以非常小的粒度级以单个多维数据集单元为单位来实行数据保护。  不幸的是为每一个用户创建一个单独的角色不仅麻烦而且还会引起性能问题——尤其对于分析服务2005之前的版本。建议如果可能的话你把你的用户分为较少的几种角色。如果每一个单独的用户需要有她自己的权限设置,那么你需要实现一个安全维度。一旦你有了这样的安全维度,每一个MDX查询都将根据目前的用户身份进行输出过滤。  当然我无法在一篇文章里介绍所有的数据仓库问题。也没有任何人可以说他熟悉建立数据仓库解决方案所遇到的每一个问题。但是,如果你打算尝试实现这样的解决方案,你应该谨慎的考虑你将要面临的是什么。做好准备工作,准备迎接挑战。简单快捷实现ASP在线发邮件功能在编写网上应用程序时,经常碰到需要在线发送邮件的问题,邮件内容是由程序动态决定的,如果你采用的是ASP方式来编写网上应用程序,如何简单、快捷地实现这一功能呢?笔者在实践中利用ASP的com组件功能,在vb中实现了一个发邮件的小组件,在ASP中只通过轻松调用,就可以实现该功能。所有邮件处理机制都被封装在这个组件中,使用起来极为方便。下面将详细介绍该组件的基本开发原理以及在ASP中的应用。  1.利用Winsock控件与发送邮件的smtp联系  和smtp的联系包括握手、发送数据以及关闭等全过程,主要程序如下:  建立一个frmsendmail的窗体,其中包含一个winsock控件,有以下几个公共变量:  publicmstmpasstring  //发送邮件的stmp上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  publicmfromasstring  //from地址  publicmtoasstring  //到达地址  publicmsubjectasstring  //邮件主题  publicmtextasstring  //邮件正文  sock.connectmstmp,25  //和发送邮件的stmp建立联系  privatesubsock_connect()  sflag=sfconn  //连接成功后设置参数  endsub  privatesubsock_dataarrival(byvalbytestotalaslong)  onerrorgotodaerr  dimsasstring  sock.getdatas  selectcasesflag  casesfstart  casesfconn  sflag=sfhelo  //发出握手信息hello  send"helo"&&mmyname  casesfhelo  sflag=sffrom  send"mailfrom:"&&getreal(mfrom)  casesffrom  ifleft(s,3)〈〉"250"thengotosrverr  //如果成功发送接收邮件地址sflag=sfrcpt  send"rcptto:"&&getreal(mto)  casesfrcpt  ifleft(s,3)〈〉"250"thengotosrverr  //如果成功开始发送数据  sflag=sfdata  send"data"  casesfdata  ifleft(s,3)〈〉"354"thengotosrverr  sflag=sfsendover//数据包括4项,最后以.结束  send"from:"&&mfrom  send"to:"&&mto  send"subject:"&&msubject&&vbcrlf上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  sendmtext  send"."  casesfsendover  ifleft(s,3)〈〉"250"thengotosrverr  sflag=sfstart  sendok=true  send"quit"  endselect  exitsubendsub  2.将上述功能封装在一个类中  由于ASP能使用的组件中不能存在控件,所以要通过类模块来封装上述窗体。首先在类初始化时建立一窗体:  privatesubclass_initialize()  setfrm=newfrmsendmail  endsub  把窗体的公共变量作为属性封装在类模块中。  该窗体的函数接口为:  publicsubsend()  frm.sendstart  endsub  3.注册该组件  将上述工程编译成dll文件,通过vb注册或手工注册都可以。  4.在ASP中的应用  调用方法如下:  setsmail=server.createobject("sendmailx.mail")  smail.stmp="166.166.1.1"  smail.logfile="e:\logs\mail.log"  smail.mfrom=mfromname&&"〈"&&mfromaddr&&"〉"  smail.mto=mtoname&&"〈"&&mtoaddr&&"〉"  smail.msubject=msubject  smail.mtext=mtext  smail.send  其中变量可以通过赋值,也可以来自上一个request页面。缓冲技术提高JSP程序的性能和稳定性一、概述上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com在Web应用中,有些报表的生成可能需要数据库花很长时间才能计算出来;有的网站提供天气信息,它需要访问远程服务器进行SOAP调用才能得到温度信息。所有这一切都属于复杂信息的例子。在Web页面中加入过多的复杂信息可能导致Web服务器、数据库服务器负荷过重。JSP代码块缓冲为开发者带来了随意地增加各种复杂信息的自由。JSP能够在标记库内封装和运行复杂的Java代码,它使得JSP页面文件更容易维护,使得非专业开发人员使用JSP页面文件更加方便。现在已经有许多标记库,它们或者是商业产品,或者是源代码开放产品。但这些产品中的大多数都只是用标记库的形式实现原本可以用一个简单的JavaScriptlet实现的功能,很少有产品以某种创造性的方式使用定制标记,提供在出现JSP定制标记库之前几乎不可能实现的用法。OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,提供了在现有JSP页面之内实现快速内存缓冲的功能。虽然已经有一些供应商在提供各种形式的缓存产品,但是,它们都属于面向特定供应商的产品。OSCache能够在任何JSP1.1兼容的服务器上运行,它不仅能够为所有用户缓冲现有JSP代码块,而且能够以用户为单位进行缓冲。OSCache还包含一些提高可伸缩性的高级特性,比如:缓冲到磁盘,可编程的缓冲刷新,异常控制,等等。另外,正如OpenSymphony的其他产品,OSCache的代码也在一个开放源代码许可协议之下免费发行。本文以一个假想的拍卖网站设计过程为例,介绍OSCache的工作过程。这个假想的Web网站将包含:一个报告最近拍卖活动的管理页面;一个功能完整、带有各种宣传信息的主页;一个特殊的导航条,它包含了用户所有尚未成交的拍卖活动信息。  二、管理页面拍卖网站包含一个管理报表,数据库服务器需要数秒时间才能创建这样一个报表。报表生成时间长这一点很重要,因为我们可能让多个管理员监视系统运行情况,同时又想避免管理员每次访问时都重新生成这个报表。为了实现这一点,我们将把整个页面封装到一个应用级的缓冲标记之内,这个缓冲标记每隔1小时刷新。其他供应商提供的一些产品也具有类似的功能,只是OSCache比它们做得更好。为简单计,我们将不过多地关注格式问题。在编写管理页面时,我们首先把标记库声明加入到页面:<%@tagliburi="cachetags"prefix="cache"%>  接下来我们要用cache标记来包围整个页面。cache标记的默认缓冲时间是1小时。<cache:cache>....复杂的管理报表....</cache:cache>  现在管理页面已经被缓冲。如果管理员在页面生成后的一个小时之内再次访问同一页面,他看到的将是以前缓存的页面,不需要由数据库服务器再次生成这个报表。  三、主页上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com拍卖网站的主页显示网站活动情况,宣传那些即将结束的拍卖活动。我们希望显示出正在进行的拍卖活动数量,当前登录用户数量,在短期内就要结束的拍卖活动的清单,以及当前时间。这些信息有着不同的时间精确度要求。网站上的拍卖活动通常持续数天,因此我们可以把缓冲有效拍卖活动数量的时间定为6个小时。用户数量的变化显然要频繁一些,但这里我们将把这个数值每次缓冲15分钟。最后,我们希望页面中显示的当前时间总是精确的页面访问时间。  在主页中声明标记库之后,我们首先以不带缓冲的方式直接输出当前日期:  现在是:<%=newjava.util.Date()%>  接下来,我们要显示一个清单,列出那些将在短期内结束的拍卖活动:<cache:cache><ul><%//构造一个包含最近拍卖活动的IteratorIteratorauctions=....while(auctions.hasMore()){Auctionauction=(Auction)auctions.next();%><li><%=auction%></li%<}%></ul></cache:cache>最后,我们希望显示出正在进行的拍卖活动的数量,这个数字需要缓冲6小时。由于cache标记需要的是缓冲数据的秒数,我们把6小时转换成21600秒:<cache:cachetime="21600"><%//查询数据库得到拍卖活动总数intauctionCount=....%>本网站正在进行的拍卖活动有<%=auctionCount%>个!</cache>  可以看到,我们只用少量的代码就构造出了一个带有复杂缓冲系统的主页。这个缓冲系统对页面各个部分分别进行缓冲,而且各个部分的缓冲时间完全符合它们各自的信息变化频繁程度。由于有了缓冲,现在我们可以在主页中放入更多的内容;而在以前没有缓冲的情况下,主页中放入过多的内容会导致页面访问速度变慢,甚至可能给数据库服务器带来过重的负载。  四、导航条假设在规划网站的时候,我们决定在左边导航条的下方显示购物车内容。我们将显示出用户所拍卖的每一种商品的出价次数和当前报价,以及所有那些当前用户出价最高的商品的清单。我们利用会话级的缓冲能力在导航条中构造上述功能。把下面的代码放入模板或者包含文件,以便网站中的其他页面引用这个导航条:<cache:cachekey="navbar"scope="session"time="300"><%//提取并显示当前的出价信息%></cache:cache>在这里我们引入了两个重要的属性,即key和scope。在本文前面的代码中,由于cache标记能够自动为代码块创建唯一的key,所以我们不需要手工设置这个key属性。但在这里,我们想要从网站的其余部分引用这个被缓冲的代码块,因此我们显式定义了该cache标记的key属性。第二,scope属性用来告诉cache标记当前代码块必须以用户为单位缓冲,而不是为所有用户缓冲一次。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com在使用会话级缓冲时应该非常小心,应该清楚:虽然我们可以让复杂的导航条减少5倍或10倍的服务器负载,但它将极大地增加每个会话所需要的内存空间。在CPU能力方面增加可能的并发用户数量无疑很理想,但是,一旦在内存支持能力方面让并发用户数量降低到了CPU的限制之下,这个方案就不再理想。正如本文前面所提到的,我们希望从网站的其余部分引用这个缓冲的代码块。这是因为,当一个用户增加了一个供拍卖的商品、或者出价竞购其他用户拍卖的商品时,我们希望刷新缓冲,使得导航条下一次被读取时具有最新的内容。虽然这些数据可能因为其他用户的活动而改变,但如果用户在网站上执行某个动作之后看到自己的清单仍未改变,他可能会感到非常困惑。OSCache库提供的flush标记能够刷新缓冲内容。我们可以把下面的代码加入到处理用户动作且可能影响这一区域的页面之中:<cache:flushkey="navbar"scope="session"/>当用户下次访问它时,navbar缓冲块将被刷新。至此为止,我们这个示例网站的构造工作已经完成且可以开始运行。下面我们来看看OSCache的异常处理能力。即使缓冲的内容已经作废,比如在缓冲块内出现了Java异常,OSCache标记库仍旧允许我们用编程的方法显示这些内容。有了这种异常控制功能,我们可以拆除数据库服务器和Web服务器之间的连接,而网站仍能够继续运行。JSP1.2规范引入了TryCatchFinally接口,这个接口允许标记本身检测和处理Java异常。因此,标记可以结合这种异常处理代码,使得JSP页面更简单、更富有条理。  OpenSymphony正在计划实现其他的缓冲机制以及一个可管理性更好的主系统,它将使我们能够对缓冲使用的RAM和磁盘空间进行管理。一旦有了这些功能,我们就能够进一步提高网站的响应速度和可靠性。衡量程序员的工作效率与其他领域一样,在软件开发领域中,管理者需要评估程序员的绩效和项目的进度。然而,如何定义恰如其分的评价体系,很令人挠头。  计算代码行数(sourcelinesofcode,SLOC)是最常用的方式之一。不过,最近ShaharYair和SteveMcConnell指出了该方法的一系列重要缺陷。首先,使用代码行数之和无法有效评估一个项目的实际进度,因为它更注重行为而不是结果。最终产品在多大程度上依赖于代码的性能和质量,这也是代码行数无法说明的。因此,聚焦于此实际上是非常有限的工作效率测量方式。  SLOC无法表明要解决的问题的复杂性,也不能以可维护性、灵活性、扩展性等等因素来说明最终产品的质量。说到质量,它反而可能起到负面作用。通过重构、使用设计模式会减少代码行数,同时提升代码质量。代码量大,可能意味着有更多不必要的代码、更高不必要的复杂性、更加僵化难懂。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com  更危险的是,要用这样一种不完整的视角来评价开发人员的绩效,会起到错误的激励作用。开发人员会因此更注重代码的数量,而不顾其对产品质量的损害,也不会从最终产品的角度考虑去优化他们的工作,他们甚至可能有意编写更多冗长无益的代码。“测量什么,就得到什么”,SteveMcConnel回忆。  他指出,有些问题可以通过测量度量功能点数解决掉。那么决定程序大小的因素就变成了输入、输出、查询和文件的数目。不过这种方式也有其缺陷。McConnell提出一些操作性上的问题,比如必须要有一个大家认可的功能点测量机制,而且要想把每个功能点映射到程序员身上也不容易。DanielYokomizo是一位经过认证的功能点专家,他在评论中明确指出了这种方式的其他问题:缺少测量功能点复杂度的工具;还需要考虑诸如代码共享、框架、程序库之类的事情。这些都会影响到完成一个功能的时间。  有很多人参与了对于测量方式的讨论,他们都同意这些做法有其局限,不过他们都觉得衡量开发人员的绩效还是有必要的。实际上,不少人认为SLOC可以作为基础,在其之上通过考虑多种不同因素来进行更复杂的分析。McConnell提出了四条分析开发人员工作效率的必备指导原则,他们也都同意。这四条原则如下:  1、不要指望单一维度的工作效率测量方式能告诉你每个人的真实情况。  2、不要指望任何测量方式可以在很小的粒度上区分出每个人的工作效率差异。这些方式可以为你提出问题,却不会告诉你答案。  3、牢记:趋势总是比单独一点的测量来得重要。  4、问问你自己:为什么要测量个人的工作效率?  测量开发人员的工作效率在什么样的上下文中才是有意义的?有哪些条件?这些条件该如何组合?许多问题仍没有答案。如果你有过类似经验可以分享,请不要犹豫。关于JSP防范SQL注入攻击 SQL注入攻击的总体思路:  发现SQL注入位置;  判断服务器类型和后台数据库类型;  确定可执行情况  对于有些攻击者而言,一般会采取sql注入法。下面我也谈一下自己关于sql注入法的感悟。注入法:  从理论上说,认证网页中会有型如:  select*fromadminwhereusername=’XXX’andpassword=’YYY’的语句,若在正式运行此句之前,如果没有进行必要的字符过滤,则很容易实施SQL注入。  如在用户名文本框内输入:abc’or1=1--在密码框内输入:123则SQL语句变成:  select*fromadminwhereusername=’abc’or1=1andpassword=’123’上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com不管用户输入任何用户名与密码,此语句永远都能正确执行,用户轻易骗过系统,获取合法身份。  猜解法:  基本思路是:猜解所有数据库名称,猜出库中的每张表名,分析可能是存放用户名与密码的表名,猜出表中的每个字段名,猜出表中的每跫锹寄谌荨?BR>  还有一种方式可以获得你的数据库名和每张表的名。  就是通过在形如:http://www..cn/news?id=10’的方式来通过报错获得你的数据库名和表名!  对于jsp而言我们一般采取一下策略来应对:  1、PreparedStatement  如果你已经是稍有水平开发者,你就应该始终以PreparedStatement代替Statement.  以下是几点原因  1、代码的可读性和可维护性.  2、PreparedStatement尽最大可能提高性能.  3、最重要的一点是极大地提高了安全性. 到目前为止,有一些人(包括本人)连基本的恶义SQL语法都不知道.  Stringsql="select*fromtb_namewherename=’"+varname+"’andpasswd=’"+varpasswd+"’";  如果我们把[’or’1’=’1]作为name传入进来.密码随意,看看会成为什么?  select*fromtb_name=’or’1’=’1’andpasswd=’随意’;  因为’1’=’1’肯定成立,所以可以任何通过验证.更有甚者:  把[’;droptabletb_name;]作为varpasswd传入进来,则:  select*fromtb_name=’随意’andpasswd=’’;droptabletb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.  而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.(前提是数据库本身支持预编译,但上前可能没有什么服务端数据库不支持编译了,只有少数的桌面数据库,就是直接文件访问的那些只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑.  2、正则表达式  2.1、检测SQLmeta-characters的正则表达式/(\')|(\’)|(\-\-)|(\#)|(#)/ix  2.2、修正检测SQLmeta-characters的正则表达式/((\=)|(=))[^\n]*((\')|(\’)|(\-\-)|(\;)|(:))/i  2.3、典型的SQL注入攻击的正则表达式/\w*((\')|(\’))((\o)|o|(\O))((\r)|r|(\R))/ix  2.4、检测SQL注入,UNION查询关键字的正则表达式/((\')|(\’))union/ix(\')|(\’)-单引号和它的hex等值union-union关键字。  2.5、检测MSSQLServerSQL注入攻击的正则表达式/exec(\s|\+)+(s|x)p\w+/ix3、字符串过滤  publicstaticStringfilterContent(Stringcontent){  Stringflt="’|and|exec|insert|select|delete|update|count|*|%  |chr|mid|master|truncate|char|declare|;|or|-|+|,";  Stringfilter[]=flt.split("|");  for(inti=0;i  {  content.replace(filter[i],上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com"");  }  returncontent;  }  、不安全字符屏蔽  本部分采用js来屏蔽,起的作用很小,这样用屏蔽关键字的方法虽然有一定作用,但是在实际应用中这些SQL的关键字也可能成为真正的查询关键字,到那是被你屏蔽了那用户不是不能正常的使用了。只要在代码规范上下点功夫就可以了。  凡涉及到执行的SQL中有变量时,用JDBC(或者其他数据持久层)提供的如:PreparedStatement就可以,切记不要用拼接字符串的方法就可以了.  功能介绍:检查是否含有"’","\\","/"  参数说明:要检查的字符串  返回值:0:是1:不是  函数名是  functioncheck(a)  {  return1;  fibdn=newArray("’","\\","/");  i=fibdn.length;  j=a.length;  for(ii=0;ii=li_WS_Width orli_my_Height+li_800bc>=li_WS_Height then   w_1.WindowState=maximized!     else   w_1.WindowState=normal! /*居中*/   w_1.X=(li_WS_Width- li_my_Width)/2   w_1.Y=(li_WS_Height-li_my_Height)/2  endif    caseelse     /*1024×768...*/  ifli_my_Width+li_1024bc>=li_WS_Widthor li_my_Height+li_1024bc>=li_WS_Heightthen    w_1.WindowState=maximized!     else     w_1.WindowState=normal!  /*居中*/   w_1.X=(li_WS_Width- li_my_Width)/2   w_1.Y=(li_WS_Height-li_my_Height)/2     endifendchoose改进的ASP备份SQLServer数据库   选择操作:备份  恢复  
数据库名:">  
文件路径:(备份或恢复的文件路径)
      <%  'SQLServer数据库的备份与恢复!  ifrequest("action")="backupdatabase"Then  dimsqlserver,sqlname,sqlpassword,sqlLoginTimeout,databasename,bak_file,act  sqlserver="localhost"  sqlname="sa"  sqlpassword上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com="password"  sqlLoginTimeout=15  databasename=trim(request("databasename"))  bak_file=trim(request("bak_file"))  bak_file=replace(bak_file,"$1",databasename)  act=lcase(request("act"))  ifdatabasename=""then  response.write"inputdatabasename"  else  ifact="backup"then  Setsrv=Server.CreateObject("SQLDMO.SQLServer")  srv.LoginTimeout=sqlLoginTimeout  srv.Connectsqlserver,sqlname,sqlpassword  Setbak=Server.CreateObject("SQLDMO.Backup")  bak.Database=databasename  bak.Devices=Files  bak.Action=0  bak.Initialize=1  'bak.Replace=True  bak.Files=bak_file  bak.SQLBackupsrv  iferr.number>0then  response.writeerr.number&"
"  response.writeerr.description&""  endif  Response.write"备份成功!"  elseifact="restore"then  '恢复时要在没有使用数据库时进行!  Setsrv=Server.CreateObject("SQLDMO.SQLServer")  srv.LoginTimeout=sqlLoginTimeout  srv.Connectsqlserver,sqlname,sqlpassword  Setrest=Server.CreateObject("SQLDMO.Restore")  rest.Action=0'fulldbrestore  rest.Database=databasename  rest.Devices=Files  rest.Files=bak_file  rest.ReplaceDatabase=True'Forcerestoreoverexistingdatabase  iferr.number>0then  response.writeerr.number&"
"  response.writeerr.description&""  endif  rest.SQLRestoresrv  Response.write"恢复成功!"  else  Response.write"没有选择操作"  endif  endif  endif  %>辅导:Java中的表达式 表达式  由运算符和变量、常数或常量组成的式子称为表达式。例如2+3,a*b等。表达式是组成程序的基本单位,也是程序运算时的基本单位。  在程序代码内部,每个表达式都有自己对应的数据类型,具体参看下表:序号运算符结果类型1算术运算符数字型位运算符移位运算符递增、递减运算符2比较运算符布尔型逻辑运算符3赋值运算符和变量类型一致4条件运算符和两个值中类型高的一致表达式结果类型  提示:对于序号1和2的运算符组成的表达式,由于比较直观,就不再单独举例了,对于3和4说明如下:  intn=10;  intm=10;  n=(m=10);//则表达式m=10的类型是变量m的类型,也是m的值  booleanb=false;  booleanb1=true;  b=(b1=true);//则表达式b1=true的类型是布尔型,值是true  doubled;  d=10>0?1.0:2;//由于1.0是double型,2是整数型,则表达式的类型是double  对于由多个运算符组成的表达式,其最终的类型由最后一个运算符决定。  在实际的程序代码中,大部分的表达式不能单独成为代码中的一行,否则程序会提示语法错误,例如:  inta=10;  intb=上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com20;  a+b;//不能单独成行  在表达式中,能够单独成行的运算符包括赋值运算符和递增、递减运算符。  总结  本部分系统的讲解了Java语言中运算符的知识,并且介绍了实际使用过程中需要注意的问题,在学习时需要熟记每种运算符的作用,然后在实际项目中根据需要使用对应的运算符来实现程序的功能。调用软键盘的解决方法         输入:                 使用软键盘    得到一个字符串中的最大长度的数字**////  ///获取字符串最长的数字  ///  ///输入字符串  ///最长数字  publicstringGetMaxLenNumber(stringinputStr)  {  //将字符串中的字符存放到数组中,便于处理  char[]strCharArray=inputStr.ToCharArray();  //开始处理的位置  intstartPos=0;  //当前处理的字符长度  inttempCharCount=0;  //数字的最长长度  intmaxLen=0;  //数组的总长度  intlen=strCharArray.Length;  intpos=0;  while(startPosmaxLen)  {  maxLen=tempMax;  pos=startPos;  }  }  else  {  //不是数字  tempMax=0;  startPos++;  break;  }  tempCharCount++;  }  if(startPos+tempCharCount==len)  {  break;  }  tempCharCount=0;  }  strings=inputStr.Substring(pos,maxLen);  returns;  }代码简单描述初学Java语言之多态初体验本文面向Java初学者,我们在教材上经常会看到Java是多态的,可是一般的教科书只停留在理论上,很少有实际操作。现在把多态个概念用代码简单描述一下,由于本人水平有限,所以难免有不足之处。  首先我们有这样几个类,电脑,个人电脑,笔记本电脑。  publicvoidturnOn(){  }  }  现在有了电脑这个类,那么个人PC,笔记本都是继承他。  classPCextendsComputer{  publicvoidturnOn(){    System.out.println("PChasturn上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comon");  }  }  classNBextendsComputer{  publicvoidturnOn(){    System.out.println("NBhasturnon");  }  } 我们看到,每个类都有一个turnOn()方法,而在父类中这个方法是空的,子类中各自有不同的实现,到这里可能还不太明显。如果有另外一个方法,要接受这些类作为参数,就像这样  classTest{  publicvoidgo(Computercomputer){    computer.turnOn();  }  }  这个方法接收的是基类参数,当然我们是可以把子类传递给方法的,也应该这么做。  go(newPC());  go(newNB());  这样他就会去调用具体子类的turnOn()方法,所以这两次调用的输出是不一样的.如果不用基类作为参数,我们想调用每个子类的turnOn()方法,那么就要些两个方法体一样的go()而接收不同的参数的重载。  publicvoidgo(PCcomputer){    computer.turnOn();  }  publicvoidgo(NBcomputer){    computer.turnOn();  }  这样些也是正确的,但是这样会产生很多重复代码,而且也不易维护,当然这只是多态中最基本的一个部分,Java多态机制还有很多特性,关于这些建议大家看看java编程思想(thinkinjava)这本书,里面讲的很详细,这里只是很简单的描述了一下。打造自己Windows终端服务客户端1.首先确保你的机器上存在mstscax.dll,如果没有这个文件,可以从http://download.microsoft.com/download/whistler/tools/1.0/wxp/en-us/msrdpcli.exe  下载并安装远程桌面连接软件.或者使用WindowXP中自带的mstscax.dll,运行regsvr32mstscax.dll进行注册,ccrun测试使用的mstscax.dll版本号是5.1.2600.0,在Windows2000Server中可以编译。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com2.运行C++Builder-->Components-->ImportActiveControl,在列表中找到下面的:  MicrosoftTerminalServicesActiveClient1.0TypeLibrary(Version1.0)  点击Install,你可以选择将其安装到现在的包中,也可以新建一个,选择Intonewpackage-->点击Browser将其保存为D:\ProgramFiles\Borland\ccrun\mstsc\mstsc.bpk。在Description一栏可以填:MicrosoftTerminalServiceControl,这个名称将出现在安装完成后的Package列表中。点击OK以后,稍等片刻,系统会提示mstsc.bpl将被编译并且安装,是否继续,点击yes。这时如果一切正常的话,系统将提示有两个编译错误(嘿嘿,我指的是正常情况下),难道是BCB的BUG?提示找不到OlePrecedure的定义。我靠。记忆中有个OleProcedure,一个o,一个e,该不会真的是笔误吧。将两处OlePrecedure换成OleProcedure,再次编译,ok了,编译成功,点击Install安装。  3.如果上一个步骤成功的话,在组件面板的ActiveX下将多出两个控件:MsTscAx和MsRdpClient,我们主要是利用MsTscAx控件。  4.MsTscAx控件的常用属性和方法:  //桌面高度  MsTscAx1->DesktopHeight=600;  //桌面宽度  MsTscAx1->DesktopWidth=800;  //在连接前显示的字符串  MsTscAx1->ConnectingText=WideString("Welcome!ccrun.");  //连接的服务器地址  MsTscAx1->Server=WideString(edtServer->Text);  //窗口/全屏模式  MsTscAx1->FullScreen=false;  //文档标题:打造自己的Windows终端服务客户端  //作者:ccrun(老妖)信箱:info@ccrun.com  //为防止不负责任的转载者遗漏作者信息,故在此插入此信息,请见谅.  //欢迎访问C++Builder研究http://www.ccrun.com  //画面色深(通常都是256色)  MsTscAx1->ColorDepth=16;  //登录用户名  MsTscAx1->UserName=WideString(edtUserName->Text);  //断开连接后显示的字符串  MsTscAx1->DisconnectedText=WideString("886,ccrun.");  //将位图缓存到磁盘  MsTscAx1->AdvancedSettings->BitmapPeristence=1;  //启用数据压缩  MsTscAx1->AdvancedSettings->Compress=1;  //上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com连接后运行的Shell程序,当关闭此Shell程序后自动断开连接  MsTscAx1->SecuredSettings->set_StartProgram(WideString("C:\\ccrun\\123.exe"));  //连接  MsTscAx1->Connect();  //断开连接  MsTscAx1->Disconnect();  5.新建一个Project,在Form上拖一个MsTscAx控件,根据上面介绍的属性和方法,相信你在BCB中建立自己的终端服务客户端没问题了。  6.编译后的程序发布时必须在目标机器上存在mstscax.dll文件,并且用Regsvr32注册以后才能正常运行。程序员:最简洁的多重查询的解决方案 我们经常会遇到多重查询问题,而长长的SQL语句往往让人丈二和尚摸不着头脑。特别是客户端部分填入查询条件时,如用普通方法将更是难上加难。  以下巧妙地利用"where1=1"的恒等式(事实上很多,让它值为TRUE即可)解决此问题。  正文概要  ’subject信息标题  ’company发布信息的公司名称  ’content发布信息的内容  ’address公司地址  ’infomation公司简介  ’note相关说明  以上值均由FORM提交,然后通过:subject=trim(Request.Form("subject"))等得到相应的值。  <%  ’这个函数很关键!---------------------------  Functionsql(a,b,sqls)  ifb<>""then’如果客户端没有提交此值,则不会产生相应的SQL语句。  sqls=sqls&"and"&a&"like’%"&b&"%’"  endif  sql=sqls  EndFunction  ’-----------------调用数据库  Setconn=Server.CreateObject("ADODB.Connection")  DBpath=Server.MapPath("/database/mydb.mdb")  Conn.Open"driver={MicrosoftAccessDriver(*.mdb)};pwd=;dbq="&DBpath  Setrs=Server.CreateObject("ADODB.Recordset")  sqls="select*frommytablewhere1=1上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com"  ’以下调用上面的函数即可,可以很多个调用(理论上是任意)  sqls=sql("subject",subject,sqls)  sqls=sql("company",company,sqls)  sqls=sql("content",content,sqls)  sqls=sql("address",address,sqls)  sqls=sql("infomation",infomation,sqls)  sqls=sql("note",note,sqls)  sqls=sqls&"orderbyiddesc"  rs.opensqls,conn,3,2  %>上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html

相关文档