美文网首页
pike学习笔记

pike学习笔记

作者: 1angxi | 来源:发表于2015-07-17 18:47 被阅读1104次

    Pike Tutorial Study

    Pike是一门解释型的、面向对象的编程语言,与C和C++有点像,但是更加容易学习和使用。它能够被用于小脚本或者是大型系统的编写。

    Pike的主要特性有:

    高级并强力、面向对象、解释性、最快的脚本语言、垃圾收集机制、易于扩展(C或者C++)

    Pike的安装

    1、去Pike官网上去下载安装包。

    2、解压缩,直接make && make install

    3、新建一个文件filename.pike,输入:

    int main()
    {
      write("Hello world!\n");
      return 0;
    }
    

    在命令行输入pike filename.pike,可以看到运行结果。

    运行在窗口中

    运行代码:

    int main()
    {
      GTK.setup_gtk();
      GTK.Alert("Hello world!")
        -> signal_connect("destroy", lambda(){ exit(0); });
      return -1;
    }
    

    效果如下:

    windows

    Pike的模块

    Pike和大多数其他语言一样,提供了丰富的API给我们开发丰富的应用。比如说,当我们需要访问一个网页的时候,可以使用Protocols.HTTP模块下的Query对象。

    形如:

    void handle_url(string this_url){    
        write("Fetching URL '" + this_url + "'...");
        Protocols.HTTP.Query web_page; 
        web_page = Protocols.HTTP.get_url(this_url); 
        if(web_page == 0) { 
            write(" Failed!\n"); 
            return; 
        } 
        write(" Done.\n");
    } 
    // handle_url
    

    当然,pike提供了import关键字完整导入一个模块。这样使用模块内部的类时就不用写上前缀了:

    import Protocols.HTTP;
    Query web_page;
    

    当用web_page访问了一个网站之后,如果想要将网站的内容显示出来,则使用web_page提供的一个data()方法。

    web_page->data()
    

    基本数据类型

    pike的基本数据类型包括:int float和string。

    容器类型包括:array, mapping,multiset等

    容器类型

    最简单的容器类型是array。你可以往这个容器里面放入数据项,array是一个连续的大小的盒子。

    array是一个形如这样的list:

    ({ "geegle", "boogle", "fnordle blordle" })
    ({ 12, 17, -3, 8 })
    ({  })
    ({ 12, 17, 17, "foo", ({ "gleep", "gleep" }) })
    

    可以看到,除了基本类型,array还能嵌套其他容器类型。

    能够这样子定义一个变量:

    array a;        // Array of anything
    array(string) b;    // Array of strings
    array(array(string)) c;    // Array of arrays of strings
    array(mixed) d;        // Array of anything
    

    可以看到最后一行的array(mixed) d,这其实是一个多态容器,能够存放任意类型的数据。

    然后就是array的赋值了:

    a = ({ 17, "hello", 3.6 });
    b = ({ "foo", "bar", "fum" });
    c = ({ ({ "John", "Sherlock" }), ({ "Holmes" }) });
    d = c;
    

    我们可以访问数组一样通过下标访问array:

    write(a[0]);    // Writes 17
    b[1] = "bloo";    // Replaces "bar" with "bloo"
    c[1][0] = b[2];    // Replaces "Holmes" with "fum"
    

    有一些有意思的操作可以运用于array,比如说加法:

    ({ 7, 1 }) + ({ 3, 1, 6 })
    
    ({ 7, 1, 3, 1, 6 })
    

    除了array还有两种容器类型:mapping和multiset。

    set用来判断一个值是不是一个集合的成员。multiset则运行集合里面存在一样的值。

    mapping有时被称为字典,通过键值对来存储数据。后面还会进一步解释。

    方法也是对象

    方法也是对象,这完全符合面向对象里面万物皆对象的理念。因此有时我们可以把方法像一个对象一样传递参数给另一个方法。比如说:

    void write_one(int x)
    {
      write("Number: " + x + "\n");
    }
    
    int main()
    {
      array(int) all_of_them = ({ 1, 5, -1, 17, 17 });
      map(all_of_them, write_one);
      return 0;
    }
    

    Python里面也有这种特性,对于编程来说非常方便。

    0是一个特别的东西

    0这个值是一个特别的东西,不单单只是int类型的0,它可以代表所有的类型的“NULL”,如果我们创造了一个变量但是我们不想赋值它,默认会被赋值为0。

    举个栗子:

    string accumulate_answer()
    {
      string result;
      // Probably some code here
      result += "Hi!\n";
      // More code goes here
      return result;
    }
    ``
    
    程序会返回一个`0Hi!\n`,前面多了一个0,这是我们常见的错误。因此,为了避免犯错,应该在变量声明的时候赋初值,哪怕是这样:`string result = ""`也好。
    
    pike支持一个任意数据类型mixed,这意味着用mixed声明的变量可以存储任意的类型:
    
    ```pike
    mixed x;
    array(mixed) build_array(mixed x) { return ({ x }); }
    

    pike还很神奇的支持或语句来声明变量类型,形如:

    int|string w;
    
    array(int|string|float) make_array(int|string|float x)
    {
      return ({ x });
    }
    

    比较好的做好是声明一个明确的变量类型,这样编译器会帮助做类型检查,使得类型错误在编译时就被发现。

    基本类型和引用类型

    熟悉C++的话自然就知道引用时啥了。

    基本数据类型都不是引用类型。int i1=5;i2=i1;在内存中像这样:

    非引用

    非基本数据类型比如说array就是引用类型,比如说下面的代码:

    array(int) a1;
    a1 = ({1,2,3})
    array(int) a2;
    a2 = a1;
    

    在内存中会是像这样:

    引用类型

    当然如果不想要引用,而是值复制的话(这种方式更加推荐,避免数据同步问题。)

    a2 = copy_value(a1)
    

    内存中是这样的:

    非引用

    如果想要复制但是又不想用copy_value函数的话,可以这样子写:

    a2 = a1 + ({})
    

    返回的是一个a1的拷贝,与copy_value效果相同。

    引用类型到底有哪些呢?下面列出来:

    array
    mapping
    multiset
    program
    object
    function

    创建方法

    pike在这方面的语法和c很像,一个简单的例子:

    float average(float x1, float x2)
    {
      return (x1 + x2) / 2;
    }
    

    方法的调用:

    float x = average(19.0 + 11.0, 10.0);
    average(27.13, x + 27.15);
    float y = average(1.0, 2.0) + average(6.0, 7.1);
    float z = average(1.0, average(2.0, 3.0));
    

    两个更加复杂的例子:

    int getDex()
    {
      int oldDex = Dex;
      Dex = 0;
      return oldDex;
    }
    
    private void
    show_user(int|string id, void|string full_name)
    {
      write("Id: " + id + "\n");
      if(full_name)
        write("Full name: " + full_name + "\n");
    }
    

    如果想要调用:

    getDex();
    show_user(19);
    show_user("john");
    show_user(19, "John Doe");
    show_user("john", "John Doe");
    

    pike的多态

    对象的使用

    pike声明并初始化一个对象是这样的:

    animal some_animal;
    some_animal = animal();
    animal my_dog = animal();
    

    通过->调用对象的内部变量:

    my_dog->name = "Fido";
    my_dog->weight = 10.0;
    some_animal->name = "Glorbie";
    write("My dog is called " + my_dog->name + ".\n");
    write("Its weight is " + my_dog->weight + ".\n");
    write("That animal is called " + some_animal->name + ".\n");
    

    初始化一个对象时可以调用有参构造函数:

    animal piglet = animal("Piglet", 6.3);
    my_dog->eat("quiche"); // Real dogs eat quiche.
    write("Its weight is now " + my_dog->weight + ".\n");
    

    从上面可以看到如果想要调用对象方法,依然是使用->。

    类定义

    话不多说,先上代码:

    class animal
    {
      string name;
      float weight;
    
      void create(string n, float w)
      {
        name = n;
        weight = w;
      }
    
      void eat(string food)
      {
        write(name + " eats some " + food + ".\n");
        weight += 0.5;
      }
    }
    

    分析一下,基本上与C++的类定义差不多,主要的区别在于没有声明访问控制(public和private)。

    当然也可以把类当做结构体来用:

    class customer
    {
      int number;
      string name;
      array(string) phone_numbers;
    }
    

    调用代码:

    array(customer) all_customers = ({ });
    customer c = customer();
    c->number = 18;
    c->name = "Ellen Ripley";
    c->phone_numbers = ({ "555-8767", "555-4001" });
    all_customers += ({ c });
    

    奇特用法

    一个pike文件就是一个类。这是pike比较特殊的地方。

    比如说我们创建一个"animal.pike"文件并输入:

    string name;
    
    float weight;
    
    void create(string n, float w)
    {
      name = n;
      weight = w;
    }
    
    void eat(string food)
    {
      write(name + " eats some " + food + ".\n");
      weight += 0.5;
    }
    

    通过下面的方式把上面的这个文件当做一个类来用:

    constant animal = (program)"animal.pike";
    animal piglet = animal("Piglet", 6.3);
    

    继承

    多态的基础就是继承。继承能够带来代码重用,多态能够在运行时确定代码段的调用,解除代码耦合并带来更好的扩展性和灵活性。

    比如说我们前面定义的动物类,可以作为父类衍生出下面这些子类:

    class bird
    {
      inherit animal;
      float max_altitude;
    
      void fly()
      {
        write(name + " flies.\n");
      }
    
      void eat(string food)
      {
        write(name + " flutters its wings.\n");
        ::eat(food);
      }
    }
    
    class fish
    {
      inherit animal;
      float max_depth;
    
      void swim()
      {
        write(name + " swims.\n");
      }
    }
    

    可以像这样调用两个新的子类:

    bird tweety = bird("Tweety", 0.13);
    tweety->eat("corn");
    tweety->fly();
    tweety->max_altitude = 180.0;
    
    fish b = fish("Bubbles", 1.13);
    b->eat("fish food");
    b->swim();
    
    animal w = fish("Willy", 4000.0);
    w->eat("tourists");
    w->swim();
    

    访问控制

    pike类的成员变量默认是public的,这并不是一个好的做法。比较好的做法是,隐藏不该公开的所有信息。

    值得注意的是:pike的static跟C++不一样,pike的static意味着成员只能被自己或者子类访问。这其实类似于protect。local变量声明的方法,意味着尽管被子类重载了,但是在这个类中还是使用这个本地的方法。

    语句

    语句包括有if、switch、for、while、do-while等。

    基本语法与C相同,感觉无需赘述了。

    写代码时,三元表达式是一个不错的选择,max_value = (a > b) ? a : b;非常用,而且理解上也不难。

    foreach语句是一个不错的工具,可以用来遍历一组数据进行操作。形如:

    foreach( container , loop-variable) 
    statement
    

    容器放前面,迭代器放后面,这似乎与其他语言的顺序是相反的。

    有三种方法提前离开循环:

    使用return
    使用throw
    使用exit终止程序

    特殊语句

    空语句

    while(!finish())
    ;
    

    catch语句

    形如:

     mixed result = catch
      {
        i = klooble() + 2;
        fnooble();
        j = 1/i;
      };
    
      if(result == 0)
        write("Everything was ok.\n");
      else
        write("Oops. There was an error.\n");
    

    后面的错误处理模块会更多的讨论catch语句。

    更多关于数据类型的事情

    int

    如果想要判断变量是否为int,用intp(??)。

    如果想要一个随机数,用random(limit)。

    如果想要翻转bit,那么使用reverse(int)。需要注意的是,int是有符号的32位整数,因此reverse一个正数会转变为一个负数。

    float

    同理:

    floatp -- 判断类型

    四舍五入:

    floor -- 下舍入,去掉小数点后面的数字。配合(int)f,转换为正数。

    ceil -- 上舍入,也就是说不管小数点后面是啥都往前进位。

    string

    注意pike的string都是双引号的。

    pike的string使用了著名的慢拷贝技术,剩下的你懂的。

    同理:

    stringp -- 判断类型

    array

    前面对于array讨论了很多。看看例子差不多了:

    array(string) b;     // Array of strings
    b = ({ "foo", "bar", "fum" });
    b[1] = "bloo";       // Replaces "bar" with "bloo"
    
    array(string) a1;       // a1 contains 0
    a1 = ({ });             // Now a1 contains an empty array
    array(int) a2 = ({ });  // a2 contains an empty array
    
    write(a[0]);
    b[1] = "bloo";
    c[1] = b[2];
    
    array(array(int)) aai = ({
      ({ 7, 9, 8 }),
      ({ -4, 9 }),
      ({ 100, 1, 2, 4, 17 })
    });
    
    array(string) a = ({ "foo", "bar" });
    array(string) b = a;
    array(string) c = ({ "foo", "bar" });
    

    同理:

    arrayp -- 判断类型

    截取:({ 1, 7, 3, 3, 7 })[ 1..3 ] = ({ 7, 3, 3 })

    array(int) a = ({ 7, 1 }); a == b;会返回0,及时a和b是相等的,但是由于使用的是完全不同的两块内存,也就是地址不同,所以其实不相等。

    真正比较两个array看起来是否相等用equal。

    支持集合操作:

    | -- 联合
    & -- 交集

    • -- A排除B的元素
      ^ -- 排除两方都有的元素
      / -- 用B把A切分成array的array,比如:
      ({ 7, 1, 2, 3, 4, 1, 2, 1, 2, 77 }) / ({ 1, 2 }) gives the result ({ ({ 7 }), ({ 3, 4 }), ({ }), ({ 77 }) }) .
      size 数量
      allocate(size) 预分配
      reverse 翻转
      search 返回第一个找到的元素位置,如果不存在返回-1
      has_value 这个只判断是否存在这个元素
      replace(array, old, new) 替换(用==)

    mapping

    先来看一些代码熟悉一下mapping:

    ([ "beer" : "cerveza", "cat" : "gato", "dog" : "perro" ])
    
    mapping(string:string) m;
    mapping(int:float) mif = ([ 1:3.6, -19:73.0 ]);
    mapping(string:string) english2spanish = ([
      "beer" : "cerveza",
      "cat" : "gato",
      "dog" : "perro"
    ]);
    
    mapping(string:float) m1;  // m1 contains 0
    m1 = ([ ]);   // Now m1 contains an empty mapping
    mapping(int:int) m2 = ([ ]);
                  // m2 contains an empty mapping
    
    write(english2spanish["cat"]); // Prints "gato"
    english2spanish["dog"] = "gato";
        // Now, english2spanish["dog"] is "gato" too
    english2spanish["beer"] = english2spanish["cat"];
        // Now, all values are "gato"
    
    

    看起来其实就是Python里面的字典类型吧。通过键值对来存放数据。当然C++的STL里面也有mapping,大致和这个是一样的,区别在于pike的mapping定义时需要用([])扩住,有点麻烦。

    mapping里面的顺序是无关系的,估计主要原因是以B树的形式存储,进入容器后会被重新排序。

    如果想要查找一个mapping中不存在的key,那么value会返回0:

    english2spanish["cat"]     // Gives "gato"
    english2spanish["glurble"] // Gives 0
    

    注意如果放入mapping的是一个对象的话,会有一些问题:

    mapping(array(int) : int) m = ([ ]);
    array(int) a = ({ 1, 2 });
    m[a] = 3; //ok
    write(m[({ 1, 2 })]) //error
    

    mapping也提供了一些函数:

    mappingp(some) :检查是否mapping

    == 和 equal:==判断两个是否指向同一个东西,equal判断两个是否元素都相同。

    indices():返回一个包含所有key的array

    values():返回一个包含所有value的array

    mkmapping(index-array, value-array):通过一个现成的index array和value array来创建mapping。

    mapping1|mapping2:就是数学里的“联合”。如果两边都有的话(可能value不同),右手边优先。"+"是"union"的同义词啦。

    mapping1 & mapping2:两边都有的才会返回,且如果value不一致,右手边优先。

    mapping1 - mapping2:将mapping1中不在mapping中的元素给挑出来

    mapping1 ^ mapping2:异或的作用是找到两个mapping的不同点。

    sizeof(mapping):返回mapping的size

    search(haystack, needle):逆向查找value的key,如果有多个也只返回第一个。如果不存在会返回编译error。

    replace(mapping, old, new):替换旧的value为新的value

    zero_type(mapping[index]):查询一个index是否存在于mapping当中。如果存在则返回一个0。不存在返回一个非0。

    multiset

    set就是集合,包含一堆数据,且数据不重复。如果需要重复数据的话,就要用multiset,这种数据类型用 (< >)来包裹。

    还是那样的,如果只是这样multiset(string) m1;,m1就只是个0而已。如果想要的是空集合的话,应该这样才对:m1 = (< >);

    直接看代码了解一下multiset的基本使用先:

    if(dogs["Fido"])
      write("Fido is one of my dogs.\n");
    if(!dogs["Dirk"])
      write("Dirk is not one of my dogs.\n");
    dogs["Kicker"] = 1; // Add Kicker to the set
    dogs["Buster"] = 0; // Remove Buster
    

    multiset支持集合并和减操作,比如说:

    dogs |= (< "Kicker" >); // Add Kicker to the set
    dogs -= (< "Buster" >); // Remove Buster
    

    multiset跟mapping一样,也是没有顺序的,不同顺序的multiset使用equal的比较是一样的。

    multiset提供的一些操作:

    multisetp(multiset):判断是否是一个multiset

    == 和 equal:和mapping相同啦

    集合的操作:| - & ^ 和前面的mapping都差不多,不再赘述了。

    其他的参数类型

    program

    感觉看不太懂,比较有用的可能就是通过类名来创建对象:

    program-name() or program-name(arguments)
    

    判断是不是一个程序:

    programp(something)
    

    object

    感觉没有太好说的,看函数吧:

    objectp(some):判断some是否为一个object

    根据类名创建一个对象:program-name() or program-name(arguments)

    destruct(object):析构一个对象,如果对象里面有一个destroy方法,会被优先调用。一般来说不用显示的destroy一个对象,pike有自动的垃圾回收器。

    访问一个对象:和C++访问一个指针是一样的。

    function

    看代码:

    void write_one(int x)
    {
      write("Number: " + x + "\n");
    }
    
    int main()
    {
      array(int) all_of_them = ({ 1, 5, -1, 17, 17 });
      map(all_of_them, write_one);
      return 0;
    }
    
    function w = write;
    w("Hello!\n");
    

    提供的客户端:

    functionp:判断是否是一个函数

    function_name(funciton_object):得到方法对象的名字。

    字符串

    字符串的操作方法

    ==/+/-/连接/index/切片(({ 1, 7, 3, 3, 7 }) [ 1..3 ]

    除法

    比较特别的是string的除法:

    "abcdfoofoo x" / "foo"  == ({ "abcd", "", " x" });
    
    abcdfoofoo x" / 5 ==  ({ "abcdf", "oofoo" });
    
    "abcdfoofoo x" / 5.0 ==  ({ "abcdf", "oofoo", " x" });
    

    关于除以int和float的区别,上面的代码一眼就能看出来。

    取模

    看代码一眼就懂了:

    "abcdfoofoo x" % 5 == " x";
    

    乘法

    看代码:

    ({ "7", "1", "foo" })  ":" == "7:1:foo";
    

    string 的内置函数

    stringp(something):判断一个对象是否是字符串

    sizeof/replace/lower_case/upper_case/String.capitalize(string)/

    search(haystack, needle):比如search("sortohum", "orto") == 1;

    sprintf格式化生成字符串

    用到直接看连接:sprintf格式化字符串

    sscanf格式化提取字符串

    用到直接看连接:sscanf提取字符串

    宽字符串

    就是除了8bit字符串之外的都叫宽字符串啦(中文编码这些)。

    String.width(string):检测是否包含宽字符串

    string_to_utf8(string data):转换编码为utf8

    utf8_to_string(string utf8_encoded_data):转为原生的pike编码

    表达式

    基本的加减乘除取模不再赘述了。

    可查通过查询得到隐式类型变换:隐式类型变换表

    对于位操作符,可通过查表:位操作符表格

    切片操作:

    array(int) iii = ({1,2,3,4,5});
    iii[1..3] = ({2,3,4})
    

    赋值

    值得留意的是群体赋值:

    int i;
    string s;
    float f1, f2;
    
    [ i, s, f1, f2 ] = ({ 3, "hi", 2.2, 3.14 });
    

    类型转换

    跟c差不多:

    (float)14    // Gives the float 14.0
    (int)6.9    // Gives the int 6
    (string)6.7    // Gives the string "6.7"
    (float)"6.7"    // Gives the float 6.7
    

    pike支持一个特殊的类型:mixed的。这个类型能够存储任何类型的数据。

    如果需要对于mixed类型做类型转换:

    mixed m = 8;
    int i = [int]m;
    

    逗号操作符

    总是返回逗号右边的那个值:

    7 + 3, 6 * 2 // Gives 12
    3,14         // Gives 14 (and not pi)
    

    call and splice

    如果我想把一个array里面的元素作为参数传给函数怎么做?(好奇怪的想法..)

    array a = ({ 17, -0.3, "foo" });
    koogle(@a);
    
    equivalent
    
    koogle(17, -0.3, "foo");
    

    优先级

    运算符的优先级可以通过查询表格:运算符优先级

    预处理

    c++推荐使用const完全代替macro的使用。我觉得pike也应该是这样的。

    #define MAX_TEMP 100当然可以用,但是并不推荐。

    const MAX_TEMP = 100是更好的选择。

    当然,预处理也可以写一些简单的函数:

    #define square(x) x * x
    

    但是这样子写函数要注意,macro是直接替换的,而不是调用函数栈,所以容易存在算数优先级不明确的问题。

    最好不要用include。用真正的继承比较好(这里不太明白???):

    inherit .somefile;
    

    macro比较能用的地方时声明源文件的字符编码:

    #charset <*charset-name*>
    

    可能这也是为什么没有废掉macro的原因所在吧。

    默认的字符集是 iso8859-1,可以换成utf-8或者iso2022.

    神奇的预处理常量

    LINE:表示现在处于哪一行

    DATA:变成month day year的时间

    TIME:变成24小时制的时间:hh:mm:ss

    模块

    模块是一系列的插件。甚至可以用c或者c++来写。

    pike提供了一系列的模块:

    Stdio:标准输入输出

    GTK:图形图像

    Image:图片处理

    Protocols:网络络协议

    MIME:用来编码和解码MIME

    Crypto:加密(我喜欢)

    Calendar:日历

    Sql:数据库操作相关

    Thread:多线程

    Process:多进程

    Getopt:命令行参数

    LR:语法分析器

    Yp:网络信息系统的支持

    Gz:解压缩文件

    Regexp:正则表达式的匹配

    如何使用这些模块

    比如说标准输入:

    string name = Stdio.stdin->gets();
    

    比如说网络:

    Protocols.HTTP.Query web_page;
    

    如果我们不想写前缀:

    import Stdio;
    import Protocols.HTTP;
    

    如果两个模块的函数名有冲突,会使用最新import的模块,谨记,这种错误很难被发现,所以要特别小心!!!

    创建模块

    用c和c++来创建模块不再这个讨论范围内,让我们来定义一个简单的模块吧:

    创建一个trig.pmod文件。

    输入:

    float cos2(float f)
    {
      return pow(cos(f), 2.0);
    }
    
    constant PI = 3.1415926535;
    

    如何使用这些自定义模块呢?

    int main()
    {
      write("The square of cos(pi/4) is " +
        .trig.cos2(.trig.PI/4) + ".\n");
      return 0;
    }
    

    当然也可以导入后再用:

    import .trig; // Import the module from this directory
    
    int main()
    {
      write("The square of cos(pi/4) is " +
        cos2(PI/4) + ".\n");
      return 0;
    }
    

    pike是如何找模块的?

    大概遵循这个步骤:

    如果前缀有.表示在本地目录下查找

    如果有路径,包含路径名

    在add_module_path中的路径

    在命令行中用-M 指定的路径

    在环境变量中的PIKE_MODULE_PATH

    内置模块目录中的:/usr/local/pike/7.4.1/lib/modules/ or C:\Program Files\Pike\lib\pike\modules

    pike是如何找到这个文件的呢?

    查找到module-name.pmod文件,拷贝

    查找到module-name.pmod目录,创建一个包含目录下所有文件的文件出来

    查找到module-name.pmod.pike文件,拷贝

    查找到module-name.so,文件会动态的链接c和c++编译的库。

    错误处理

    pike包括warning和error两种类型的警告。

    waring通常不会显示出来,通过声明#pragma strict_types才能显示warning。

    或者也可以再运行pike的时候这样:

    pike -rT myprogram.pike
    

    效果一样的。

    pike里面,空对象会默认赋值为0。所以使用对象前都需要判断一下是否为0.

    处理错误的方式:

    1、终止程序并打印错误

    if(result_of_something == 0)
    {
      werror("Failed to open the file called '" +
             file_name + "'\n");
      exit(1);
    }
    

    2、输出错误到文件里面

    webbrowser.pike cod.ida.liu.se > output.txt

    错误码

    不同类型的错误有不同的错误码。

    比如说文件打开失败的错误:

    Stdio.File localfile = Stdio.File();
    if(!localfile->open(file_name, "r"))
    {
      werror("Couldn't open '" + file_name + "'.\n");
      werror(strerror(localfile->errno()) +
             " (errno = " + localfile->errno() + ").\n");
      exit(1);
    }
    

    通过localfile->errno()来获取错误码。

    catch-throw

    这部分可能无需赘述,直接看代码吧:

    if(result_of_something == 0)
      throw("Failed to open the file called '" +
            file_name + "'\n");
    
      mixed result = catch {
        i = klooble() + 2;
        fnooble();
        j = 1/i;
      };
      if(result == 0)
        write("Everything was ok.\n");
      else
        write("Oops. There was an error.\n");
    
    void drink_coffee()
    {
      if(coffe_pot == 0)
        throw("No coffe-pot.");
    }
    
    void eat_dinner()
    {
      eat_main_course();
      eat_dessert();
      drink_coffee();
    }
    
    int main()
    {
      mixed result = catch {
        eat_dinner();
      };
      if(result == 0)
        write("Everything was ok.\n");
      else
        write("There was an error: " + result + "\n");
    
      return 0;
    }
    
    int eat_dinner()
    {
      if(eat_main_course() == 0)
        return 0;
      if(eat_dessert() == 0)
        return 0;
      if(drink_coffee() == 0)
        return 0;
      return 1;
    }
    
    mixed result = catch {
      koogle(0, 3.0, "foo");
    };
    
    if(result == 0)
      write("Everything was ok.\n");
    else if(objectp(result))
    {
      write("There was an error.\n");
      write("Type of error: " + result->error_type + "\n");
      write("Description of the error:\n");
      write(result->describe());
      write("Done.\n");
    }
    else {
      write("There was some other type of error.\n");
    }
    

    相关文章

      网友评论

          本文标题:pike学习笔记

          本文链接:https://www.haomeiwen.com/subject/uyfpqttx.html