Dennis's profileDennis的共享空间PhotosBlogListsMore Tools Help

Blog


    February 24

    数学推理

    俗话说拳不离手  曲不离口 ,我们程序员也应该时常锻炼一下自己的脑子
    下面发几个据说是大多出自微软或其他世界500强企业的面试题
    1.元帅领兵

      元帅统领八员将,每将各分八个营,每营里面摆八阵,每阵配置八先锋,每个先锋八旗头,每个旗头有八队,每队分设八个组,每组带领八个兵。请你掐指算一算,元师共有多少兵?

      2.运算符号的妙用

      在1、2、3、4、5、6、7、8、9这一串数字中间,加入运算符号“+”或“-”,使其代数和等于99,按(1 …… 9)可以有17种解,倒过来的后者(9 …… 1)可以有11种解。有兴趣的读者,不妨一试。

      3.两龟赛跑

      有两只乌龟一起赛跑。甲龟到达10米终点线时,乙龟才跑到9米。现在如果让甲龟的起跑线退后1米,这时两龟再同时起跑比赛,问甲、乙两龟是否同时到达终点?

      4.电视机的价格

      麦克因工作繁忙,决定临时请尼克来协助他工作。规定以一年为期限,一年的报酬为600美元与一台电视机。

      可是尼克做了7个月后,因急事必须离开麦克,并要求麦克付给他应得的钱和电视机。由于电视机不能拆散付给他,结果尼克得到了150美元和一台电视机。

      现在请你想一想:这台电视机值多少钱?

      5.这块石头究竟有多重

      有4个小孩看见一块石头正沿着山坡滚下来,便议论开了。

      “我看这块石头有17公斤重,”第一个孩子说。

      “我说它有26公斤,”第二个孩子不同意地说。

      “我看它重21公斤”,第三个孩子说。

      “你们都说得不对,我看它的正确重量是20公斤,”第四个孩子争着说。

      他们四人争得面红耳赤,谁也不服谁。最后他们把石头拿去称了一下,结果谁也没猜准。其中一个人所猜的重量与石头的正确重量相差2公斤,另外两个人所猜的重量与石头的正确重量之差相同。当然,这里所指的差,不考虑正负号,取绝对值。请问这块石头究竟有多重?

      6.三只砝码称东西

      现在有三种不同重量的标准砝码1克、3克、9克。请问可以称出多少不同物品的重量?在进行称量时,要称的东西与已知的标准砝码可以任意地放在天平的两盘之一。另外,每种砝码都只有一只,而且不准复制。

      7.称米

      现有米9公斤以及50克和200克的砝码各一个。问怎样在天平上只称量三次而称出2公斤米?

      8.比萨饼交易

      在我最喜欢的那家比萨饼店中,10寸的比萨卖4.99美元。店主说,他们有一笔12寸比萨饼的交易,定价为每份5.39美元。请问:该店在这笔比萨饼交易中给予了买方多少折扣?

     9.伊沙贝拉时装精品屋

      纽约伊沙贝拉时装精品屋,新近从意大利购进了一件女式冬装。这衣服的购入价格再加二成,是该店标出的销售价。

      出于半个月内未卖出去,女老板又将这个定价减去了一成,很快被一位漂亮小姐买走了

    。女老板获利400元。

      请问,这件高档女式冬装购入价是多少?

      10.称量罐头

      为罐头工厂工作的送货员A,给一家食品公司送了10箱菠萝罐头。每个罐头重量是800克,每箱装20个。

      正当他送完了货,要回工厂的时候,接到了从工厂打来的电话,说这10箱中有一箱由于机器出了问题而混进了次品,每个罐头缺50克的分量,要送货员把这箱罐头送回工厂以便更换。但是,怎样从中找出到底哪一箱是次品呢?最需要的当然是秤,可是手边又没有。

      正在这时,他忽然发现不远的路旁有一台自动称量体重的机器,也就是投进去1元硬币就可以称量一次重量。他的口袋里刚好就有一个1元硬币。当然也就只能量一次。那么他应该怎么充分利用这只有一次的机会,来找到那一箱不符合规格的产品呢?

      11.按劳取酬

      有一个农场主,雇用了两个临时工帮忙种小麦。其中一个叫做汤姆,是一个耕地能手,但是他不会播种;而另一个叫做尼克,他并不擅长于耕地,但是,他却是播种的好手。这个农场主决定要种十公顷小麦,让他们各自包一半,于是,汤姆从东头开始耕地,而尼克从西头开始耕地。耕一亩地汤姆只要用二十分钟,而尼克却需要四十分钟,但是尼克播种的速度比汤姆要快三倍。

      他们播种完工后,农场主按照他们的工作量给予他俩一共一百元的工钱。请问:他们应该怎么样分这份工钱才最合理?

      12.四兄弟的年龄

      一家有4个兄弟,他们4个的年龄乘起来的积为14。那么,他们各自的年龄是多大?当然年龄应该是整数。

      13.爱的程度

      在一所乡村学校中,一个刚刚毕业的男数学老师S很幸运地同时得到了两个女教师A、B的青睐。S满脑袋数字,在无法从两者之中选择的情况下,他只好对这两位女教师说,“希望你们用数字或者数学公式,来表示你们对我的爱的程度。”

      A说,“与B比起来,我是一百倍地爱你。”

      B说,“A对你的感情当然没有我对你的感情深。与A相比,我是一千倍地爱你。”

      听了她们深情的话语,不知为什么数学老师S反而神情沮丧地说,“这不就等于说,你们两个都是完全不爱我吗?”

      这究竟是怎么回事?

      14.爬楼梯

      一位先生要到10层楼的第8层去办事,不巧正赶上停电,电梯无法使用,他只能够步行上楼。如果他从第1层爬到第4层需要用48秒,那么请问,以同样的速度走到第8层需要多少秒?

      15.空姐分配物品

      在一架飞机上,中间是一条过道,两边是座位,每一排为三人。两位空姐A和B每人负责一边,对每位旅客分配旅行物品。

      开始的时候,A给右边的旅客发放了6份,此时,B过来对她说,左边应该由A负责。于是A重新到左边开始发放,B接着给右边剩下的旅客发放物品,之后,又帮A发了15份,最后两人同时结束工作。

      请问:A和B谁发的多?多发了多少份?

     ★假设一张圆盘像唱机上的唱盘那样转动。这张盘一半是黑色,一半是白色。假设你有数量不限的一些颜色传感器。要想确定圆盘转动的方向,你需要在它周围摆多少个颜色传感器?它们应该被摆放在什么位置?

      ★假设时钟到了12点。注意时针和分针重叠在一起。在一天之中,时针和分针共重叠多少次?你知道它们重叠时的具体时间吗?

      ★你有两个罐子,分别装着50个红色的玻璃球和50个蓝色的玻璃球。随意拿起一个罐子,然后从里面拿出一个玻璃球。怎样最大程度地增加让自己拿到红球的机会?利用这种方法,拿到红球的几率有多大?

      ★中间只隔一个数字的两个奇数被称为奇数对,比如17和19。证明奇数对之间的数字总能被6整除(假设这两个奇数都大于6)。现在证明没有由三个奇数组成的奇数对。

      ★一个屋子有一个门(门是关闭的)和3盏电灯。屋外有3个开关,分别与这3盏灯相连。你可以随意操纵这些开关,可一旦你将门打开,就不能变换开关了。确定每个开关具体管哪盏灯。

      ★假设你有8个球,其中一个略微重一些,但是找出这个球的惟一方法是将两个球放在天平上对比。最少要称多少次才能找出这个较重的球?

      ★假设你站在镜子前,抬起左手,抬起右手,看看镜中的自己。当你抬起左手时,镜中的自己抬起的似乎是右手。可是当你仰头时,镜中的自己也在仰头,而不是低头。为什么镜子中的影像似乎颠倒了左右,却没有颠倒上下?

      ★ 你有4瓶药。每粒药丸的重量是固定的,不过其中有一瓶药受到了污染,药丸的重量发生了变化,每个药丸增加了一点重量。你怎样一下子测出哪瓶药是遭到污染的呢?

      ★下面玩一个拆字游戏,所有字母的顺序都被打乱。你要判断这个字是什么。假设这个被拆开的字由5个字母组成:

      1. 共有多少种可能的组合方式?

      2. 如果我们知道是哪5个字母,那会怎么样?

      3. 找出一种解决这个问题的方法。

      ★有4个女人要过一座桥。她们都站在桥的某一边,要让她们在17分钟内全部通过这座桥。这时是晚上。她们只有一个手电筒。最多只能让两个人同时过桥。不管是谁过桥,不管是一个人还是两个人,必须要带着手电筒。手电筒必须要传来传去,不能扔过去。每个女人过桥的速度不同,两个人的速度必须以较慢的那个人的速度过桥。

      第一个女人:过桥需要1分钟;

      第二个女人:过桥需要2分钟;

      第三个女人:过桥需要5分钟;

      第四个女人:过桥需要10分钟。

      比如,如果第一个女人与第4个女人首先过桥,等她们过去时,已经过去了10分钟。如果让第4个女人将手电筒送回去,那么等她到达桥的另一端时,总共用去了20分钟,行动也就失败了。怎样让这4个女人在17分钟内过桥?还有别的什么方法?

      ★如果你有一个5夸脱的水桶和一个3夸脱的水桶,如何准确量出4夸脱的水?

      ★你有一袋糖,有红色的,蓝色的,绿色的。闭上眼睛,拿出两块颜色一样的糖,你需要拿多少次才能确保有两块颜色相同的?

      ★如果你有两个桶,一个装的是红色的颜料,另一个装的是蓝色的颜料。你从蓝色颜料桶里舀一杯,倒入红色颜料桶,再从红色颜料桶里舀一杯倒入蓝颜料桶。两个桶中红蓝颜料的比例哪个更高?通过算术的方式来证明这一点。

    July 30

    人工智能

    作者:维基百科   文章来源:维基百科
        近年来,随着计算机技术的迅猛发展和日益广泛的应用,自然地会提出人类智力活动能不能由计算机来实现的问题。几十年来,人们一向把计算机当作是只能以极快地、熟练地、准确地运算数字的机器。但是在当今世界要解决的问题并不完全是数值计算,像语言的理解和翻译、图形和声音的识别、决策管理等都不属于数值计算,特别像医疗诊断要有专门的特有的经验和知识的医师才能作出正确的诊断。这就要求计算机能从“数据处理”扩展到还能“知识处理”的范畴。计算机能力范畴的转化是导至“人工智能”快速发展的重要因素。
    人工智能的定义:
        著名的美国斯坦福大学人工智能研究中心尼尔逊教授对人工智能下了这样一个定义:“人工智能是关于知识的学科――怎样表示知识以及怎样获得知识并使用知识的科学。”而另一个美国麻省理工学院的温斯顿教授认为:“人工智能就是研究如何使计算机去做过去只有人才能做的智能工作。”这些说法反映了人工智能学科的基本思想和基本内容。即人工智能是研究人类智能活动的规律,构造具有一定智能的人工系统,研究如何让计算机去完成以往需要人的智力才能胜任的工作,也就是研究如何应用计算机的软硬件来模拟人类某些智能行为的基本理论、方法和技术。
        人工智能(ArtificialIntelligence,简称AI)是计算机学科的一个分支,二十世纪七十年代以来被称为世界三大尖端技术之一(空间技术、能源技术、人工智能)。也被认为是二十一世纪(基因工程、纳米科学、人工智能)三大尖端技术之一。这是因为近三十年来它获得了迅速的发展,在很多学科领域都获得了广泛应用,并取得了丰硕的成果,人工智能已逐步成为一个独立的分支,无论在理论和实践上都已自成一个系统。
        人工智能是研究使计算机来模拟人的某些思维过程和智能行为(如学习、推理、思考、规划等)的学科,主要包括计算机实现智能的原理、制造类似于人脑智能的计算机,使计算机能实现更高层次的应用。人工智能将涉及到计算机科学、心理学、哲学和语言学等学科。可以说几乎是自然科学和社会科学的所有学科,其范围已远远超出了计算机科学的范畴,人工智能与思维科学的关系是实践和理论的关系,人工智能是处于思维科学的技术应用层次,是它的一个应用分支。从思维观点看,人工智能不仅限于逻辑思维,要考虑形象思维、灵感思维才能促进人工智能的突破性的发展,数学常被认为是多种学科的基础科学,数学也进入语言、思维领域,人工智能学科也必须借用数学工具,数学不仅在标准逻辑、模糊数学等范围发挥作用,数学进入人工智能学科,它们将互相促进而更快地发展。
        从实用观点来看,人工智能是一门知识工程学:以知识为对象,研究知识的获取、知识的表示方法和知识的使用。
    计算机与智能
        通常我们用计算机,不仅要告诉计算机,要做什么,还必须详细地、正确地告诉计算机怎么做。也就是说,人们要根据任务的要求,以适当的计算机语言,编制针对该任务的应用程序,才能应用计算机完成此项任务。这样实际上是在人完全控制计算机完成的,是谈不上计算机有“智能”。
        大家都知道,世界国际象棋棋王卡斯帕罗夫与美国IBM公司的RS/6000(深蓝)计算机系统于1997年5月11日进行了六局“人机大战”,结果“深蓝”以3.5比2.5的总比分获胜。比赛结束了给人们留下了深刻的思考;下棋要获胜要求选手要有很强的思维能力、记忆能力、丰富的下棋经验,还得及时作出反映,迅速进行有效的处理,否则一着出错满皆输,这显然是个“智能”问题。尽管开发“深蓝”计算机的IBM专家也认为它离智能计算机还相差甚远,但它以高速的并行的计算能力(2r108步/秒棋的计算速度)。实现了人类智力的计算机上的部分模拟。
        从字面上看,“人工智能”就是用人工的方法在计算机上实现人的智能,或者说是人们使计算机具有类似于人的智能。
    智能与知识
        在20世纪70年代以后,在许多国家都相继开展了人工智能的研究,由于当时对实现机器智能理解得过于容易和片面,认为只要一些推理的定律加上强大的计算机就能有专家的水平和超人的能力。这样,虽然也获得一定成果,但问题也跟着出现了,例如机器翻译当时人们往往认为只要用一部双向词典及词法知识,就能实现两种语言文字的互译,其实完全不是这么一回事,例如,把英语句子“Timeflieslikeanarrow”(光阴似箭)翻译成日语,然后再译回英语,竟然成为“苍蝇喜欢箭”;当把英语“Thespiritiswillingbutthefleshisweak”(心有余而力不足)译成俄语后,再译回来竟变成“Thewineisgoodbutthemeatisspoiled”(酒是好的但肉已变质)。在其它方面也都遇到这样或者那样的困难。这时,本来对人工智能抱怀疑态度的人提出指责,甚至把人工智能说成是“骗局”、“庸人自扰”,有些国家还削减人工智能的研究经费,一时人工智能的研究进入了低潮。
        然而,人工智能研究的先驱者们没有放弃,而是经过认真的反思、总结经验和教训,认识到人的智能表现在人能学习知识,有了知识,能了解、运用已有的知识。正向思维科学所说“智能的核心是思维,人的一切智慧或智能都来自大脑思维活动,人类的一切知识都是人们思维的产物。”“一个系统之所以有智能是因为它具有可运用的知识。”要让计算机“聪明”起来,首先要解决计算机如何学会一些必要知识,以及如何运用学到的知识问题。只是对一般事物的思维规律进行探索是不可能解决较高层次问题的。人工智能研究的开展应当改变为以知识为中心来进行。
        自从人工智能转向以知识为中心进行研究以来,以专家知识为基础开发的专家系统在许多领域里获得成功,例如:地矿勘探专家系统(PROSPECTOR)拥有15种矿藏知识,能根据岩石标本及地质勘探数据对矿产资源进行估计和预测,能对矿床分布、储藏量、品位、开采价值等进行推断,制定合理的开采方案,成功地找到了超亿美元的钼矿。又如专家系统(MYCIN)能识别51种病菌,正确使用23种抗菌素,可协助医生诊断、治疗细菌感染性血液病,为患者提供最佳处方,成功地处理了数百个病例。它还通过以下的测试:在互相隔离的情况下,用MYCIN系统和九位斯坦福大学医学院医生,分别对十名不清楚感染源的患者进行诊断和处方,由八位专家进行评判,结果是MYCIN和三位医生所开出的处方对症有效;而在是否对其它可能的病原体也有效而且用药又不过量方面,MYCIN则胜过了九位医生。显示出较高的水平。
        专家系统的成功,充分表明知识是智能的基础,人工智能的研究必须以知识为中心来进行。由于知识的表示、利用、获取等的研究都取得较大的进展。因而,人工智能的研究得以解决了许多理论和技术上问题。
    人工智能研究的目标
        1950年英国数学家图灵(A.M.Turing,1912—1954)发表了“计算机与智能”的论文中提出著名的“图灵测试”,形象地提出人工智能应该达到的智能标准;图灵在这篇论文中认为“不要问一个机器是否能思维,而是要看它能否通过以下的测试;让人和机器分别位于两个房间,他们只可通话,不能互相看见。通过对话,如果人的一方不能区分对方是人还是机器,那么就可以认为那台机器达到了人类智能的水平。图灵为此特地设计了被称为“图灵梦想”的对话。在这段对话中“询问者”代表人,“智者”代表机器,并且假定他们都读过狄更斯(C.Dickens)的著名小说《匹克威克外传》,对话内容如下:
        询问者:在14行诗的首行是“你如同夏日”,你不觉得“春日”更好吗? 智者:它不合韵。 询问者:“冬日”如何?它可完全合韵的。 智者:它确是合韵,但没有人愿意被比作“冬日”。 询问者:你不是说过匹克威克先生让你想起圣诞节吗? 智者:是的。 询问者:圣诞节是冬天的一个日子,我想匹克威克先生对这个比喻不会介意吧。 智者:我认为您不够严谨,“冬日”指的是一般冬天的日子,而不是某个特别的日子,如圣诞节。 从上面的对话可以看出,能满足这样的要求,要求计算机不仅能模拟而且可以延伸、扩展人的智能,达到甚至超过人类智能的水平,在目前是难以达到的,它是人工智能研究的根本目标。
        人工智能研究的近期目标;是使现有的计算机不仅能做一般的数值计算及非数值信息的数据处理,而且能运用知识处理问题,能模拟人类的部分智能行为。按照这一目标,根据现行的计算机的特点研究实现智能的有关理论、技术和方法,建立相应的智能系统。例如目前研究开发的专家系统,机器翻译系统、模式识别系统、机器学习系统、机器人等。
    人工智能的研究领域
        目前,人工智能的研究是与具体领域相结合进行的。基本上有如下领域;
    专家系统
        专家系统是依靠人类专家已有的知识建立起来的知识系统,目前专家系统是人工智能研究中开展较早、最活跃、成效最多的领域,广泛应用于医疗诊断、地质勘探、石油化工、军事、文化教育等各方面。它是在特定的领域内具有相应的知识和经验的程序系统,它应用人工智能技术、模拟人类专家解决问题时的思维过程,来求解领域内的各种问题,达到或接近专家的水平。
     
    机器学习
        要使计算机具有知识一般有两种方法;一种是由知识工程师将有关的知识归纳、整理,并且表示为计算机可以接受、处理的方式输入计算机。另一种是使计算机本身有获得知识的能力,它可以学习人类已有的知识,并且在实践过程中不总结、完善,这种方式称为机器学习。
        机器学习的研究,主要在以下三个方面进行:一是研究人类学习的机理、人脑思维的过程;和机器学习的方法;以及建立针对具体任务的学习系统。
        机器学习的研究是在信息科学、脑科学、神经心理学、逻辑学、模糊数学等多种学科基础上的。依赖于这些学科而共同发展。目前已经取得很大的进展,但还没有能完全解决问题。
    模式识别
        模式识别是研究如何使机器具有感知能力,主要研究视觉模式和听觉模式的识别。如识别物体、地形、图象、字体(如签字)等。在日常生活各方面以及军事上都有广大的用途。近年来迅速发展起来应用模糊数学模式、人工神经网络模式的方法逐渐取代传统的用统计模式和结构模式的识别方法。特别神经网络方法在模式识别中取得较大进展。
    理解自然语言
        计算机如能“听懂”人的语言(如汉语、英语等),便可以直接用口语操作计算机,这将给人们带极大的便利。计算机理解自然语言的研究有以下三个目标:一是计算机能正确理解人类的自然语言输入的信息,并能正确答复(或响应)输入的信息。二是计算机对输入的信息能产生相应的摘要,而且复述输入的内容。三是计算机能把输入的自然语言翻译成要求的另一种语言,如将汉语译成英语或将英语译成汉语等。目前,研究计算机进行文字或语言的自动翻译,人们作了大量的尝试,还没有找到最佳的方法,有待于更进一步深入探索。
    机器人学
        机器人是一种能模拟人的行为的机械,对它的研究经历了三代的发展过程:
        第一代(程序控制)机器人:这种机器人一般是按以下二种方式“学会”工作的;一种是由设计师预先按工作流程编写好程序存贮在机器人的内部存储器,在程序控制下工作。另一种是被称为“示教—再现”方式,这种方式是在机器人第一次执行任务之前,由技术人员引导机器人操作,机器人将整个操作过程一步一步地记录下来,每一步操作都表示为指令。示教结束后,机器人按指令顺序完成工作(即再现)。如任务或环境有了改变,要重新进行程序设计。这种机器人能尽心尽责的在机床、熔炉、焊机、生产线上工作。日前商品化、实用化的机器人大都属于这一类。这种机器人最大的缺点是它只能刻板地按程序完成工作,环境稍有变化(如加工物品略有倾斜)就会出问题,甚至发生危险,这是由于它没有感觉功能,在日本曾发生过机器人把现场的一个工人抓起来塞到刀具下面的情况。
        第二代(自适应)机器人:这种机器人配备有相应的感觉传感器(如视觉、听觉、触觉传感器等),能取得作业环境、操作对象等简单的信息,并由机器人体内的计算机进行分析、处理,控制机器人的动作。虽然第二代机器人具有一些初级的智能,但还需要技术人员协调工作。目前已经有了一些商品化的产品。
        第三代(智能)机器人:智能机器人具有类似于人的智能,它装备了高灵敏度的传感器,因而具有超过一般人的视觉、听觉、嗅觉、触觉的能力,能对感知的信息进行分析,控制自己的行为,处理环境发生的变化,完成交给的各种复杂、困难的任务。而且有自我学习、归纳、总结、提高已掌握知识的能力。目前研制的智能机器人大都只具有部分的智能,和真正的意义上的智能机器人,还差得很远。
    智能决策支持系统
        决策支持系统是属于管理科学的范畴,它与“知识—智能”有着极其密切的关系。在80年代以来专家系统在许多方面取得成功,将人工智能中特别是智能和知识处理技术应用于决策支持系统,扩大了决策支持系统的应用范围,提高了系统解决问题的能力,这就成为智能决策支持系统。
    人工神经网络
        人工神经网络是在研究人脑的奥秘中得到启发,试图用大量的处理单元(人工神经元、处理元件、电子元件等)模仿人脑神经系统工程结构和工作机理。
        在人工神经网络中,信息的处理是由神经元之间的相互作用来实现的,知识与信息的存储表现为网络元件互连间分布式的物理联系,网络的学习和识别取决于和神经元连接权值的动态演化过程。
        多年来,人工神经网络的研究取得了较大的进展,成为具有一种独特风格的信息处理学科。当然目前的研究还只是一些简单的人工神经网络模型。要建立起一套完整的理论和技术系统,需要做出更多努力和探讨。然而人工神经网络已经成为人工智能中极其重要的一个研究领域。
        结束语:人类经过五千的发展进入了基于知识的“知识经济”。人类社会空前地高速发展。知识是智能的基础,知识只有转化为智能才能发挥作用,知识无限的积累,智能也就将在人类社会起越来越大的作用,更有人提出:知识经济的进一步发展将是“智能经济”。“智能经济”是基于“广义智能”的经济,“广义智能”包含:人的智能、人工智能以及人和智能机器相结合的“集成智能”。可以想象基于广义智能的“智能经济”将比基于知识的“知识经济”将具有更高的智能水平,更高更快发展速度。 
    July 11

    delphi学习笔记

       由于客观原因在搞delphi,记录一些资料方便以后察看。
     
    listbox从文件中读取列表的操作
    ListBox1.Items.LoadFromFile(ExtractFilePath(Application.ExeName)+’aaa.txt’);
    ListBox1.Items.Add(Edit1.Text); //添加了一个项目
    ListBox1.Items.SaveToFile(ExtractFilePath(Application.ExeName)+’aaa.txt’);
    删除项目ListBox1.Items.Delete(listbox1.itemindex);
    ------------------------------------
    判断窗体是否已经打开
    if frmPriceInput <> nil then ....
    注意:有时窗体虽然已经关闭,但没完全释放,最好在该窗体关闭的CLOSE事件里加入 frmPrintInput = nil;
    ------------------------------------
    关闭MDI子窗口的方法
    在子窗口的OnClose事件处理过程中加入如下代码
      Action := caFree;
    Delphi为一个Form的关闭行为指定了四种方式,分别是:
    caNone -- 禁止Form被关闭
    caHide -- Form不被关闭,但是被隐藏。被隐藏的Form仍然可以被程序访问。
    caFree -- Form被关闭,并且释放其占用的资源。
    caMinimize -- Form被最小化而不是被关闭,这是MDI子窗口的默认关闭行为。
    ------------------------------------
    系统配置文件 *.INI 的操作
    头部要引用IniFiles
    1、声明变量
    IniFile:TiniFile;
    2、指明路径
    IniFile := TIniFile.Create(ExtractFilePath(Application.ExeName)+’option.ini’);
    3、读取变量,注意变量有类型之分readstring,readinteger...等
    titleBMPFile:=IniFile.ReadString(’TitleImage’,’FileName’,’’);  //IniFile.ReadString(’组名’,’变量’,’默认值’)
    IniFile.ReadInteger
    IniFile.ReadBool
    4、写入或修改变量
    IniFile.WriteString(’标题’,’变量1’,’值’);
    5、用完后释放
    IniFile.Free;
    ------------------------------------
    动态读取图象
    Image1.Picture.LoadFromFile(titleBMPFile);
    ------------------------------------
    fastreport自定义函数的用法
    1、先在普通工程窗体上定义好函数
    2、在frreport控件的userfunction中写入
        if ansicomparetext( ’My_StrToRMB’ , Name ) = 0 then
       val:=My_StrToRMB(frparser.Calc(p1));
    //MY_STRTORMB是函数名
    //如果定义多个函数,就多来几个IF即可。
    在报表设计视图中就可以调用这个函数了。
    ------------------------------------
    数组是这样定义的sbh:array [0..9999999,0..1]  of string;
    ------------------------------------
    treeview的用法
    //先定义项目序数和节点
    n: Integer;
    Node: TTreeNode;
    Node := Tree1.Selected;
    if (Node = nil) or (Node.StateIndex = -1) then Exit;//一般可以把不作反应的列的stateindex定为-1
    n := Node.StateIndex;
    ------------------------------------
    Fields[]       通过索引返回字段,要自己選擇返回的類型!
    FieldByName()  通过名字返回字段,要自己選擇返回的類型!
    FieldValues[]  通过名字返回字段的值,自動化類型!  
    ------------------------------------
    调用外部程序方法
    用ShellExecute,在USES段加入SHELLAPI,使用时如:
       ShellExecute(handle,’open’,’c:\myapp\myapp.exe’,’-s’,’’,SW_SHOWNORMAL);
       第一个参数为父窗口句柄;
       第二个参数为打开方式(OPEN,PRINT两种);
       第三个参数为执行文件全路径;
       第四个参数为执行文件参数;
       第五个参数为执行文件开始运行时的初始目录;
       第六个参数为为执行文件运行方式(SW_HIDE,SW_MAXIMIZE,SW_MINIMIZE,
    SW_RESTORE,SW_SHOW,SW_SHOWDEFAULT,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED,
    SW_SHOWMINNOACTIVE,SW_SHOWNA,SW_SHOWNOACTIVATE,SW_SHOWNORMAL);
    ------------------------------------
    判断文件是否存在
    if not fileexists(’db2.mdb.bak’) then ...
    ------------------------------------
    判断按键
    if Key=#13 then //如果回车则。。。
    ------------------------------------
    退出
    关闭窗口 close;
    关闭程序:Application.Terminate;
    退出事件 exit;
    ------------------------------------
    检测软件是否已在运行
    if GetLastError = ERROR_ALREADY_EXISTS then...
    ------------------------------------
    定义函数是这样写的
    function IsReadOnly(b: Boolean; colors: Tcolor): Boolean;
    ------------------------------------
    fastreport直接打印
    FrReport1.PrepareReport;     //初始化
    FrReport1.PrintPreparedReport(’1’,1,True,frAll);    //打印
    预览FrReport1.showreport;
    ------------------------------------
    找开浏览器,进入某站点。(或调用WINDOWS程序)
    进入站点ShellExecute(Handle, PChar(’OPEN’), PChar(’http://www.devexpress.com/downloads/index.asp’), nil, nil, SW_SHOWMAXIMIZED);
    发送邮件ShellExecute(Handle, ’open’, PChar(’mailto:’ + edtemail.Text + ’?subject=’), nil, nil, SW_SHOW);
    ------------------------------------
    打开文件对话框
    if OpenPictureDialog.Execute then

    ------------------------------------
    调用帮助文件
    Application.HelpFile := ’..\..\Help\eBars.hlp’;

    ------------------------------------
    打开窗口
    TForm1.Create(self).ShowModal;

    ------------------------------------
    取得当前执行程序的路径
    FPath := ExtractFilePath(Application.ExeName);

    FileName := ExtractFilePath(ParamStr(0)) + ’\MDB\电子通讯录.mdb’;
    ------------------------------------
    当前路径
    getcurrentdir

    ------------------------------------
    判断当前鼠标处于某个位置(TAG)
        case TComponent(Sender).Tag of
          0: begin
            ...
              lbBarBackgroud.Caption := sCustomImage;
             end;
          1: begin
            ...
              lbBarBackgroud.Caption := sCustomImage;
             end;
          2: begin
            ...
              lbBarBackgroud.Caption := sCustomImage;
             end;
    ------------------------------------
    数据库连接
    1、建立一个adoconnection控件,命名为conn
    2、建立一个adodataset控件,命名为ds
    然后就可以用以下语句连接并执行SQL查询(本例是access的数据库,带密码)。
    conn.ConnectionString:=’Provider=Microsoft.Jet.OLEDB.4.0;Data Source=’+getcurrentdir+’\data\pn.mdb;Persist Security Info=False;jet oledb:database password=80513’;
    conn.Connected:=true;
    ds.Active:=false;
    ds.CommandText:=’select 拜访日期,拜访时间,拜访客户,拜访地点,谈话内容 from khbf order by 拜访日期 desc’;
    ds.Active:=true;
    ------------------------------------
    ADODataSet1.State的用法
    if ADODataSet1.State in [dsEdit,dsInsert] then
          ADODataSet1.Post ;
    ------------------------------------
    ADOQuery.open和ADOQuery.execSQL的区别
    用于存贮时如insert 只能用execSQL
    ------------------------------------
    ------------------------------------
    ------------------------------------
    ------------------------------------
    回车光标移到另一个输入框
    if key=#13 then
    cmb_name.SetFocus;
    ------------------------------------
    播放声音
    playsound(’c:\windows\media\start.wav’,0,SND_ASYNC);
    ------------------------------------
    列表框listbox增加项目
    cmb_name.Items.Add(adotable1.FieldValues[’帐号’]);

    ------------------------------------
    listview用法
    ListView.Selected := ListView.Items[0];
    ListView.Selected.Focused := True;
    ListView.Selected.MakeVisible(False);
    ListView.Selected.Index
    ListView.Items.Count
    ListView.Items.Delete(3) //删除第3个项目
    ListView.Items.Add.Caption:=’dddddddd’; //增加一个项目
    ListView.Items.BeginUpdate;
    ListView.Items.EndUpdate
    ListView.Canvas.Font.Color := clGrayText;
    if ListView.Selected <> nil then。。。。。
    //往listview添加项目
    先定义
    var itm: TListItem;
    然后
    listview.Items.Clear;
    itm := listview.Items.Add;
    itm.ImageIndex := 5;
    itm.Caption := Msg.Subject;
    itm.SubItems.Add(’aaaaa’);
    itm.SubItems.Add(’ffffff’);
    itm.SubItems.Add(’ffdfdfdf’);
    itm.SubItems.Add(’oooo’);
    ------------------------------------
    静态调用DLL的方法
    有参数
    procedure CreateSms(Text: Pchar);stdcall;External ’SmsLib.dll’;
    无参数
    procedure CreateSms;stdcall;External ’SmsLib.dll’;
    ------------------------------------
    确定、取消对话框作用
    if application.MessageBox(’真的退出?’,’提示’,mb_okcancel)=idok then
    application.Terminate;   //Terminate是终止程序
    showmessage(’请先选中要修改的班级’);    //这个是简单的显示提示框
    messagebox(self.Handle ,’价格输入不合法!’,’提示’,MB_OK or MB_ICONASTERISK);
    ------------------------------------
    调用窗体的步骤
    先引用该窗体的单元,然后建立窗体,最后显示出来。
    例1:
    use uxsgl;
    Application.CreateForm(TFmXsgl, FmXsgl);
    fmxsgl.ShowModal;
    例2:
      Frm_LendDetail:=TFrm_LendDetail.Create(self);
      Try
        Frm_LendDetail.ShowModal;
      Finally
        Frm_LendDetail.Free;
      End;
    ------------------------------------
    数据库查询
    先建立数据源,然后添加一个TADOQUERY
    adoquery1.SQL.Clear ;
    adoquery1.Close;
    adoquery1.SQL.Add(’select * from tkcb order by ckcb_kh’);
    adoquery1.Open;
    aaa=adoquery1.FieldValues[’ckcb_kc’];    //取出当前记录某字段的值
    adoquery1.Next;        //下一记录
    adoquery1.Close;    //关闭查询
    ------------------------------------
    判断键盘输入字符-chr(13)是回车
     if key=chr(13) then
       bitbtn1.SetFocus;
    ------------------------------------
    时间格式
    lblTime.Caption := FormatDateTime(’yyyymmdd hh:nn:ss’,Now);
    ------------------------------------
    表数据的添加添加
    dmd是数据模块 tbl_zgdb是表名
      with dmd.tbl_zgdb do begin
        Append;
        FieldValues[’HYZH’] := Edt_HYZH.text;
        FieldValues[’XM’] := Edt_xm.text;
        FieldValues[’XB’] := Edt_xb.text;
        FieldValues[’dw’] := Edt_dw.text;
        FieldValues[’ZZMM’] := zzmm;
        FieldValues[’CSNY’] := trim(Edt_csny.text);
        FieldValues[’GZSJ’] := Edt_gzsj.text;
        FieldValues[’DBLB’] := dblb;
        FieldValues[’ZCLB’] := zclb;
        FieldValues[’XL’] := xl;
        FieldValues[’BZ’] := Edt_bz.text;
        Post;
        close;
      end;
    ------------------------------------
    列表框的选项值
    Edit1.Text:=listbox1.Items.Strings[listbox1.itemindex];
    ------------------------------------
    Delphi键盘按键伪码
    用法:if key = chr(VK_RETURN) then...
    常数名称 十六进制值 十进制值 对应按键
    VK_LBUTTON 01 1 鼠标的左键
    VK_RBUTTON 02 2 鼠标的右键
    VK-CANCEL 03 3 Contol-break 执行
    VK_MBUTTON 04 4 鼠标的中键(三按键鼠标)
    VK_BACK 08 8 Backspace键
    VK_TAB 09 9 Tab键
    VK_CLEAR 0C 12 Clear键
    VK_RETURN 0D 13 Enter键
    VK_SHIFT 10 16 Shift键
    VK_CONTROL 11 17 Ctrl键
    VK_MENU 12 18 Alt键
    VK_PAUSE 13 19 Pause键
    VK_CAPITAL 14 20 Caps Lock键
    VK_ESCAPE 1B 27 Ese键
    VK_SPACE 20 32 Spacebar键
    VK_PRIOR 21 33 Page Up键
    VK_NEXT 22 34 Page Domw键
    VK_END 23 35 End键
    VK_HOME 24 36 Home键
    VK_LEFT 25 37 LEFT ARROW 键(←)
    VK_UP 26 38 UP ARROW键(↑)
    VK_RIGHT 27 39 RIGHT ARROW键(→)
    VK_DOWN 28 40 DOWN ARROW键(↓)
    VK_Select 29 41 Select键
    VK_EXECUTE 2B 43 EXECUTE键
    VK_SNAPSHOT 2C 44 Print Screen键 
    VK_Insert 2D 45 Ins键
    VK_Delete 2E 46 Del键
    VK_HELP 2F 47 Help键
    VK_0 30 48 0键
    VK_1 31 49 1键
    VK_2 32 50 2键
    VK_3 33 51 3键
    VK_4 34 52 4键
    VK_5 35 53 5键
    VK_6 36 54 6键
    VK_7 37 55 7键
    VK_8 38 56 8键
    VK_9 39 57 9键
    VK_A 41 65 A键
    VK_B 42 66 B键
    VK_C 43 67 C键
    VK_D 44 68 D键
    VK_E 45 69 E键
    VK_F 46 70 F键
    VK_G 47 71 G键
    VK_H 48 72 H键
    VK_I 49 73 I键
    VK_J 4A 74 J键
    VK_K 4B 75 K键
    VK_L 4C 76 L键
    VK_M 4D 77 M键
    VK_N 4E 78 N键
    VK_O 4F 79 O键
    VK_P 50 80 P键
    VK_Q 51 81 Q键
    VK_R 52 82 R键
    VK_S 53 83 S键
    VK_T 54 84 T键
    VK_U 55 85 U键
    VK_V 56 86 V键
    VK_W 57 87 W键
    VK_X 58 88 X键
    VK_Y 59 89 Y键
    VK_BZ 5A 90 Z键
    VK_NUMPAD0 60 96 数字键0键
    VK_NUMPAD1 61 97 数字键1键
    VK_NUMPAD2 62 98 数字键2键
    VK_NUMPAD3 63 99 数字键3键
    VK_NUMPAD4 64 100 数字键4键
    VK_NUMPAD5 65 101 数字键5键
    VK_NUMPAD6 66 102 数字键6键
    VK_NUMPAD7 67 103 数字键7键
    VK_NUMPAD8 68 104 数字键8键
    VK_NUMPAD9 69 105 数字键9键
    VK_MULTIPLY 6A 106 *键
    VK_ADD 6B 107 +键
    VK_SEPARATOR 6C 108 Separator键
    VK_SUBTRACT 6D 109 -键
    VK_DECIMAL 6E 110 .键
    VK_DIVIDE 6F 111 键
    VK_F1 70 112 F1键
    VK_F2 71 113 F2键
    VK_F3 72 114 F3键
    VK_F4 73 115 F4键
    VK_F5 74 116 F5键
    VK_F6 75 117 F6键
    VK_F7 76 118 F7键
    VK_F8 77 119 F8键
    VK_F9 78 120 F9键
    VK_F10 79 121 F10键
    VK_F11 7A 122 F11键
    VK_F12 7B 123 F12键
    VK_NUMLOCK 90 144 Num Lock 键
    VK_SCROLL 91 145 Scroll Lock键
    ==================
    Delphi中怎么将实数取整? 

      floor 和 ceil 是 math unit 里的函数,使用前要先 Uses Math。
      trunc 和 round 是 system unit 里的函数,缺省就可以用。
       floor 直接往小的取,比如 floor(-123.55)=-124,floor(123.55)=123
       trunc 直接切下整数,比如 trunc(-123.55)=-123, floor(123.55)=123
       ceil 直接往大的取,比如 ceil(-123.55)=-123, ceil(123.55)=124
       round 计算四舍五入,比如 round(-123.55)=-124,round(123.55)=124
    ==================================================
    如何把RGB颜色转变成Delphi的 Tcolor?
    form1.color:=rgbtocolor(255,0,0); 
    函数: 
    --------- 
    function RGBToColor(R,G,B:Byte): TColor; 
    begin 
      Result:=B Shl 16 or 
              G Shl 8  or 
              R; 
    end; 
    =========================== 
    //////////////////////////////////////////////////////////////////////////////// 
    回调函数(Callback Routine)的解释 
    MyWindowClassInfo = packed record 
    Style:UINT 
    ... 
    lpFnWndProc:Pointer 
    ... 
    end; 
    应用程序只需要将一个能处理消息的函数地址指定给MyWindowClassInfo中的lpFnWndProc字段,执行环境就知道消息需要调用的函数,于是应用程序可以把任何的函数地址指定给该字段以代表可以处理窗口消息的函数,这个函数是由执行环境来调用的,因此这种函数也被称为回调函数(Callback Routine)。 
    回调函数的机制:调用者在初始化一个对象的时候,将一些参数传递给对象,同时将一个调用者可以访问的函数地址传递给该对象,这个函数就是调用者和被调用者之间的一种通知约定,当约定的事件发生时,被调用者就会按照回调函数地址调用该函数。 
    ///////////////////////////////////////////////////////////////////////////////////////// 
    Object Inspector(对象检视器) 
    Properties页显示窗体中当前被选择部件的属性信息 
    Events页列出了当前部件可以响应的事件 
    (小窍门:Object Inspector一直可见,可将鼠标移到Object Inspector上,按动右键,以启动Object Inspector的弹出式菜单,将其设置为Stay On Top。) 
    部件的调整与对齐 
    如果要精确地表述部件的尺寸,可以在Object Inspector上,改变Left(表示部件左边缘到窗体左边框的象素点数)、Top(表示窗体上边框到部件上边缘的象素点数)、 Width(部件本身的宽度)、Height(部件本身的高度)等属性。 
     
    使四个按钮对齐。先将四个按钮选为一组:按住并向右下方拖动鼠标左键,在窗体上画出围绕四个按钮的矩形,释放左键后,被选中的按钮周边会出现暗灰色的边框。选用Edit|Align命令, 
    或选中4个按钮,出现灰色边框后,点右键,选择position,后面align…等,是不同方式的对齐,可以调整同样大小的尺寸。 
     
    锁定部件 
    选择主菜单上的Edit|Lock Controls选项 
    设置窗体的缺省按钮 
    按钮的Default属性从False改成True,即将它设为窗体的缺省按钮 
     
    OnClick事件,即按钮接收到左键单击时应用程序所作出的反应 
     
    ColorDialog1.Execute; 
    程序的第一句用Execute方法,使得ColorDialog运行它本身 
     
    Label(标签)一般放在对象的旁边,用来标记这些对象,当用户使用“Alt+关键字母”时,将自动选中它所指向的对象。方法是设置Label部件的FocusControl属性,在值段中,选用与它关联对象的对象名。  
     
    Edit、MaskEdit、Memo部件都是用作接收、显示用户输入文本的。ReadOnly在运行时间内控制对象是否可以进行Windows的操作,当此值为False时,该框内的文本就不能被复制到剪贴板上。MaxLength可以设置输入文本的长度限制。用PasswordChar属性可以按照显示隐蔽密码的方法显示用户输入文本。当一个字段被加上高亮度显示时,按键操作会将这一字段删除,替换成当前的键盘输入。这种设置为操作提供了方便,您不必每次先删除原来的文本;但也可能会导致误删文本。将AutoSelect属性设置成False,这种替代功能就被取消了。 
     
    它的EditMask属性为它提供了过滤文本的格式。点动这一属性的省略按钮,会弹出过滤编辑对话框 
     
    Memo是备注框,与以上对象不同的是,它可以接收多行文本输入。将ScrollBars设置成ssVertical,可以为它加上一个垂直的滚行条。Align属性调整该对象在窗口中的对齐情况,有alNone(无对齐指定)、alBottom(底部对齐)、alClient(全窗口显示)等可以选择;而Alignment属性则决定了文本在框中的对齐显示格式。Lines属性访问的文本被存储在一个TStrings对象中,按动它的省略按钮,可以通过对话框向它增加文本,也可以用程序对这一属性进行操作,以达到修改或增加备注文本的目的。 
     
    Combo Box(组合框) 显示可用磁盘驱动器 
    List Box(列表框) Windows打开文件操作时显示文件列表
     
    May 22

    老掉牙的算法

    LXY曾经在我大三的时候问我一道题
    关于跳马的题目,就是在一个n*n的棋盘里随机一点开始
    输出一条跳完所有点的路线并且跳过的点不能再跳

    当时写的程序老是调不成功就不了了之(唉~ 没有编程的天赋)
    后来大四学了算法,同学们都说用递归回溯
    网上也有很多现成的算法
     
    其事这个问题早在十八世纪初倍受数学家和拼图迷的注意
    也被称作骑士走棋盘,它什么时候被提出已不可考
    骑士的走法是西洋棋的走法,骑士要如何走完所有的位置?
     
    纯粹的递归回溯在维度大时相当没有效率
    一个聪明的解法由J.C. Warnsdorff在1823年提出
    简单的说,先将最难的位置走完,接下來的路就宽广了
    骑士所要走的下一步,「为下一步再选择时,所能走的步数最少的一步。」
    使用这个方法,在不使用递归回溯的情況下,可以有较高的几率找出走法(找不到走法的机会也是有的)。
     
    演算:
    FOR(m = 2; m <= 总步数; m++) [
        测试下一步可以走的八個方向,记录可停留的格个count。
        IF(count == 0) [
           都不可停留,表示无路可走,失败
        ]
        ELSE IF(count == 1) [
           下一步只有一个可能,直接记录这步
        ]
        ELSE [ 
            按照难走的路优先原则选择一条出路
            如果出路值相同,则选第一个遇到的出路。
        ]
        走最少出路的格子,记录跳马的新位置。
      ]
     
    下面是实现的程序,可以在java环境下运行:
    public class Knight {
     public boolean travel(int startX, int startY, int[][] board) {
      int[] ktmove1 = { -2, -1, 1, 2, 2, 1, -1, -2 };// 跳马走的8步
      int[] ktmove2 = { 1, 2, 2, 1, -1, -2, -2, -1 };  
      int[] nexti = new int[board.length];// 保存下一步出路的位置,最多board.length个
      int[] nextj = new int[board.length];  
      int[] exists = new int[board.length];// 记录board.length个下步的出路个数
      int x = startX;
      int y = startY;
      board[x][y] = 1;
      for (int m = 2; m <= Math.pow(board.length, 2); m++) {
       for (int k = 0; k < board.length; k++) {
        exists[k] = 0;// 初始化全为0 不可走
       }
       int count = 0;// 8方向可走的个数
       for (int k = 0; k < 8; k++) {// 试探八个方向可走性
        int tmpi = x + ktmove1[k];
        int tmpj = y + ktmove2[k];// 如果是出边界了,不可走
        if (tmpi < 0 || tmpj < 0 || tmpi > board.length - 1
          || tmpj > board.length - 1) {
         continue;
        } // 如果这个方向可走,记录下來
        if (board[tmpi][tmpj] == 0) {// 没有被走过,存入下一步的数组
         nexti[count] = tmpi;
         nextj[count] = tmpj;
         count++;// 计数索引加一
        }
       }
       int min = -1;// 记录出路最少的下一步的索引
       if (count == 0) {// 都不可走则返回
        return false;
       } else if (count == 1) {// 只有一个可走,就是第一个
        min = 0;
       } else {// 多个位置可走
        for (int l = 0; l < count; l++) {// 找出下一个位置的出路数,遍历可走的
         // 判断
         for (int k = 0; k < 8; k++) {
          int tmpi = nexti[l] + ktmove1[k];
          int tmpj = nextj[l] + ktmove2[k];
          if (tmpi < 0 || tmpj < 0 || tmpi > board.length - 1
            || tmpj > board.length - 1) {
           continue;
          }
          if (board[tmpi][tmpj] == 0) {// 下步可走则记录
           exists[l]++;
          }
         }
        }
        int tmp = exists[0];
        min = 0;
        for (int l = 1; l < count; l++) {// 从可走的方向中寻找最少出路的方向
         if (exists[l] < tmp) {
          tmp = exists[l];
          min = l;
         }
        }
       }
        x = nexti[min];// 走下一步出路最少的方向
        y = nextj[min];
        board[x][y] = m;
       }
       return true;
     }
     public static void main(String[] args) {
         int[][] board = new int[8][8];
         Knight knight = new Knight();
         if (knight.travel(0, 1, board)) {
             System.out.println("完成!");
         } else {
             System.out.println("无法走完!");
         }
      for (int i = 0; i < board.length; i++) {
         for (int j = 0; j < board[0].length; j++) {
         if (board[i][j] < 10) {
            System.out.print("  " + board[i][j]);
         } else if (board[i][j] < 100) {
             System.out.print(" " + board[i][j]);
         } else {
             System.out.print(board[i][j]);
        }
           System.out.print(" ");
       }
       System.out.println();
      }
     }
    }
     
     
    执行结果:
    完成!
      4    1    6  21  28  43  16  19 
      7  22   3  44  17  20  29  42 
      2    5  24  27  48  41  18  15
     23   8  45  40  25  56  47  30
     52  39  26  61  46  49  14  57
      9  64  53  50  55  60  31  34
     38  51  62  11  36  33  58  13
     63  10  37  54  59  12  35  32
    May 17

    软件开发:需求分析的20条法则[转]

       对商业用户来说,他们后面是成百上千个供应商,前面是成千上万个消费顾客。怎样利用软件管理错综复杂的供应商和消费顾客,如何做好精细到一个小小调料包的进、销、调、存的商品流通工作,这些都是商业企业需要信息管理系统的理由。软件开发的意义也就在于此。而弄清商业用户如此复杂需求的真面目,正是软件开发成功的关键所在。
    ---  经理:“我们要建立一套完整的商业管理软件系统,包括商品的进、销、调、存管理,是总部-门店的连锁经营模式。通过通信手段门店自动订货,供应商自动结算,卖场通过扫条码实现销售,管理人员能够随时查询门店商品销售和库存情况。另外,我们也得为政府部门提供关于商品营运的报告。”

    --  -分析员:“我已经明白这个项目的大体结构框架,这非常重要,但在制定计划之前,我们必须收集一些需求。”

    --  -经理觉得奇怪:“我不是刚告诉你我的需求了吗?”

    --  -分析员:“实际上,您只说明了整个项目的概念和目标。这些高层次的业务需求不足以提供开发的内容和时间。我需要与实际将要使用系统的业务人员进行讨论,然后才能真正明白达到业务目标所需功能和用户要求,了解清楚后,才可以发现哪些是现有组件即可实现的,哪些是需要开发的,这样可节省很多时间。”

    --  -经理:“业务人员都在招商。他们非常忙,没有时间与你们详细讨论各种细节。你能不能说明一下你们现有的系统?”

    ---  分析员尽量解释从用户处收集需求的合理性:“如果我们只是凭空猜想用户的要求,结果不会令人满意。我们只是软件开发人员,而不是采购专家、营运专家或是财务专家,我们并不真正明白您这个企业内部运营需要做些什么。我曾经尝试过,未真正明白这些问题就开始编码,结果没有人对产品满意。”

    ---  经理坚持道:“行了,行了,我们没有那么多的时间。让我来告诉您我们的需求。实际上我也很忙。请马上开始开发,并随时将你们的进展情况告诉我。”

    ---  风险躲在需求的迷雾之后

    -  --以上我们看到的是某客户项目经理与系统开发小组的分析人员讨论业务需求。在项目开发中,所有的项目风险承担者都对需求分析阶段备感兴趣。这里所指的风险承担者包括客户方面的项目负责人和用户,开发方面的需求分析人员和项目管理者。这部分工作做得到位,能开发出很优秀的软件产品,同时也会令客户满意。若处理不好,则会导致误解、挫折、障碍以及潜在的质量和业务价值上的威胁。因此可见——需求分析奠定了软件工程和项目管理的基础。

    --  -拨开需求分析的迷雾

    ---  像这样的对话经常出现在软件开发的过程中。客户项目经理的需求对分析人员来讲,像“雾里看花”般模糊并令开发者感到困惑。那么,我们就拨开雾影,分析一下需求的具体内容:

    -- -·业务需求——反映了组织机构或客户对系统、产品高层次的目标要求,通常在项目定义与范围文档中予以说明。

    --- ·用户需求——描述了用户使用产品必须要完成的任务,这在使用实例或方案脚本中予以说明。

    --- ·功能需求——定义了开发人员必须实现的软件功能,使用户利用系统能够完成他们的任务,从而满足了业务需求。

    -- -·非功能性的需求——描述了系统展现给用户的行为和执行的操作等,它包括产品必须遵从的标准、规范和约束,操作界面的具体细节和构造上的限制。

    --- ·需求分析报告——报告所说明的功能需求充分描述了软件系统所应具有的外部行为。“需求分析报告”在开发、测试、质量保证、项目管理以及相关项目功能中起着重要作用。

    --- 前面提到的客户项目经理通常阐明产品的高层次概念和主要业务内容,为后继工作建立了一个指导性的框架。其他任何说明都应遵循“业务需求”的规定,然而“业务需求”并不能为开发人员提供开发所需的许多细节说明。

    --- 下一层次需求——用户需求,必须从使用产品的用户处收集。因此,这些用户构成了另一种软件客户,他们清楚要使用该产品完成什么任务和一些非功能性的特性需求。例如:程序的易用性、健壮性和可靠性,而这些特性将会使用户很好地接受具有该特点的软件产品。

    --- 经理层有时试图代替实际用户说话,但通常他们无法准确说明“用户需求”。用户需求来自产品的真正使用者,必须让实际用户参与到收集需求的过程中。如果不这样做,产品很可能会因缺乏足够的信息而遗留不少隐患。

    --- 在实际需求分析过程中,以上两种客户可能都觉得没有时间与需求分析人员讨论,有时客户还希望分析人员无须讨论和编写需求说明就能说出用户的需求。除非遇到的需求极为简单;否则不能这样做。如果您的组织希望软件成功,那么必须要花上数天时间来消除需求中模糊不清的地方和一些使开发者感到困惑的方面。

    --- 优秀的软件产品建立在优秀的需求基础之上,而优秀的需求源于客户与开发人员之间有效的交流和合作。只有双方参与者都明白自己需要什么、成功的合作需要什么时,才能建立起一种良好的合作关系。

    --- 由于项目的压力与日俱增,所有项目风险承担者有着一个共同目标,那就是大家都想开发出一个既能实现商业价值又能满足用户要求,还能使开发者感到满足的优秀软件产品。

    -- -客户的需求观

    -- -客户与开发人员交流需要好的方法。下面建议20条法则,客户和开发人员可以通过评审以下内容并达成共识。如果遇到分歧,将通过协商达成对各自义务的相互理解,以便减少以后的磨擦(如一方要求而另一方不愿意或不能够满足要求)。

    --- 1、 分析人员要使用符合客户语言习惯的表达

    --- 需求讨论集中于业务需求和任务,因此要使用术语。客户应将有关术语(例如:采价、印花商品等采购术语)教给分析人员,而客户不一定要懂得计算机行业的术语。

    --- 2、分析人员要了解客户的业务及目标

    --- 只有分析人员更好地了解客户的业务,才能使产品更好地满足需要。这将有助于开发人员设计出真正满足客户需要并达到期望的优秀软件。为帮助开发和分析人员,客户可以考虑邀请他们观察自己的工作流程。如果是切换新系统,那么开发和分析人员应使用一下目前的旧系统,有利于他们明白目前系统是怎样工作的,其流程情况以及可供改进之处。s

    --- 3、 分析人员必须编写软件需求报告

    --- 分析人员应将从客户那里获得的所有信息进行整理,以区分业务需求及规范、功能需求、质量目标、解决方法和其他信息。通过这些分析,客户就能得到一份“需求分析报告”,此份报告使开发人员和客户之间针对要开发的产品内容达成协议。报告应以一种客户认为易于翻阅和理解的方式组织编写。客户要评审此报告,以确保报告内容准确完整地表达其需求。一份高质量的“需求分析报告”有助于开发人员开发出真正需要的产品。

    --- 4、 要求得到需求工作结果的解释说明

    --- 分析人员可能采用了多种图表作为文字性“需求分析报告”的补充说明,因为工作图表能很清晰地描述出系统行为的某些方面,所以报告中各种图表有着极高的价值;虽然它们不太难于理解,但是客户可能对此并不熟悉,因此客户可以要求分析人员解释说明每个图表的作用、符号的意义和需求开发工作的结果,以及怎样检查图表有无错误及不一致等。

    --- 5、 开发人员要尊重客户的意见

    --- 如果用户与开发人员之间不能相互理解,那关于需求的讨论将会有障碍。共同合作能使大家“兼听则明”。参与需求开发过程的客户有权要求开发人员尊重他们并珍惜他们为项目成功所付出的时间,同样,客户也应对开发人员为项目成功这一共同目标所做出的努力表示尊重。

    --- 6、 开发人员要对需求及产品实施提出建议和解决方案

    --- 通常客户所说的“需求”已经是一种实际可行的实施方案,分析人员应尽力从这些解决方法中了解真正的业务需求,同时还应找出已有系统与当前业务不符之处,以确保产品不会无效或低效;在彻底弄清业务领域内的事情后,分析人员就能提出相当好的改进方法,有经验且有创造力的分析人员还能提出增加一些用户没有发现的很有价值的系统特性。

    --- 7、 描述产品使用特性

    --- 客户可以要求分析人员在实现功能需求的同时还注意软件的易用性,因为这些易用特性或质量属性能使客户更准确、高效地完成任务。例如:客户有时要求产品要“界面友好”或“健壮”或“高效率”,但对于开发人员来讲,太主观了并无实用价值。正确的做法是,分析人员通过询问和调查了解客户所要的“友好、健壮、高效所包含的具体特性,具体分析哪些特性对哪些特性有负面影响,在性能代价和所提出解决方案的预期利益之间做出权衡,以确保做出合理的取舍。

    --- 8、 允许重用已有的软件组件

    --- 需求通常有一定灵活性,分析人员可能发现已有的某个软件组件与客户描述的需求很相符,在这种情况下,分析人员应提供一些修改需求的选择以便开发人员能够降低新系统的开发成本和节省时间,而不必严格按原有的需求说明开发。所以说,如果想在产品中使用一些已有的商业常用组件,而它们并不完全适合您所需的特性,这时一定程度上的需求灵活性就显得极为重要了。

    --- 9、 要求对变更的代价提供真实可靠的评估

    --- 有时,人们面临更好、也更昂贵的方案时,会做出不同的选择。而这时,对需求变更的影响进行评估从而对业务决策提供帮助,是十分必要的。所以,客户有权利要求开发人员通过分析给出一个真实可信的评估,包括影响、成本和得失等。开发人员不能由于不想实施变更而随意夸大评估成本。

    --- 10、 获得满足客户功能和质量要求的系统

    --- 每个人都希望项目成功,但这不仅要求客户要清晰地告知开发人员关于系统“做什么”所需的所有信息,而且还要求开发人员能通过交流了解清楚取舍与限制,一定要明确说明您的假设和潜在的期望,否则,开发人员开发出的产品很可能无法让您满意。

    --- 11、 给分析人员讲解您的业务

    --- 分析人员要依靠客户讲解业务概念及术语,但客户不能指望分析人员会成为该领域的专家,而只能让他们明白您的问题和目标;不要期望分析人员能把握客户业务的细微潜在之处,他们可能不知道那些对于客户来说理所当然的“常识”。

    --- 12、 抽出时间清楚地说明并完善需求

    --- 客户很忙,但无论如何客户有必要抽出时间参与“头脑高峰会议”的讨论,接受采访或其他获取需求的活动。有些分析人员可能先明白了您的观点,而过后发现还需要您的讲解,这时请耐心对待一些需求和需求的精化工作过程中的反复,因为它是人们交流中很自然的现象,何况这对软件产品的成功极为重要。

    --- 13、 准确而详细地说明需求

    --- 编写一份清晰、准确的需求文档是很困难的。由于处理细节问题不但烦人而且耗时,因此很容易留下模糊不清的需求。但是在开发过程中,必须解决这种模糊性和不准确性,而客户恰恰是为解决这些问题作出决定的最佳人选,否则,就只好靠开发人员去正确猜测了。

    --- 在需求分析中暂时加上“待定”标志是个方法。用该标志可指明哪些是需要进一步讨论、分析或增加信息的地方,有时也可能因为某个特殊需求难以解决或没有人愿意处理它而标注上“待定”。客户要尽量将每项需求的内容都阐述清楚,以便分析人员能准确地将它们写进“软件需求报告”中去。如果客户一时不能准确表达,通常就要求用原型技术,通过原型开发,客户可以同开发人员一起反复修改,不断完善需求定义。

    --- 14、 及时作出决定

    --- 分析人员会要求客户作出一些选择和决定,这些决定包括来自多个用户提出的处理方法或在质量特性冲突和信息准确度中选择折衷方案等。有权作出决定的客户必须积极地对待这一切,尽快做处理,做决定,因为开发人员通常只有等客户做出决定才能行动,而这种等待会延误项目的进展。

    --- 15、 尊重开发人员的需求可行性及成本评估

    --- 所有的软件功能都有其成本。客户所希望的某些产品特性可能在技术上行不通,或者实现它要付出极高的代价,而某些需求试图达到在操作环境中不可能达到的性能,或试图得到一些根本得不到的数据。开发人员会对此作出负面的评价,客户应该尊重他们的意见。

    --- 16、 划分需求的优先级

    --- 绝大多数项目没有足够的时间或资源实现功能性的每个细节。决定哪些特性是必要的,哪些是重要的,是需求开发的主要部分,这只能由客户负责设定需求优先级,因为开发者不可能按照客户的观点决定需求优先级;开发人员将为您确定优先级提供有关每个需求的花费和风险的信息。

    --- 在时间和资源限制下,关于所需特性能否完成或完成多少应尊重开发人员的意见。尽管没有人愿意看到自己所希望的需求在项目中未被实现,但毕竟是要面对现实,业务决策有时不得不依据优先级来缩小项目范围或延长工期,或增加资源,或在质量上寻找折衷。

    --- 17、 评审需求文档和原型

    --- 客户评审需求文档,是给分析人员带来反馈信息的一个机会。如果客户认为编写的“需求分析报告”不够准确,就有必要尽早告知分析人员并为改进提供建议。

    --- 更好的办法是先为产品开发一个原型。这样客户就能提供更有价值的反馈信息给开发人员,使他们更好地理解您的需求;原型并非是一个实际应用产品,但开发人员能将其转化、扩充成功能齐全的系统。

    --- 18、 需求变更要立即联系

    --- 不断的需求变更,会给在预定计划内完成的质量产品带来严重的不利影响。变更是不可避免的,但在开发周期中,变更越在晚期出现,其影响越大;变更不仅会导致代价极高的返工,而且工期将被延误,特别是在大体结构已完成后又需要增加新特性时。所以,一旦客户发现需要变更需求时,请立即通知分析人员。

    --- 19、 遵照开发小组处理需求变更的过程

    --- 为将变更带来的负面影响减少到最低限度,所有参与者必须遵照项目变更控制过程。这要求不放弃所有提出的变更,对每项要求的变更进行分析、综合考虑,最后做出合适的决策,以确定应将哪些变更引入项目中。

    --- 20、 尊重开发人员采用的需求分析过程

    --- 软件开发中最具挑战性的莫过于收集需求并确定其正确性,分析人员采用的方法有其合理性。也许客户认为收集需求的过程不太划算,但请相信花在需求开发上的时间是非常有价值的;如果您理解并支持分析人员为收集、编写需求文档和确保其质量所采用的技术,那么整个过程将会更为顺利。

    --- “需求确认”意味着什么

    --- 在“需求分析报告”上签字确认,通常被认为是客户同意需求分析的标志行为,然而实际操作中,客户往往把“签字”看作是毫无意义的事情。“他们要我在需求文档的最后一行下面签名,于是我就签了,否则这些开发人员不开始编码。”

    --- 这种态度将带来麻烦,譬如客户想更改需求或对产品不满时就会说:“不错,我是在需求分析报告上签了字,但我并没有时间去读完所有的内容,我是相信你们的,是你们非让我签字的。”

    --- 同样问题也会发生在仅把“签字确认”看作是完成任务的分析人员身上,一旦有需求变更出现,他便指着“需求分析报告”说:“您已经在需求上签字了,所以这些就是我们所开发的,如果您想要别的什么,您应早些告诉我们。”

    --- 这两种态度都是不对的。因为不可能在项目的早期就了解所有的需求,而且毫无疑问地需求将会出现变更,在“需求分析报告”上签字确认是终止需求分析过程的正确方法,所以我们必须明白签字意味着什么。

    --- 对“需求分析报告”的签名是建立在一个需求协议的基线上,因此我们对签名应该这样理解:“我同意这份需求文档表述了我们对项目软件需求的了解,进一步的变更可在此基线上通过项目定义的变更过程来进行。我知道变更可能会使我们重新协商成本、资源和项目阶段任务等事宜。”对需求分析达成一定的共识会使双方易于忍受将来的摩擦,这些摩擦来源于项目的改进和需求的误差或市场和业务的新要求等。

    --- 需求确认将迷雾拨散,显现需求的真面目,给初步的需求开发工作画上了双方都明确的句号,并有助于形成一个持续良好的客户与开发人员的关系,为项目的成功奠定了坚实的基础
    February 23

    测测你的杀毒软件到底多能干

    编者按:鸣谢欧洲计算机防病毒协会提供本测试病毒代码。本代码尽管测试,无任何危险。测试代码:

      ------------------请复制分割线中间的代码到文本中保存----------------

      X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

      ------------------请复制分割线中间的代码到文本中保存----------------

      测试方法:

      1.鼠标右键点击桌面空白处,创建一个“文本文档”。(什么,还不会建?我倒)

      2.将下面这段测试代码复制到“文本”里,保存,然后可以直接右键点击这个文本,用杀毒软件扫描。也可以等一会,如果你的杀毒软件还行,会自动报毒并将该文本删除,那就可以初步放心了。

            X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

      该段代码是欧洲计算机防病毒协会开发的一种病毒代码,其中的特征码已经包含在各种杀毒软件的病毒代码库里,所以可以用做测试病毒扫描引擎。

      测试等级:

      特等:复制完代码后便提示内存有病毒

      优等:刚保存完就提示病毒(或者直接删除)

      中等:保存后几秒提示病毒(或者直接删除)

      下等:需自己启动病毒扫描查杀才提示病毒(或者直接删除)

      劣等:无论怎么扫描都无法提示病毒(或者直接删除)

      最后说明:

      请大家测试完后在评论里说下自己用的什么杀毒软件以及排什么等级,那这篇文就好似中文杀毒软件评测文章了,也可以惠及更多的网友了。
    December 20

    Map-电子地图

    最近在调研国内外电子地图网站:

    很多的电子地图网站都是采用AJAX技术实现鼠标拖动浏览操作栅格数据,支持放大、缩小、查询、定位等功能

    1.  神州龙地图网http://www.668map.com/shmap/

    特色:功能分类较多,使用applet作客户端表现层,将数据加载到客户端,在客户端计算查询速度快,动态显示效果好

    2.  台湾电子地图网http://www.map.com.tw/Map_Engine/

    特色:公交查询信息详尽明了还有图利,速度也快,还可查找附近车站,并可按车站检索经过的公车

    3.  Map666数字电子地图http://www.map666.com/new/

    特色:mapbar的引擎,查询与结果放在tab中,结果显示分页

     

    4.  百度地图 http://map.baidu.com/

    特色:使用mapbar的引擎

    5.  搜狗-图行天下 http://www.go2map.com/

    特色:查询采用地图上浮动面板,地图显示范围较大

    6.  Mapbac-Google地图

    特色:这个不是google maps

    7.  图迈天下-广州市电子地图http://www.toumai.cn/bigmap/

    特色:浮动收缩的查询结果

    8 .e都市——深圳电子地图 http://sz.edushi.com/

    特色:3D地图表现让人耳目一新,点击标注即可提示用户查询,并提供相应的辅助

    9Mapabc中国地图http://www.mapabc.com/

    10.日本停车场地图http://www.s-park.jp/

    特色:在缩小到一定程度才显示显示区停车场内容,图标丰富,信息多样,无须点击查询按钮即可查询区域内停车场,有单独的图例说明页面

    11.韩国电子地图http://escortmap.co.kr/

    特色:全部采用静态网页,切成块放入表格中,貌似很不灵活

    August 21

    常用数据库JDBC连接写法

    1. MySQL(http://www.mysql.com)mysql-connector-java-2.0.14-bin.jar
    Class.forName( "org.gjt.mm.mysql.Driver" );
    cn = DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd );

    2. PostgreSQL(http://www.de.postgresql.org)pgjdbc2.jar
    Class.forName( "org.postgresql.Driver" );
    cn = DriverManager.getConnection( "jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd );

    3. Oracle(http://www.oracle.com/ip/deploy/database/oracle9i/)classes12.zip
    Class.forName( "oracle.jdbc.driver.OracleDriver" );
    cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd );

    4. Sybase(http://jtds.sourceforge.net)jconn2.jar
    Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" );
    cn = DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd );
    //(Default-Username/Password: "dba"/"sql")

    5. Microsoft SQLServer(http://jtds.sourceforge.net)
    Class.forName( "net.sourceforge.jtds.jdbc.Driver" );
    cn = DriverManager.getConnection( "jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master", sUsr, sPwd );

    6. Microsoft SQLServer(http://www.microsoft.com)
    Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" );
    cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;databaseName=master", sUsr, sPwd );

    7. ODBC
    Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
    Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );

    8.DB2
    Class.forName("com.ibm.db2.jdbc.net.DB2Driver");
    String url="jdbc:db2://192.9.200.108:6789/SAMPLE"
    cn = DriverManager.getConnection( url, sUsr, sPwd );
     
    9、access数据库直连用ODBC的

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
    String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Test.mdb");
    Connection conn = DriverManager.getConnection(url,"","");
    Statement stmtNew=conn.createStatement() ;

     

    10、Informix数据库

    Class.forName("com.informix.jdbc.IfxDriver").newInstance();
    String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
    user=testuser;password=testpassword"; //myDB为数据库名
    Connection conn= DriverManager.getConnection(url);

    May 24

    自动产生式

    自动产生式(quine)就是要写一个程序,这个程序就就是简单的描述自己,比如,如果您写了一个java程序,编译它产生一个class文件,然后将java文件删除,执行class文件就可以将java文件的所有内容打印出来,即还原出来
     这个问题的提出和解法是在良格格的blog上看到的,很有意思。http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/Quine.htm
    April 28

    关于sql注入问题的心得

    首先我们来看看字符串解释执行如何影响SQL和JDBC。
    假设我们要以用户名字和密码为条件搜索数据库中的用户,下面的Servlet代码看起来没有什么问题,但事实上它却是危险的。
    .....
    String user = request.getAttribute("username");
    String pass = request.getAttribute("password");
    String query = "SELECT id FROM users WHERE
    username="+user+" AND password="+pass;
    Statement stmt = con.createStatement(query);
    ResultSet rs = con.executeQuery(query);
    if (rs.next())
    {
    // 登录成功
    int id = rs.getInt(1);
    ...
    }
    else
    {
    // 登录失败
    ...
    }
    ...
    如果用户输入的查询条件中,用户名字等于“fred”,密码等于“something”,则系统执行的sql查询实际上是:
    SELECT id FROM users
    WHERE username='fred' AND password='something'
    这个查询能够正确地对用户名字和密码进行检查。但是,如果用户输入的查询条件中,名字等于“ fred' or'a'='a ”,密码等于“something”,此时系统执行的查询变成了:
    SELECT id FROM users
    WHERE username='fred' OR 'a'='a' AND password='something'
    上面的查询可以正确的执行,并且等效于SELECT id FROM users,所以一定是登陆成功的,并且使用的是第一行用户的id
    这个漏洞就是源于 'or'1'='1 的漏洞,下面我们再来看看下面的Servlet代码:
    ...
    String user = request.getAttribute("username");
    String pass = request.getAttribute("password");
    String query = "SELECT id FROM users WHERE
    username="+user;
    Statement stmt = con.createStatement(query);
    ResultSet rs = con.executeQuery(query);
    if (rs.next())
    {
        if(pass.equals(rs.getString("password"))){
          // 登录成功
           int id = rs.getInt(1);
        }else{
            // 登录失败
            ...
        }
    ...
    }
    else
    {
    // 登录失败
    ...
    }
    ...
        这段代码是根据用户输入的用户名来检索数据库,选出对应用户的密码再来和用户输入的密码比较,对这段程序用用户名“ fred' or'a'='a ”,密码“something”来攻击几乎不可能,因为你不知道选出来的用户密码是多少,所以看起来这种策略更加高明一些。
        我正在做一个**网的web系统的测试的时候发现就是这样的策略,其实费点心思一样可以入侵。
    刚开始我使用正常用户名,密码时,系统提示用户名或密码错误
    改用“‘ ”加在用户名里,发现系统提示数据库查询错误
    哈哈,显然没有检查非法字符,这种系统提示对安全来说是比较致命的。
    用第一种方法“ fred' or'a'='a ”的用户名试了试,系统又提示用户名或密码错误,说明这段sql注入成功执行了。
    下面来看使用用户名“ ' or password='1 ”密码“1”,又是数据库查询错误,问题在于我并不知道这个系统使用的密码字段的名称,所以执行的时候出了column not found的错误,下面我又继续使用下列用户名密码:
    用户名“ ' or pass='1 ”  密码“1”
    用户名“ ' or pwd='1 ”   密码“1”
    用户名“ ' or psd='1 ”   密码“1”
    用户名“ ' or user_pwd='1 ” 密码“1”
    用户名“ ' or user_psd='1 ” 密码“1”
    用户名“ ' or user_pass='1 ”密码“1”
    用户名“ ' or user_password='1 ”密码“1”
    用户名“ ' or 网站名称缩写_pwd='1 ”密码“1”
    用户名“ ' or userpwd='1 ”密码“1”
    用户名“ ' or userpass='1 ”密码“1”
    用户名“ ' or userpassword='1 ”密码“1”
     唉~~~~没办法,想入侵是需要耐心的,功夫不负有心人,终于发现上面有个用户名让系统提示用户名和密码错误,根据他的命名规则我相继知道了他们数据里其他的一些字段(这些发现只是好奇的尝试),知道了密码字段还抛错误,说明数据库表里没有人用1这个密码(都还是有点安全意识的)。
    我想尝试别的常见密码的时候发现登陆界面对用户名有长度限制,顶多能写出2位密码,f***~~~~~~~~~~。
    把页面down下来,修改text的属性,把action和验证码里用的相对地址改称该网站的绝对地址,在自己的电脑上打开修改的界面,嘿嘿用户名多长都可以了。如果系统管理员使用了不安全的密码,我们不需要知道用户名就能进入系统管理界面。
    下面又是需要耐心的时候了,我就这样试了好几个比较容易此想到的密码就进去了,
    然后可以对网站信息做添加,修改,删除了
    唉,我不是cracker,也不是hacker,只是一个对网络安全了解一点皮毛的本科生,就这个问题发了封email给管理员,爽啊~~~~~~~
    可以看出,上面两个查询无法正确地对用户名字和密码进行检查。下面的的代码要安全得多,它从根本上防止了用户修改SQL命令逃避检查。
    ...
    String user = request.getAttribute("username");
    String pass = request.getAttribute("password");
    String query = "SELECT id FROM users
    WHERE username=? AND password=?";
    PreparedStatement stmt = con.prepareStatement(query);
    stmt.setString(1, user);
    stmt.setString(2, pass);
    ResultSet rs = stmt.executeQuery();
    ...
     
    April 18

    一篇关于读研的文章

    发信人: chinabingo (ice), 信区: Computer
    标 题: 谈谈我对攻读计算机研究生的看法[转自TIANYA\CSDN]
    发信站: 虎踞龙蟠 (Thu Dec 23 10:52:23 2004), 转信

    回复CSDN和KAOYAN诸位网友的几点看法,(为避免吵架,郑重声明,本人不是高手
    ,只是有感而发的一点个人陋见,欢迎指正,事先感谢):

      就我自己的理解,谈谈我对读研和软件学院的看法,不妥之处一笑了之即可。


      如果你有实际开发工作经验,感觉自己的水平和实力进入了一个高原期,迫切
    需要从理论上提高,那么计算机学院是唯一选择。因为计算机学院才能让你在理论
    上更上一层楼。软件学院从教学计划上就没有把你往这方面带。当然能不能更上一
    层楼最终还是完全取决于你自己。需要特别说明的是,工作经验并不一定等于开发
    经验,我见过很多工作2-3年的人,但是没有一点开发经验。

      你说:“他们都有很强的开发能力,只是不太喜欢读书,也只是希望混个学历对
    今后在岗位上晋升有好处”,我可以向你保证,你所说的人绝对不是开发能力很强
    的人。因为,1)高手不可能不喜欢读书;2)高手不可能想去混一个学历;3)高手
    不可能认为晋升是因为学历的原因。

      还需要说明的是,考计算机的人未必个个都是高手,严格来说,大部分都不会
    编程序。也就是说,庸庸碌碌之辈仍然占绝大多数。研究生毕业的师兄只拿2500元
    左右的比比皆是,所以不要寄希望于拿一张研究生文凭出去赚高薪。但是,对于有
    实际开发工作经验的人,要想自己在3年之中有一个真正的提高的话,计算机学院提
    供了广阔的平台。就我所知,每一个月拿2万以上的也有(上海育碧,图形特效算法
    设计)。所以,同为研究生毕业,能力的差距是极大的。所以,不要去问“研究生
    毕业能拿多少?”,要问“像我这种水平的人,研究生毕业能拿多少钱?”这样人
    家才能够准确地回答你。

      所谓“有实际开发工作经验”是指你目前已经具备下列能力:1)你已经认为C
    ++和汇编语言都是很简单的语言,并能够自如地运用;2)你能够在30分钟之内想到
    正确的五子棋AI算法设计思路和方向;3)你完全理解STL为什么这么重要;4)你能
    够独立地解决所有的编译与链接问题,哪怕你从来没有遇到的问题,你也不需要询
    问任何人;5)英文网站是你的首要信息来源;6)能够读懂英语写成的国际标准,
    比如NTFS磁盘格式标准。7)你经常站在集合论的角度思考算法问题;8)能够理解
    一个简单的驱动程序,能够理解一个简单3D交互程序;9)你能够认识到线性代数和
    概率论在实际编程工作中的极端重要性;10)你完全理解COM的设计思想,尤其能够
    理解COM为什么要设计成这样;11)当我说到虚函数的重要作用时,你不会急着去找
    书来翻;12)你能够说出C++为什么比其他语言优秀的理由,记住这种理由应该来自
    于你的开发体会,而不是因为其他人都这么说。此外还有很多判断标准,但如果你
    同时具备5条以上,可以认为你已经具备相应的开发经验了。在这种状态下读研,你
    将取得读研效益的最大值。

    读研最重要的是要明白你自己要干什么,不能等导师来告诉你你应该干什么。
    研究生的优势在于理论功底深厚,思维具有穿透力,当然编程能力首先要过关,不
    要读完研究生还不知道MFC程序的WinMain函数在哪里。所以,研究生期间,你一定
    要做有理论深度的算法设计,比如大规模数据的搜索算法,性能是首要考虑因素,
    不要奢望SQL函数能够帮你解决问题,所有的问题你都必须自己解决,你必须解决内
    外存交换的性能瓶颈。再比如极品飞车的3D场景生成,图形变换,碰撞检测,物性
    模拟,纹理映射,灯光模型等等,这些都是可以保证你能拿到2万以上月薪的技术。
    如果你认为这些东西太难,不可能做得出来的话,那么你就不适合读研。真的,要
    是你认为读研之后还是要去搞一般的程序设计,如信息管理系统之类的软件,那么
    你读研的价值就完全不会得到体现,因为这些工作根本就不需要读研。

      软件学院宣称培养软件开发人才,恕我直言,我从来没有看见那个高手是培训
    成功的。成为软件开发高手的路只有一条:自学!软件开发中需要大量的编程实践
    和独立思考,只有在此过程中,你才能够逐步成长起来。软件学院宣称培养软件项
    目经理,这更是搞笑,在某种意义上这是欺骗行为。学院里面能够培养出软件开发
    经理更是十足的谎言,软件项目经理必须,或者说更强调从战争中学会战争。没有
    实践经验的项目经理就是绣花枕头一个。

      实话实说,软件学院就是一个蒙钱的机构,公关工作做得很好,善于打广告,
    而且都是打着高薪的幌子,就如同外面的什么北大青鸟培训班一样。两个字:蒙钱
    !四个字:还是蒙钱!

      总之一句话,如果你只想成为软件开发高手(比如认为会编驱动程序或杀毒软
    件就是高手的那种),建议工作,不要考研;完全没有工作经验的,也不建议考研
    ,你进来了只有瞎混一通。如果你有上述工作经验且想成为高级软件工程师(能够
    独立理解并设计出快速傅立叶变换算法的那种软件工程师)的话,那么强烈建议考
    研。考研让你有3年放松思考的机会,也有3年让你思想和技术积累沉淀的机会。非
    常难得的机会。不考研的话,这种机会就是一种奢侈,可望而不可即的那么一种奢
    侈。

      所以,不管你是哪一种情况,都不建议考软件学院。除非你是女生,把能够成
    为一个研究生当着一生最大满足的那种女生。

    )关于读书的机会成本问题。读研的机会成本的确是很高。任何人都可以简单
    地计算出来。所以,我也不赞成所有的人都去读研。读研只适合那些痛感数学在编
    程中的极端重要性的人。如果对理论工具和理论思维的极端重要性没有切肤的认识
    ,那么读研的价值几乎为0;读研的好处在于:A,把你自己放在一个学术和工程的
    交叉点上;B,让你具备了进入微软等世界顶级软件研发机构的可能性;记住只是可
    能性。但是不读研这种可能性为0;C,如前所述,如果没有读研的机会,你也就没
    有静下心来好好钻研几年理论的机会;一边工作拿高薪,一边深入地学习各种理论
    ,诸位认为这可能吗?我反正认为不可能,我觉得学习钻研理论最需要的就是一个
    长期安静独处的环境,一边工作一边读书是不可能有这样的环境的,你会觉得每天
    都在疲于奔命。而读研正好可以提供这样一个环境。我同时还反对整天跟着导师的
    屁股后面跑,这样会浪费很多时间。读计算机的研究生,主要依靠自己去查阅最新
    文献,自己去研读文献,和导师的口头交流一个月一次就足够了,前提还需要导师
    的水平足够牛。如果导师的水平不牛,这也没关系,不理他就是了,自己做好自己
    的事情即可。

      2)关于研究生教学质量问题。坦白地说,全国都是“洪桐县中无好人”,尤其
    在计算科学领域,大牛极少。那为什么还要去读研?大哉问!把读研的收获寄托在
    名校或名师的名我认为气上,是注定要失败的。读研全靠自学,研究生之间的差距
    全部体现在自学能力上面。又有人问,既然是自学,为什么非要读研?回答是:因
    为读研就是为你买一份保险,就是买一份你自学三年之后不会失业的保险。这份保
    险主要是一种心理上的后盾,让你在自学过程中经得起诱惑,能够从容镇定地去追
    寻计算机理论发展的坚实足迹,从欧拉,费马,高斯,康托,图灵等巨匠那里寻找
    方法论的珠宝。倘若没有这份保证,你在家里面自学3个月,保证你会被失业的压力
    压得喘不过气来,何谈安心学习?

      3)关于实战经验与理论学习的优劣问题。这没有定论,如前所述,管理信息系
    统,设备驱动开发,工具软件开发,软件病毒剖析等等这些工作不太需要创造性,
    需要的是耐心和经验,需要的是对既有规范的准确理解,这类开发工作最适合在实
    战中提高,理论学习没什么作用。但是在人工智能,模式识别,图像压缩,虚拟现
    实,巨量数据检索,自然语言理解,计算机图形学等等领域,理论学习就占据着绝
    对的统治地位!这些领域的突破对人类的生活的影响是极其巨大而深刻的。某些领
    域处于一个极其快速发展的态势之中,比如计算机图形学,相信诸君能够从众多3D
    游戏的灿烂辉煌中体认到我的这种说法。在这些领域,如果没有扎实的理论功底,
    一切都是那么遥远,不管你花了多少时间在编程上面。

      4)关于高级研发人员的知识结构问题。首先声明,我不是一个纯粹理论激进分
    子,即认为除了理论之外,一切都不重要。我认为,纯熟的编程技能是最基本但也
    是最必不可少的技能。没有这个基础,一切计算机理论就是空谈(研究图灵可计算
    性理论的研究者除外)。有了这个基础之后,下列理论学习方向必须重点突破:

    终于有人发帖了,
    不可以连续回复三次以上,
    还有一段补上,
    =================================================================
    1,科学哲学。这是核心中的核心!可惜国内不开这门课。不但不开课,而且还
    作为批判对象来引用,实在是遗憾至极!这是一门教你如何“钓鱼”的学科,在一
    切科学研究中居于最核心的地位。它是古今科研方法和思维方法的集大成者,很难
    想象一个成熟的研究者没有一套自己的方法论体系。科学哲学最需要的是领会与总
    结,它的思想与启示会伴随我们的一生。

      2,康托集合论,矩阵方法,离散结构,图论方法,群论方法之间的紧密关系。
    最重要的认识这些理论对实践的重要启示和方法引导。我始终认为,如果你学了一
    门理论之后,却不知道这门理论有什么作用,那么你的理论就白学了,你什么东西
    都没有捞着。所以,学习任何理论之前,先问自己:它有什么用?在哪里用?如何
    用?带着这些问题去学习理论,你才会真正地学到东西。用这三个问题去问你的理
    论课老师,他的回答就是判断其实际水平的最佳标准。

      3,思维要有极强的穿透力,学会看透文献作者没有写出来的动机。绝大部分大
    师都有隐瞒自己最具有方法论启示意义的思考环节的习惯。牛顿和华罗庚先生都有
    这个坏习惯。这让大家认为他们是天才,因为很多问题他想到了,我们想不到。但
    是为什么他们能想到,我们想不到?他们是怎样想到的?没有人告诉我们牛顿发现
    万有引力定律时的思考过程,当然,牛顿可以慷慨地把他的思考结果告诉我们,但
    是,他那可以点石成金的“金手指”却没有教给我们。我们的任务就是要培养透过
    文章看穿作者背后意图和动机的能力,在这方面,台湾的侯捷和美国的Donbox是绝
    佳典范。这两只老狐狸(呵呵,是爱称)凭着其猎犬一般的嗅觉,抽丝剥茧,一个
    把COM背后的幕后设计动机揭开并暴露到了光天化日之下,另一个把MFC的宏观架构
    做了一次完美的外科手术。其非凡的思维穿透力令人惊叹。

      4,英语。英语本身不重要,但是用英语写成的文献就极其重要了。所以,专门
    把英语作为一个重头戏列出来。大家不要相信英语无用论的鬼话。对于搞计算机的
    而言,英语就是你的母语!

      5,其它的具体理论还有很多,但是都不如这三个方面重要,因为我觉得这三个
    方面是最具有根本性,全局性的能力培养环节。需要指出的是,很多高深理论对你
    的工作是无意义的,当心时间陷进去。一定要把效率最高的时间段用在最具有决定
    性意义的理论学习上。

      5)关于读研之后的出路是否光明的问题。我们应该承认,读研之后,你的工作
    机会不是变多了,而是变少了。而且越是高手,他的工作机会和工作范围就越少。
    这是因为,越是搞前沿研发的公司,其数量越少,在这个圈子的人也就越少。你找
    工作的范围就越小,试问:如果微软的OS设计专家出来找工作,能够让他选择的公
    司能有几家?但是,这种公司数量的减少是以工资待遇的急剧上升为补偿的,同时
    ,你在工作中所受到的充分尊重也是在一般公司中体会不到的。所以不要担心学了
    高科技用不上,呵呵,你只会越来越感觉自己学的不够用。相信接到过猎头公司电
    话的人会体会得到。真正的高手从来就不会担心工作的问题,也从来不会到人才市
    场上去找工作。既然选择了理论深入,那么就应该把眼光放得更远。
    April 05

    简简单单使用(java)来加密

    //des 消息加密的使用
    import java.security.*;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.Cipher;
    import com.sun.crypto.provider.SunJCE;
    public class DES {
     /**
      * @param args
      */
     public static void main(String[] args) {
       try{
                 SunJCE jce=new SunJCE();
                 Security.addProvider(jce);
                 KeyGenerator keygen = KeyGenerator.getInstance("DES");
                 SecretKey desKey= keygen.generateKey();
                 Cipher desCipher =Cipher.getInstance("DES");
                 desCipher.init(Cipher.ENCRYPT_MODE,desKey);
                 byte[]clearText="hello world .".getBytes();
                 System.out.println("clearText:"+new String(clearText));
                 byte[] cipherText =desCipher.doFinal(clearText);
                 System.out.println("cipherText:"+new String(cipherText));
                
                 desCipher.init(Cipher.DECRYPT_MODE,desKey);
                 byte[] recoveredText = desCipher.doFinal(cipherText);
                    System.out.println("recoveredText:"+new String(recoveredText));
             }catch(GeneralSecurityException e){
               System.out.println(""+e.getMessage());
             }
     }
     
    }