kenlistian

勤学多思

  IT博客 :: 首页 :: 新随笔 ::  :: 聚合  :: 管理 ::
  412 随笔 :: 0 文章 :: 23 评论 :: 0 Trackbacks

#

在cbuilder中,其实调用soap倒是很简单,只是不知道能否和其他语言通用。说是可以跨语言,但是没有做过。

预备:

web services控件的说明如下:

● thttprio:通过http和soap数据包调用远程web services;
● toptosoapdomconvert:将请求参数打包成soap,并且解析soap响应数据包;
● thttpeqresp:通过wininet.dll传送http请求或接收http响应;
● thttpsoapdispatcher:拦截http请求,并把请求分派给thttpsoapcppinvoker;
● thttpsoapcppinvoker:根据请求调用正确的web services;
● twsdlhtmlpublish:自动产生描述web servicse的服务信息以及wsdl内容。

 

下面做了一个例子检测一下能否调用对数据库的操作。

1.服务端:

在project立即建立一个soap服务端程序,加入datamodual,

加入adoconnection,如图:

在接口类中写一个接口方法:如下:


/*************************************************
  操作数据库,返回对数据库的操作处理
*/
string ttest6impl::do1(string s)
{
   if (dm1 == null)
   {
      dm1 = new tdm1(null);
   }
   dm1->adoquery->close();
   dm1->adoquery->sql->clear();
   dm1->adoquery->sql->text = "select * from workno where workno ='"+ s + "'";
   dm1->adoquery->open();
   if (!dm1->adoquery->isempty())
   {
     return dm1->adoquery->fieldbyname("name")->asstring;
   }
   else
     return "no";
}
它将返回对数据库的业务逻辑处理。 

继续,看能否将数据表发布出去,直接引入webdatamodual,

同样,加入adoconnection控件,如图:

放入表格控件。

对上编译后,将dll放到iis中,通过本地ie可以看到其webdatamodual已经发布出去。如图:

点击ie中的接口itest6的【wsdl】把生成的xml文件到文件,作为客户端导入的接口头文件。 

2.客户端编写

  a。创建一个应用程序,导入websoap中的接口,如图:

将在ie中刚拷贝的xml文件生成接口文件,

在客户端编写调用。在界面添一个edit,button控件,其代码

其中加入httprio1,其是通过http和soap数据包调用远程web services;

其实接口文件中的getites6封装了httpprio调用的过程。

void __fastcall tform3::button1click(tobject *sender)
{
  //  label1->caption = getitest6()->do1(edit1->text);

    _di_itest6 service;   
  httprio1->queryinterface(service);   //查询接口
  if (!service)
    return;
  label1->caption =  service->do1(edit1->text);

}

如何返回数据集,加入tsoapconnection,以及tdataclient控件,

设置相应的链接数据集以及接口属性。

如图:

挂好后,增加一个按钮:激活clientdataset控件

void __fastcall tform3::button3click(tobject *sender)
{
   clientdataset1->active = true;
}

编译上面的文件,生成客户端exe,启动该客户端,运行检查。

由于本人机子上安装的是sql server,打开一个工号表,看输入工号

1234返回的是否姓名:运行结果返回姓名。

在第二页检查是否返回数据集,运行结果如图:

看来,把客户端程序以后可以通过80端口处理业务,

而不是直接连接到数据库上,对于配置来说是不是减少了

麻烦,而且,可以在客户端混用其他的语言,这样,一个小组

开发没有必要非cbuilder不可。

源码附:http://www.tomore.com/1/44173.html

posted @ 2007-03-29 17:23 kenlistian 阅读(742) | 评论 (0)编辑 收藏

     在iis中发布cbuilder6编写的soap程序,要在创建web server开始时,开始选择创建服务程序的类型,如图:


isapi/nsapi dynamic link library ;将生成一个.dll文件,即选择这个选项,然后通过iis来进行发布;
cgi stand-alone executable 将生成一个cgi程序;一般比较占用内存,建议不用
apache 1.x;apache 2.x 可以用apache来发布;可以实现在不同平台上用行;
web app debugger executable 用webappdbg.exe运行的一个方便调试的程序;一般作为自测用。

1.写一个简单的服务程序,勾选第一选项。生成dll。

2.在iis中建立虚拟目录把其dll加入相应目录。

在ie中可以看到

注意:启动internet服务管理器,选择web站点的“属性”,依次选择弹出对话框的“主目录-〉配置”. 在web service服务器端程序设计期间,因为需要不停的修改、编译和测试程序运行,所以不能使用“缓存isapi应用程序”,否则一旦运行程序,服务器程序是处于使用期间,重新编译的新程序无法覆盖。在实际配置运行中,则选择“缓存isapi应用程序”,因为一旦运行isapi程序它会被调入缓存以后,在以后的执行中效率会大大提高,据测试,至少有一倍以上的提升幅度。

3.运行它,并将xml文件拷贝下来,作为客户端导入接口文件。

执行界面如下:

 

程序附:

http://www.tomore.com/1/44164.html

