• homework-08


    上次作业中,已经提到了C++ 11的特性。不过,光说不练假把式,这次作业中,我们就对此进行验证。

    进行测试的4个项目分别为:

    1.变量作用域和生命周期

    2.堆和栈

    3.unique_ptr和shared_ptr

    4.分割url

     

    为了保证测试的有效性,先要检测编译器对于C++ 11的支持情况。以下是目前主流编译器的支持情况:

    http://developer.51cto.com/art/201303/384630.htm

    由于Clang编译器对于C++ 11的支持比较不错,所以本次我们就选择了Clang作为编译环境

     

    从中我们可以看到,编译器是3.3版本,支持本次我们需要用到的所有特性。

    1.变量作用域和生命周期

    这个测试主要是让我们理解变量作用域的概念,所以我们可以使用如下代码:

    int main()
    {
        int v = 1;
        cout << "In level 1: v=" << v << endl;
        {
            int v = 2;
            cout << "In level 2: v=" << v << endl;
        }
        cout << "Back to level 1: v=" << v << endl;
        return 0;
    }

    main第一层的v只管第一层,第二层的v只管第二层,第二层的v不会影响到第一层的。如图所示:

    运行结果如下:

    与上述解释相符。

    2.堆和栈

    堆和栈是一个容易上新手感到困惑的概念。其实很简单,只要这样理解:栈空间会自动消失,堆空间如果不释放,就不会消失。就类似第一个问题里面,栈的变量都是局部变量,出了那个局部,变量就消失了。比如如下代码:

    #include <iostream>
    using namespace std;
    int *getValueInStack()
    {
        int *v;
        *v=9210;
        return v;
    }
    int *getValueInHeap()
    {
        int *v;
        v = new int;
        *v=9210;
        return v;
    }
    int main()
    {
        cout << "In heap: v=" << *getValueInStack() << endl;
        cout << "In stack: v=" << *getValueInHeap() << endl;
        return 0;
    }

    getValueInStack是从栈里面获得一个变量

    getValueInHeap是从堆里面获得一个变量

    现在的编译器已经十分智能了,帮我们发现了这个错误,并给出了警告。如果我们不管这个警告,继续执行的话,就会产生非法访存的段错误:

    但是,当我把main()函数里两句话换一下位置以后,再加上点修改,就产生了奇妙的现象:程序能输出一个结果,不过非常诡异。

    #include <iostream>
    using namespace std;
    int *getValueInStack()
    {
        int *v;
        *v=9210;
        cout << "In getValue(): v=" << *v << endl;
        return v;
    }
    int *getValueInHeap()
    {
        int *v;
        v = new int;
        *v=9210;
        cout << "In getValue(): v=" << *v << endl;
        return v;
    }
    int main()
    {
        cout << "In heap: v=" << *getValueInHeap() << endl;
        cout << "In stack: v=" << *getValueInStack() << endl;
        return 0;
    }

    这段代码是在我输入错误的时候打进去的,可是却能神奇的输出结果。对于这个奇妙的现象,我在Windows 8.1(编译环境Visual Studio 2013)和Mac(Clang & LLVM 3.3)下都进行了测试。居然是不一样的,windows下这里会报错。

    由于这个错误,我猜测Windows和Mac有着微妙的差别:Windows编译器对参数是从右往左解析的,Mac是从左往右的。所以Mac在执行getValueInStack之前已经输出了"In stack:"字符串,所以getValueInStack返回的地址的空间先前已经被字符串指针申请过了,所以不会报错。而windows是从右向左的,执行函数之前,那片空间还没有被申请,所以就产生了非法访问。

    3.unique_ptr和shared_ptr

    这个真的是一个激动人心的想法,本来C语言的内存泄漏问题就比较严重,有了这个以后就可以在很大程度上避免这个问题。

    先说unique_ptr,这个的意义就在于一块空间只能有一个指针指向它。下面一张图表示了一个空间指针的交接:

    unique_ptr是不能直接传值的,比如如下代码在编译时就会直接报错:

    #include <iostream>
    #include <memory>
    using namespace std;
    int main()
    {
        std::unique_ptr<int>p1(new int(5));
        std::unique_ptr<int>p2=p1;
        return 0;
    }

    为了实现这个转移功能,我们就需要修改代码:

    #include <iostream>
    #include <memory>
    using namespace std;
    int main()
    {
        std::shared_ptr<int>p1(new int(5));
        std::shared_ptr<int>p2 = p1;
        cout << *p1 << endl;
        cout << *p2 << endl;
        return 0;
    }

    move()函数进行了交接操作,p1内存归p2所有,p1变成无效指针,运行起来能输出p1,输出p2就会产生错误

    然后就顺利完成了

    unique_ptr的意义在于,有效防止了指针悬挂,以及由此引起的非法访问操作。

    shared_ptr

    感觉这个就像个超级保姆,有效避免了内存泄漏。

    #include <iostream>
    #include <memory>
    using namespace std;
    int main()
    {
        std::shared_ptr<int>p1(new int(5));
        std::shared_ptr<int>p2 = p1;
        cout << *p1 << endl;
        cout << *p2 << endl;
        return 0;
    }

    shared_ptr的意义在于,统一管理了指针的分配,在没有指针指向空间的时候立即释放空间,很大程度上避免了内存泄漏。

    4.url分割

    要求:

    1. 类的定义和使用,基本成员是否完整

    2. 输入参数的检查及其他鲁棒性的考虑

    3. STL和C++11元素的使用

    4. 除http://之外, 是否有考虑ftp:// site:// 等情况

    5. 是否考虑url中的中文

    6. 算法是否简洁高效

    7. 代码风格

     C语言实现

    我的代码做到了

    绝对robust,保证不会有溢出,哪怕100W的字符进来也不会

    对于所有符号通吃

    url中文也毫无压力

    算法是O(1)复杂度

    代码风格规范

    #include <stdio.h>
    #define isChar(x) (x>='a'&&x<='z'||x>='A'&&x<='Z'||x>='0'&&x<='9'||x=='-'||x<0)
    int main()
    {
        char c;
        int inWord = 1;
        while ((c=getchar())!='
    ') {
            if (isChar(c)) {
                inWord = 1;
                printf("%c", c);
            } else if (inWord) {
                printf(", ");
                inWord = 0;
            }
        }
        printf("
    ");
        return 0;
    }

    中文的实现主要在于字符的判断

    以上的代码十分简单,但是有个小问题,不支持"://"的判断,不过不要紧,稍加改动就可以:

    #include <stdio.h>
    #define isChar(x) (x>='a'&&x<='z'||x>='A'&&x<='Z'||x>='0'&&x<='9'||x=='-'||x<0)
    int main()
    {
        char c;
        int inWord = 1, readHead = 0;
        while ((c=getchar())!='
    ') {
            if (isChar(c)) {
                inWord = 1;
                printf("%c", c);
            } else if (inWord) {
                printf(", ");
                if (!readHead) {
                    if (c != ':') break;
                    if (getchar() != '/') break;
                    if (getchar() != '/') break;
                    readHead = 1;
                } else {
                    inWord = 0;
                }
            }
        }
        if (!readHead) {
            printf("
    Not a valid URL!");
        }
        printf("
    ");
        return 0;
    }

    经过这样的修改,程序就具有了超强的鲁棒性完全不怕数据溢出,哪怕几千万个字节的输入也都可以分割。

    程序也有了超强的性能内存占用几乎为0,可以以超高的吞吐量处理流数据

    中文的支持,统统能够分割。

    简洁的代码

    url完整性检查

    最后,还有跨平台(Windows和OS X),跨编码集的(GBK与UTF-8)支持:

    C++代码(使用STL):

    #include <iostream>
    #include <string>
    #include <vector>
    #define isChar(x) (x>='a'&&x<='z'||x>='A'&&x<='Z'||x>='0'&&x<='9'||x=='-'||x<0)
    using namespace std;
    
    vector<string> split(string s)
    {
        int i = 0, begin, inWord = 0;
        vector<string> ret;
        for (i=0;i<s.size();i++) {
            if (!inWord && isChar(s[i])) {
                begin = i;
                inWord = 1;
            } else if (inWord && !isChar(s[i])) {
                ret.push_back(s.substr(begin, i-begin));
                inWord = 0;
            }
        }
        return ret;
    }
    
    int main()
    {
        string s;
        int i;
        getline(cin, s);
        s = s+'
    ';
        if (s.find("://") == string::npos) {
            cout << "not a url" << endl;
            return 0;
        }
        vector<string> v = split(s);
        if (v.size() > 0) {
            cout << v[0];
        }
        for (i=1;i<v.size();i++) {
            cout << ", " << v[i];
        }
        cout << endl;
        return 0;      
    }

    使用了两个类,一个是srting,另一个vector。先判断是否有字串”://”,然后就进行分割操作即可。分割的结果存入STL提供的vector中。

     

  • 相关阅读:
    web service--基础概念(1)
    java web--国际化 i18n
    洛谷 P3842 [TJOI2007]线段
    洛谷 P6205 [USACO06JAN]Dollar Dayz S
    洛谷 P5414 [YNOI2019]排序
    洛谷 P1681 最大正方形II
    洛谷 P2327 [SCOI2005]扫雷
    洛谷 P1373 小a和uim之大逃离
    洛谷 P4317 花神的数论题
    洛谷 P4127 [AHOI2009]同类分布
  • 原文地址:https://www.cnblogs.com/yzong/p/3428632.html
Copyright © 2020-2023  润新知