posted @ 2007-03-28 13:07 kenlistian 阅读(335) | 评论 (0)编辑 收藏

例子步骤如下:

1.在cbuilder6中选择soap server application,建立。

2.选Web App Debugger executeable 类型,

   定义一个CoClass Name 为:wadSoapDemo1 ,

3. 提示是否要新建一个接口,确定即可打开新建接口向导,

   如果要以后再增加接口,则在 New|WebServices 中选择 SOAP Server Interface 同样可打开新建接口向导。

 Generate sample methods 即可在生成的接口中同时生成一系列方法,比较全面地说明了如何在接口中定义方法。

 Service Activation Model 指定服务端的激活方式:Per Request(每次请求服务时激活)/Global(全局)。

采用Per Request则客户端的每次服务请求时建立服务,响应结束后也结束服务。Global 方式下,服务端只有一个服务实例,所有的客户端服务请求都由此实例处理,具体是通过一个叫 xxxFactory 的全局静态函数来实现的;

4.添加方法,并实现方法

 a。在申明的接口中添加虚拟方法

 b。在接口实现类中添加方法的申明

 c。在接口实现类中添加方法的定义

 5.  测试,看其接口方法是否提供出来。

    a。build 后先运行一次生成的exe ,其会自动注册。

    b。启动 Web App Debugger ,其实它就是一个测试用的IIS,点击ServerInfo

         打开其http://localhost:1024/ServerInfo.ServerInfo

         即可看到一个注册的列表,找到刚注册的服务器,点击go,

     c。在Service Info Page中可以看到定义的接口方法。

***************************************************************

 客户端编写

1.New|Application 新建一个一般 VCL 应用程序;
2.New|Web Services|Web Services Importer :

  在url中输入刚才在服务端测试的接口,如
    http://localhost:1024/xxxxxxx/wsdl/ITest  (保证在浏览器可以看到xml文档)

   选择“Next”后导入生成接口单元文件,谁用这个单元则#include 该单元。

3. 在 Form 上放上一个 Label ,Edit 和一个 Button

4. 双击 Button1 写下面的程序:

void __fastcall TForm2::Button1Click(TObject *Sender)
{
Label->Caption = GetITest()->GetMyMethod( StrToInt( Edit1->Text ) );
}
7.编译运行,在 Edit 中调参即可返回所要的结果。
源码:
http://www.tomore.com/1/44162.html

 

 

 

 

 

 

posted @ 2007-03-28 10:49 kenlistian 阅读(203) | 评论 (0)编辑 收藏

关于无法生成临时类CS2001CS2008解决办法(原创)
 

本人解决方法:将系统所在的盘下面的%windir%\Temp目录给予Asp.Net站点用户的读取及写入权限即可解决,

转:

http://szie.cn/blog/user1/1/archives/2007/134.html

posted @ 2007-01-04 11:16 kenlistian 阅读(853) | 评论 (0)编辑 收藏

无法在服务器上启动调试的解决办法

作者:未知    文章来源:      更新时间:2005-6-18

:无法在服务器上启动调试(Unable to start debugging on the Web server)

原因1:IIS的应用程序设置并没有使用集成windows认证,打开windows集成认证选项

原因2:检查IIS中的"保持HTTP连接"选项,确保该选项为选中状态

消息2:您没有在服务器启动调试的权限(You do not have permission to debug the server)

原因1:确保windows集成认证选项打开
原因2:如果您打开了windows集成认证选项的话,确保您的用户帐号具有对IIS目录的完全控制权
原因3:如果您的Web项目使用额完整的机器名作为项目名称(machinename.domainname.something)的话,那么这个Web站点就会被认为是一个Internet站点,所以IE的缺省设置就会影响登陆状态,在这种情况下,您需要在IE设置的Internet区域中允许您使用当前用户帐户登陆;这并不是IE的缺省设置,所以您最好使用你的机器名称来作为您项目的名字!


消息3:当发送HTTP调试请求时发生服务器端错误(Server side-error occurred on sending debug HTTP request)

原因1:您的Web应用程序可能没有应用程序名称,解决这个问题,您需要使用IIS MMC为您的Web项目分配一个应用程序名称;

原因2:如果您正在使用NTFS文件系统的话,确保aspnet帐户对于wwwroot或您的应用程序文件夹具有适当的读写权限

消息4:当前项目没有被配置为允许调试(The project is not configured to be debugged)

对于这个错误,您需要确保您的Web被配置为调试状态,完成这项工作,您需要在web.config中设置debug=true
原因1:asp.net 调试在项目属性中没有被开启;

原因2:请确认所期望的DLL已经被载入对应的调试符号文件,您可以在模块窗口中检查

消息5:调试器可能没有被安装(The debugger is not properly installed)

如果遇到这样的问题,检查控制台应用程序项目中的调试功能,如果控制台应用程序项目中显示图示的错误信息的话,说明您的.net framework并没有被完全的安装

您需要执行命令"regsvr32 mscordbi.dll"手动注册您的"mscordbi.dll"文件

消息6:服务器不支持asp.net 或 ATL server 应用程序调试

如果你正使用WindowsXP Pro或是Win2000 Pro的话,您可能要思考一下您安装VS.Net的顺序问题;您如果在安装Vs.Net之后才安装IIS的话,你就会遇到这个错误,在这种情况下,您需要使用命令"aspnet_regiis.exe –i"来注册"aspnet_isapi.dll"

消息7:访问被拒绝。检查您是否是系统管理员或...组的成员(Access is denied. Verify that you are an administrator or a member of ...)

您的帐户可能不是本机Debugger Users组的成员,将您的帐户加入该组可以解决这个问题;

消息8:无法启动ASP.NET或ATL Server调试

原因1:您可能安装了IIS Lockdown,如果是这样的话,找到urlscan.ini文件,在[allowverbs]节中加入DEBUG(大小写敏感)字段
原因2:如果您正使用域控制器(Domain controller)作为您的服务器,并且您的项目使用了机器器名而没有使用完整的域名的话,您肯能需要改变您项目的Url为使用完整的域名
原因3:如果您的IIS被设置为使用专用的IP作为Web站点的定位标志(Web site identification)的话,你肯那个就会遇到这个错误;在这种情况下,您需要改变您的项目名字为直接使用IP地址作为项目名。对于已经存在的项目,你需要编辑.sln文件和.webinfo文件来改变项目的名字为IP地址
原因4:web.config文件中的<httpRuntime maxRequestLength="#########" />值太大。缺省单位是Kbyte,不是byte,所以如果您使用了错误的单位来改变这个数值的话,可能会导致调试错误!

消息9:访问被拒绝

原因:您可能是Debugger Users组中的成员,但是你没有调试aspnet工作进程的权限,因为您并不是aspnet用户帐户或Administrator组中的成员。将您的用户帐户加入到机器的Administrator组中以解决该问题。

无法对于一个Included File进行调试
ASPX中,您无法调试一个included file,一个included fie通常是您从asp项目转向ASPX的结果,如果您使用<!--#include file = "file name"-->包含文件,您可能不能正确的调试那个包含文件,您需要使用<!--#include virtual="file name"-->来代替。

在改变了您的密码时,您需要为使用ASP.NET调试进行log off/log in

在安装了Win2000 SP4后,ASP.NET调试无法工作,报错:"访问被拒绝"
解决办法是使用命令"regsvr32 –i aspnet_isap.dll"重新注册aspnet_isapi.dll

只能在页面第一次被加载的时候停在断点处(hit breakpoint)
对于这个问题可能有几种不同的原因,但是最有可能的原因应该是您在web.config文件中使用了page cache选项;如果您在web.config中看到了如<add key="<your web project name".Web.EnablePageCache" value="True" />的配置,您需要设置value为False来关闭Web页面缓存,在改变该设置之后,您应该就可以停在断点处了;

您需要共享一个Web服务器来进行调试,但是又不想其他用户能够在该机器上进行管理
在VS.Net中,有两件事情决定是否一个用户可以进行调试,一是Debugger Users组,令一个是用户权限,如administrator,power user 或者 SEDebug
Debugger Users组决定是否用户可以访问VS调试模块(主要是MDM-Machine Debug Manager,VS的一个部分),所以作为该组成员意味着您获得了访问MDM的权限,所以您可以调试您的开放进程(open process)并且可以看到您机器上的进程列表.
但在这之后,您是否可以调试其他用户的进程就决定于您的权限,举例说明:如果您想要调试其他用户的自然进程(native process),您就需要具有SEDebug权限。对于其他用户的托管进程(Managed Process),您需要是该机器的管理员!
由于这样的约束,在这样的情况下,学生们就必须被提升为管理员,如果不这样做的话ASP.NET工作进程在缺省情况下就无法被调试。


常规调试(General Debugging)
这些情况是基于控制台应用程序类型的

消息1:无法启动调试

这个问题时因为没有正确注册mscordbi.dll造成的,重新注册文件就可以解决这个问题

消息2:无法启动调试,访问被拒绝

确保Machine Debugger Manager服务被正确启动,并且您是Debugger Users组中的一员,或是administrator

我可以启动托管调试(Managed debugging),但是PDB并没被加载,所以我无法设置任何断点
如果调试器被正确运行,但是您并没有停在任何断点的话,您可能需要检查diasymreader.dll的安装情况,这个文件可能没有被注册,您需要这样做:
regsvr32 <path to DLL>\diasymreader.dll

托管调试无法工作
您使用CLR模式附加到一个自然进程在该进程还没有创建一个CLR对象时,托管调试就无法工作
解决1:在CLR代码已经被该进程使用后再附加到该进程
解决2:使用InterOp模式附加到该进程,在这种情况下,您不需要在CLR代码被调用以后再附加到该进程

托管调试器无响应
当您针对托管代码启动调试时,调试器无响应
解决:确认 .NET Framework Support 服务被停止并且禁用(仅停止该服务是不够的)
如果您并没有.NET Framework Support 在运行的话,禁止IIS admin服务

对C# 代码使用 Stepping 结果并不正确
看看以下代码:
string someStr;
someStr = "SomeValue";
if(someStr == null)
    Console.WriteLine("what's up?");

try
{
}
catch(Exception e)
{
}

如果您对这段代码使用Step的话,您会发现当您进入"if"语句的时候,指令指针(instruction pointer)会移动到Console.WriteLine("what's up?");这句
这并不是调试器的bug,但是这是针对try catch块调试信息的一支问题。看看以下该例子的反编译代码:
if(someStr == null)
0000002a  cmp         dword ptr [ebp-18h],0
0000002e  jne         0000003C

Console.WriteLine("what's up?");
00000030  mov         ecx,dword ptr ds:[01C50070h]
00000036  call        dword ptr ds:[02F0257Ch]
0000003c  jmp         00000048

catch(Exception e)
0000003e  mov         dword ptr [ebp-1Ch],eax
00000041  call        762C0846
00000046  jmp         00000048

}
00000048  nop

当value并不为真的时候指令指针移动到了0000003c  jmp         00000048这一行,但是这行错误的对应了if语句的语句块。所以当执行结果正确时,我们看到的调试过程并不正确!

 

因果调试:在Web Service 客户端和Web Service之间进行步进(Stepping)

无法从Web Service客户端进入Web Service进行调试
缺省设置下并不允许您从Web Service客户端进入Web Service。
ASPNET工作进程在"aspnet"或"network service"用户帐户下工作,这些帐号并不具有通过DCOM访问MDM的权限。所以,您需要把这些帐户增加进Debugger Users组中

在允许扮演Web Service(impersonation of Web service)之后,您无法做到因果步进
您需要做以下的事情来纠正客户端与服务之间的步进
 1.关闭IIS的匿名访问
 2.改变客户端代码,设置一个安全证书(credential)给WebService
 Service1 obj = new Service1();
obj.Credentials =  System.Net.CredentialCache.DefaultCredentials;

调试器挂起
如果您的Web Service客户端代码运行在一个STA(Single Thread Apartment)模型下,并且它正

在等待一个异步调用的完成,如下代码所示:
Single Thread Apartment
Service1 obj = new Service1();
System.IAsyncResult ar = obj.BeginHelloWorld(new System.AsyncCallback

(Class1.Handle),obj);
while(ar.IsCompleted != true)
{
    System.Threading.Thread.Sleep(1000);
}
那调试器就会挂起。导致这种挂起的原因是因为一个调试器组件被在这个调试中的您的代码锁定了,解决方案1就是改变您的代码使用事件进行线程同步或是使用 mutext.其他的解决方案就是注销csm.dll.第二种解决方案就是禁用因果调试。你可能需要手动附加到aspnet_wp.exe来调试Web Service

posted @ 2007-01-04 11:13 kenlistian 阅读(1063) | 评论 (0)编辑 收藏

装了VS2005再装IIS,结果出了些小问题
在调用iis上网页时,报出
“访问IIS元数据库失败”
 
在网上查到解决方案,
 
1、打开CMD,进入 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
2、输入 aspnet_regiis.exe -i

接着还会出现“未能创建 Mutex”的问题 
解决方法:
1、先关闭你的VS2005。
2、打开 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files  找到你刚才调试的程序的名字的目录删除它。
3、关闭IIS服务器,重开一次。
4、用IE浏览一下你的程序,问题解决。

都是次序惹的祸,最好是先IIS 再VS2K5 
 
 
posted @ 2007-01-04 10:04 kenlistian 阅读(175) | 评论 (0)编辑 收藏

. :: ,* 的细节使用

Super

语法:

super
super(表达式, ... )

用于类继承中,super调用的父类覆盖的同名方法。若省略括号和参数时,将会把当前方法的参数原封不动地传递给父类中的同名方法。若调用时不想使用参数的话,请使用括号显式地标出,像super()这样。

其实就是delphi中的inherited,在c中就是直接写父类和其方法名。

-----------------------------------------

带块的方法调用

例:

[1,2,3].each do |i| print i*2, "\n" end
[1,2,3].each {|i| print i*2, "\n" }

语法:

method(arg1, arg2, ...)  do [`|' 表达式 ... `|'] 表达式 ... end
method(arg1, arg2, ...) `{' [`|' 表达式 ... `|'] 表达式 ... `}'
method(arg1, arg2, ..., `&' proc_object)

将do...end或{...}中的代码片段(也就是块)添加在方法后面,然后再调用该方法时,就能从该方法
内部对快进行计算。在带块的方法内进行块调用时使用 yield 表达式。
传给yield的值会被赋值给夹在"||"中的变量。

{...}比do...end块的结合能力强。例如:

foobar a, b do .. end   # foobar 是带块的方法
foobar a, b { .. }      # b    成了带块的方法

块中首次被赋值(声明)的局部变量的作用域仅限于该块。例如:

foobar {
  i = 20                # 声明了局部变量i
   ...
}
print defined? i        # 此处的i尚未定义,false
foobar a, b do
  i = 11                # 声明了一个新变量i
   ...
end

如下所示,在块外仍然有效。

i = 10
[1,2,3].each do |m|
  p i * m               # 马上就能使用i
end
采用&来调用过程对象,
嘿,像在一个函数参数是另一个函数地址作为参数传入一样。
还可以把过程对象( Proc )当作块传递给带块的方法。这时要在过程对象名前面添加"&",
并把该过程对象传递给带块的方法的最后一个参数。除了过程对象以外,还可以传递方法对象( Method )。这时将生成一个调用该方法的过程对象,然后把这个过程对象传给带块的方法。
pobj = proc {|v| p v }

[1,2,3].each(&pobj)
=> 1
   2
   3

ruby 1.7 特性: 在version 1.7中,若该对象自带to_proc方法的话,就可以把它当作带"&"的参数传给带块方法(默认状态下,Proc、Method对象都有to_proc方法)。方法调用时会执行to_proc,它将返回Proc对象。

class Foo
  def to_proc
    Proc.new {|v| p v}
  end
end

[1,2,3].each(&Foo.new)

=> 1
   2
   3

带块方法的返回值与通常的方法是一样的。若块中的 break 引起中断时,将返回nil。
ruby 1.7 特性 :若break带参数的话,该参数的值就是带块方法的返回值。

1.8呢?

yield

语法:
yield `(' [表达式 [`,' 表达式 ... ]] `)'
yield [表达式 [`,' 表达式 ... ]]

把参数传给块之后,对块进行计算。因为yield定义迭代器,所以是在方法定义内使用。

def foo
  yield(1,2)
end

foo {|a,b| p [a,b]}

对块参数进行赋值时遵从多重赋值规律。若执行yield时,方法并没有带块(不是迭代器)的话,就会引发 LocalJumpError 异常。

yield将会返回块内最后被计算的表达式的值。若因 next 引起块的运行中断的话,返回nil。

def foo
  yield 1,2,3
end

foo {|v| p v}

# => -:5: warning: multiple values for a block parameter (3 for 1)
     [1, 2, 3]

应该写成

yield [1,2,3]

或者

foo {|*v| p v}

这样才对。虽然现在使用

v = 1,2,3

这样的多重赋值还不会有警告,但最好不要使用。

 

posted @ 2006-12-29 10:41 kenlistian 阅读(144) | 评论 (0)编辑 收藏

控制语句

if

if 表达式 [then]
  表达式 ...
[elsif 表达式 [then]
  表达式 ... ]
...
[else
  表达式 ... ]
end

Ruby中只有falsenil代表伪,其他都是真,甚至0或空字符串也是如此。

if 修饰句

语法:

表达式 if 表达式
unless(除非)
语法:
unless 表达式 [then]

表达式 ...
[else 表达式 ... ]
end

unless 修饰句

语法:     表达式 unless 表达式

Case

语法:

case [表达式]
[when 表达式 [, 表达式] ...[, `*' 表达式] [then]
  表达式..]..
[when `*' 表达式 [then]
  表达式..]..
[else
  表达式..]
end
在表达式并列时是or的关系,还有*的使用,遵循以下:

若when 部分中的最后一个表达式前带"*"的话,
该表达式将被当作数组展开。

ary = [1,2,3]

case v
when *ary
 ..
end

等同于

case v
when 1, 2, 3
 ..
end
 
 
while
语法: 
  while 表达式 [do]
     ...
  end
do 可要可不要
 
while 修饰句   
语法:
   表达式 while 表达式
如: sleep(60) while io_not_ready?

until
语法:
  until 表达式 [do]
 ...
  end
在表达式的计算值变为真之前,一直循环执行until中的内容。until不返回值。
 
是先判断表达式呢还是执行后再判断?
until修饰句
  表达式 until  表达式
 
 
for 
  语法:
for lhs ... in 表达式 [do]
  表达式
end
<===>
(表达式).each '{' '|' lhs.. '|' 表达式.. '}'
 
--------------------------------------------------------------------
break
退出循环,循环有下列:
while
until
for
迭代
 
next
next将跳转到最内侧循环的头部,像continue;
 
redo
  不检查循环条件,重新开始当前循环
 
retry

在迭代、块或for语句中使用retry,意味着重启迭代器。
同时迭代器的参数也将被重新计算。

for i in 1..5
  retry if some_condition # 从 i == 1 开始重新执行
end

# 用户定义的 "until循环"
def UNTIL(cond)
  return if cond
  yield
  retry
end
 
---------------------------------------------------------
异常处理语句
raise

例:

   raise "you lose"  # 引发RuntimeError异常
   
# 下面两个将引发SyntaxError异常
raise SyntaxError, "invalid syntax"
raise SyntaxError.new("invalid syntax")
raise                 # 再次引发上一个异常

语法:

raise
raise message或exception
raise error_type, message
raise error_type, message, traceback

引发异常。

第一句将再次引发上一个异常。

第二句中,若参数是字符串的话,就把它当作错误信息(message)再引发RuntimeError异常。

若参数为异常对象则引发该异常。

第三句中,将引发第一个参数所指的异常,并以第二个参数的内容作为错误信息。

第四句中,第三参数装载的是源自于$@caller的堆栈信息,它指明发生异常的地点。

可以使用begin表达式的rescue部分来捕捉异常。这时使用rescue error_type => var就可以得到异常对象。您还可以从内部变量$!中获得这个对象。另外,变量$@中装载的是发生异常的源代码位置。

raise并不是Ruby的保留字,它是Kernel模块中定义的函数式的方法。

 

 

begin

异常处理的开始,

这个其实就像try catch finally一样,

其中

rescue === catch

ensure === finally

 

语法:

begin
  表达式..
[rescue [error_type,..] [=> evar] [then]
  表达式..]..
[else
  表达式..]
[ensure
  表达式..]
end

 

若给出了rescue部分(可以有若干个)的话,就可以在发生异常时捕捉到它。

若存在与异常类型一致的rescue部分的话,就执行rescue的内容。

可以使用$!来查看异常的情况。另外,若事先设定了变量evar的话,

它也可以像$!一样存储那些异常的信息。

begin
  raise "error message"
rescue => evar
  p $!
  p evar
end
# => #<RuntimeError: error message>
     #<RuntimeError: error message>

rescue部分使用Object#kind of?来判断刚才的异常的类是否就是自己期待的异常类,

或者这二者是否处于父类/子类的关系。

error_type被省略,则将捕捉StandardError的子类中的所有异常。

 

Ruby的内部异常(除了SystemExitInterrupt这些退出命令以外)

StandardError的子类。

 

请参考异常类来了解异常类的层次关系。

rescue部分中,error_type与普通的参数一样接受计算,若符合的话就执行

相应部分的内容。

error_type的计算值既非类又非模块的话,则引发TypeError异常。

若运行过程中没发生异常,则开始计算可选的else部分。

若存在ensure部分的话,则在begin表达式结束之前一定会计算它。

 

begin表达式整体的计算值取决于,begin的内容部分/rescue部分/else部分

中最后被计算的句子的值。若各部分中均无语句时,其值为nil。不管怎样,

ensure部分的值始终会被忽略。

例:

  open("nonexistent file") 
  rescue STDERR.puts "Warning: #$!"

语法:

表达式1 rescue 表达式2

若表达式1中发生异常时就计算表达式2。这等同于下例。

不能指定想捕捉的异常类。(也就是说,只能捕捉StandardError异常类的子类了)

begin
  表达式1
rescue
  表达式2
end

在包括rescue修饰句的表达式中,若没发生异常则返回表达式1的值,

若发生异常则返回表达式2的值。但在大多数场合中,因为考虑到优先度的问题,

所以需要使用括号将整个表达式括起来。

 
var = open("nonexistent file") rescue false
p var
=> nil      # 因为只定义了一个空变量var

var = (open("nonexistent file") rescue false)
p var
=> false

是传递给某方法的参数时,有必要使用双重括号。

p(open("nonexistent file") rescue false)
=> parse error

p((open("nonexistent file") rescue false))
=> false
 
return

例:

return
return 12
return 1,2,3

语法:

return [表达式[`,' 表达式 ... ]]

结束方法的运行,且把表达式的值设定为方法的返回值。若给出了2个以上的表达式,

则将把这些表达式化为一个数组,然后把该数组设定为方法的返回值。若省略表达式,

将返回值设为nil。

 
BEGIN
 

语法:

BEGIN '{' 语句.. '}'

注册初始化例程(routine)。BEGIN块所指定的语句的执行顺序将先于该文件中任何语句。
若有多个BEGIN块的话,将按照出现顺序依次执行。

BEGIN块在编译时被注册。也就是说,同一条语句只会被注册一次。

if false
  BEGIN { p "begin" }
end

# => "begin"

BEGIN块引入了独立的局部变量作用域,因此不能和外部共享局部变量。

为了与块外交换信息,必须借助于常数或全局变量。

BEGIN { $foo, foo = true, true }
p $foo  # => true
p foo   # undefined local variable or method `foo' for main:Object (NameError)

BEGIN不能出现在方法定义表达式中,否则会引发 parse error。

def foo
  BEGIN { p "begin" }
end
# => -:2: BEGIN in method
 
END

语法:
END '{' 
语句..
'}'

注册“善后”例程。END块中指定的语句会在解释器结束前得到执行。

 

若注册了若干END块的话,则与注册时相反的顺序依次执行这些块。
END { p 1 } END { p 2 } END { p 3 } # => 3 2 1

 

 


 

 


 

 

把END块置入循环中,也只会注册一次。

5.times do |i|
  END { p i }
end
# => 0

 

若把END块置入方法定义表达式中会引起警告。

def foo
  END { p "end" }
end
p foo

# => -:2: warning: END in method; use at_exit
     nil
     "end"


END块与BEGIN块不同的是,它同周围部分共享作用域。也就是说,它的作用域同迭代器一样。

若END块中发生了异常,将中断该块。但解释器并不结束,只是发出信息,
并且试图处理完所有的善后例程。

例:

END { p "FOO" }
END { raise "bar"; p "BAR" }
END { raise "baz"; p "BAZ" }

=> baz (RuntimeError)
   bar (RuntimeError)
   "FOO"
 
posted @ 2006-12-29 10:21 kenlistian 阅读(399) | 评论 (0)编辑 收藏

运算符优先度

高 
      ::
       []
       +(单项)   !     ~
       **
       -  (单项)
       *   /    %
       +   -
       <<   >>
       &
       |  ^
       > >=  < <=
       <=> ==  === !=  =~  !~
       &&
       ||
       ..  ...
       ?:(条件操作符)
       =(+=, -= ... )
       not
低   and or

赋值:语法

表达式1 op= 表达式2
op可以是下列中某一个。
   +, -, *, /, %, **, &, |, ^, <<, >>, &&, ||

等同于                                                    表达式1 = 表达式1 op 表达式2
但,当op是“&&”或“||”时则:  表达式1 op (表达式1 = 表达式2)
这个样子。如在属性调用时
obj.foo ||= true     应是    obj.foo || (obj.foo = true)

多重赋值:

foo, bar, baz = 1, 2, 3
foo, = list()
foo, *rest = list2()

语法:
   表达式 [`,' [表达式 `,' ... ] [`*' [表达式]]] = 表达式 [, 表达式 ... ][`*' 表达式]
`*' [表达式] = 表达式 [, 表达式 ... ][`*' 表达式]

     多重赋值是指,在多个表达式以及数组中同时进行的赋值。左边的各个表达式必须是可以被赋值的。若右边只有一个表达式时,则将该表达式的计算值转为数组后,再把数组中的各个元素依次赋值给左边。若右边数组元素的数量超过左边的话,将忽略多余的数组元素。若右边数组元素个数不足的话,将向左边多余的元素中代入nil。
     若左边最后一个表达式前带*的话,则将右边多余的元素以数组的形式代入这个带*的表达式中。若右边没有多余元素的话,就把空数组代入其中。

例:

foo, bar = [1, 2]       # foo = 1; bar = 2
foo, bar = 1, 2         # foo = 1; bar = 2
foo, bar = 1            # foo = 1; bar = nil

foo, bar, baz = 1, 2    # foo = 1; bar = 2; baz = nil
foo, bar = 1, 2, 3      # foo = 1; bar = 2
foo      = 1, 2, 3      # foo = [1, 2, 3]
*foo     = 1, 2, 3      # foo = [1, 2, 3]
foo,*bar = 1, 2, 3      # foo = 1; bar = [2, 3]

在多重赋值过程中,若使用括号的话,就可以把数组内含的元素取出来进行赋值。

(foo, bar), baz = [1, 2], 3       # foo = 1; bar = 2; baz = 3

还可以把特殊形式的赋值表达式转化为多重代入。

class C
  def foo=( v )
    @foo = v
  end
  def []=(i,v)
    @bar = ["a", "b", "c"]
    @bar[i] = v
  end
end

obj = C.new
obj.foo, obj[2] = 1, 2     # @foo = 1; @bar = ["a", "b", 2]

若左边以","结尾或"*"后面没有表达式时,将忽略右边多余的元素。

foo,*    = 1, 2, 3      # foo = 1
foo,     = 1, 2, 3      # foo = 1
*        = 1, 2, 3

当您想忽略方法调用中的所有参数时,就可以使用这个"*"
def foo(*)
end
foo(1,2,3)
多重赋值的值变换为右边的数组。

范围表达式     如:    1 .. 20       
语法为:
表达式1 .. 表达式2
表达式1 ... 表达式2      不包含终点,就像a<= x < b一样。
如果不是出现在条件表达式中的话,它将返回从表达式1到表达式2的范围对象。
范围对象是Range类的实例。

若它出现在条件表达式中时,在表达式1变成真之前,它将一直返回伪。接下来,在表达式2返回真之前,它将一直返回真。一旦表达式2变为真,它将重新返回伪。
  使用".."时,一旦表达式1返回真,马上就会对表达式2进行计算(就象awk)。
  而使用"..."时,在进行下个计算之前,一直都不会对表达式2进行计算(就象sed)。

就这样理解就行,细节等用时再看。

and
表达式 `&&' 表达式
表达式 `and' 表达式

or
表达式 `||' 表达式
表达式 or 表达式

not
`!' 表达式
not 表达式

表达式 `!=' 表达式    <====>!(表达式 == 表达式)

表达式 `!~' 表达式 <====>!(表达式 =~ 表达式)

将包含not的表达式传递给某方法的参数时,必须使用双层括号。
p(! false)      #=> true
p((not false))  #=> true

条件操作符

obj == 1 ? foo : bar

语法:
表达式1 ? 表达式2 : 表达式3
和C是一致的。

 

posted @ 2006-12-29 09:33 kenlistian 阅读(142) | 评论 (0)编辑 收藏

ruby的注释

行注释 #

块注释 =begin

                。。。

               =end

ruby的保留字

BEGIN    class    ensure   nil      self     when
END     
def      false    not      super    while
alias    defined? for      or       then     yield
and      do       if       redo     true
begin    else     in       rescue   undef
break    elsif    module   retry    unless
case     end      next     return   until

变量

局部变量

 

实例变量 

@为开头,属于特定的对象,一般在类中用 

类变量

@@开头,在类的定义中定义类变量
类变量可以是被类、子类以及它们的实例所共享的全局变量

全局变量

$为开头,在程序的任何地方可以引用

伪变量

self

当前方法执行主体

nil

NilClas的唯一实例

true

TrueClass实例

false

FalseClass实例

__FILE__

源名

__LINE__

行号


 常量

     以大写字母([A-Z])开始的标识符为常数。
     常数的定义(和初始化)在赋值过程完成.
     不能在方法中对常数进行定义.若对已定义的常数进行赋值的话,会出现警告信息.
      若引用未定义的常数的话,则会引发NameError异常.

 

字面值
   如数字1或字符串“hello”写入ruby中值都是。
  表达整数     124
   表达符号整数  -123
   表达浮点数   123.45
   表达浮点数   1.2e-4
   表达16进制数   0xffff
   表达二进制数  0b1001
   表达8进制    0o377
   表达字符asii码  ?a
   表达控制码      ?\C-a
   表达Meta a的代码   ?\M-a
   表达Meta-Control a 的代码  ?\M-\C-a
  有趣一点是数字中间夹 _ 下划线是作为阅读分清数字用,ruby会忽略它。

字符串字面值
双引号   反斜线表示法和展开式都是有效的
单引号   除了\\(反斜线本身)、\'(单引号)和行尾的\(忽略换行)以外,
                不会对字符串内容作任何处理
字符串引号分隔之间留空白也被当作一个空格处理。

反斜线表示:
\t    Tab(0x09)
\n   换行(0x0a)
\r  
\f     换页
\b    BackSpace
\a    Bell
\e    Escape
\s    空白
\nnn  8进制表示
\xnn   16进制
\cx  \C-x    control字符,x为ascii码
\x  字符x本身

字符串中有如下形式,其中  #{表达式} 就是表达式
如下:

“this  is #{$ruby}"  ------->"this is RUBY"
  ' this is #{$ruby}'    -------->'this is #{$ruby}'
  "this is $ruby"        ---------->"this is $ruby"
   "this is #$ruby"    ----------> "this is RUBY"     可以省略{}

批量字符串赋值
例子

print << EOS   #(从这里开始)直到标识符 EOS 之前的部分就是字面值
   this is test
   next line
EOS
equal fellow :
   print " this is test \n next line\n"

 可以使用引号(""、''或``)将开始标签“<<标识符”中的标识符括起来。这时,集成字符串的性质将取决于您所选择的引号的种类。请参考下列,当您选择双引号时,其效果与不使用任何引号时的效果相同。

# 反斜线表示法和展开式都是有效的
print <<"EOS"
The price is #{$price}.
EOS

# 效果同上
print <<EOS
The price is #{$price}.
EOS

# 展开式无法工作
print <<'EOS'
The price is #{$price}.
EOS

# 执行命令
print <<`EOC`
date
diff test.c.org test.c
EOC
规范点,用双引号或不用是不会错。
数组表达式

例:

[1, 2, 3]
%w(a b c)

语法:

`[' 表达式`,' ... `]'

分别计算每个表达式的值,然后返回由这些值构成的数组。数组是Array类的实例。

当数组元素都是字符串字面值时,可以使用%表示法将数组写成其他形式。

每次对数组表达式进行计算时都会返回一个新的数组对象。

%w(a b c) ===== ["a", "b","c"]

 

 

%表示法,它就像一个定义任意分隔符号的前缀,

字符串字面值命令输出正则表达式字面值数组表达式符号 中,
用这种以%开头的表达法。特别是当字符串或正则表达式中以非字符非数字(包含双引号(")、斜线(/)等)(它们是作为切分字面值时使用的字符)要素时,它可以减少反斜线(\)在代码中出现的次数。

  • % !STRING! : 双引号中的字符串
  • %Q!STRING! : 同上
  • %q!STRING! : 单引号中的字符串
  • %x!STRING! : 命令输出
  • %r!STRING! : 正则表达式
  • %w!STRING! : 字符串数组(以空白字符切分各元素)
  • %W!STRING! : 字符串数组(以空白字符切分各元素)。展开式、反斜线表示法都有效(ruby 1.7 特性)
  • %s!STRING! : 符号。展开式、反斜线表示法都无效(ruby 1.7 特性)

!部分是任何非字母非数字的字符,包括换行。
 若起始切分字符是括号("(","[","{","<")的话,则终止切分字符就是与其对应的括号。
若以括号作为切分字符的话,只要对应部分使用了对应的括号,就可以在其中的元素中使用与切分字符一样的括号。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2006-12-28 14:24 kenlistian 阅读(511) | 评论 (0)编辑 收藏

仅列出标题
共42页: First 34 35 36 37 38 39 40 41 42