美文网首页
Coursera C++ Part B [Week1] C++进

Coursera C++ Part B [Week1] C++进

作者: 小啾Kris | 来源:发表于2019-09-30 21:57 被阅读0次

    C++ Part B是C++进阶课程,bf
    课程网址 https://www.coursera.org/learn/c-plus-plus-b/home/welcome

    course overview

    • Introduction to the STL library
    • Iterator categories and examples
    • Containers and algorithms
    • Lambda expressions, functions and algorithms

    参考书

    • C++ for C Programmers, ch. 7
    • C++ by Dissection, ch. 6-7

    1. More Standard Template Library

    2. New features of C++, such us semantics and lambda expressions

    • enum class
      相比于enum更能保证类型安全
    enum color{RED, BLUE};
    enum spotlight{RED, GREEN};
    // 如果在一个scope下会导致编译器错误
    

    enum class会自动定义成int,但是也可以特化为别的类

    enum class Color: short{RED,BLUE,GREEN};
    
    • some new libraries
      <regrex> -regular expression
      <thread> -threading
      <unordered_map> -hash based map; 普通的图在stl中是基于红黑树,普通的日志操作需要log(N)复杂度
      <array> -固定长度的数组,vector是可变长度
      <forward_list> -singly linked list
    // 一段实现序列平方的例子
    #include <iostream>
    #include <iterator>
    #include <fstream>
    #include <vector>
    using namespace std;
    
    template<typename FowardIterator>
    void square(FowardIterator first, FowardIterator last){
        for(; first!=last;first++)
            *first = (*first)*(*first);
    }
    int main(){
        ...... //省略 w could be anything like a vector<int>
        square(w.begin(), w.end());
        for (auto i:w) //range for
            cout << i <<'\t'
        cout<<endl;
    }
    

    3. Iterator categories and examples

    1). 单项指针
    用C++计算扑克牌同花顺的概率

    // 定义花色类和数字类来表示扑克牌
    enum class suit:short{SPADE, HEART, DIAMOND, CLUB} //用short相比int和float更加节省内存
    
    class pips{
    public:
        pips(int val):v(val){assert(v>0 && v<14);}
        friend ostream& operator<<(ostream& out, const pips& p);
        int get_pips(){return v;}
    private:
        int v;
    }
    
    //用suit 和 pips表示扑克牌
    class card{
    public:
        card():s(suit:SPADE),v(1){}
        card(suit s, pips v):s(s),v(v){}
        friend ostream& operator<<(ostream& out, const card& c);
        suit get_suit(){return s;}
        pips get_pips(return v;}
    private:
        suit s;
        pips v;
    }
    ostream& operator<<(ostream& out, const card& c){
        cout<<c.v<<c.s;
        return out; 
    }
    
    //建立card向量
    void int_deck(vector<card>& d){
        for (int i=1;i<14;++i){
            card c(suit:: SPADE, i);
             d[i-1] = c;
        }
        for (int i=1;i<14;++i){
            card c(suit::HEART, i);
            d[i+12] = c;
        }
        for (int i=1; i<14;++i){
            card c(suit::DIAMOND, i);
            c[i+25] = c
        }
        for (int i=1; i<14;++i){
            card c(suit::CLUB, i);
            c[i+38] = c
        }
    }
    
    void print(vector <card>& deck){
        for(auto p=deck.begin();p!=deck.end();++p)
            cout<<*p;
        cout<<endl;
    }
    //print 的另一种写法
    void print(vector<card>& deck){
        for(auto cardval:deck)
            cout<<cardval;
        cout<<endl;
    }
    //判断是否是同花
    bool is_flush(vector <card> & hand){
        suit s = hand[0].get_suit();
        for(auto p= hand.begin()+1; p!=hand.end();++p)
            if(s!=p->get_suit())
                return false;
         return true;
    }
    //判断是否连顺
    bool is_straight(vector<card>& hand){
        int pips_v[5], i=0
        for(auto p=hand.begin();p!=hand.end();++p)
            pips_v[i++] = (p->get_pips()).get_pips();
        sort(pips_v, pips_v+5);  // stl iterator range
        if (pips_v[0]!=1) //没有A
            return(pips_v[0]==pips_v[1]-1&&
                       pips_v[1]==pips_v[2]-1&&
                       pips_v[2]==pips_v[3]-1&&
                       pips_v[3]==pips_v[4]-1);
        else //有A
            return(pips_v[0]==pips_v[1]-1&&
                       pips_v[1]==pips_v[2]-1&&
                       pips_v[2]==pips_v[3]-1&&
                       pips_v[3]==pips_v[4]-1)||
                       pips_v[1]==10&&pips_v[2]==11&&
                       pips_v[3]==12&&pips_v[4]==13;
    }
    bool is_straight_flush(vector<card> & hand){
        return is_flush(hand)&&is_straight(hand);
    }
    // set up simulation
    int main(){
        vector<card> deck(52);
        srand(time(0));
        init_deck(deck);
        int how_many; 
        int flush_count=0; 
        int str_count = 0;
        int str_flush_count = 0;
        cout<<'How many shuffles?';
        cin>>how_many;
        for(int loop=0;loop<how_many;++loop){
            random_shuffle(deck.begin(), deck.end()); //stl algorithm
            vector<card> hand(5);
            int i = 0;
            for (auto p = deck.begin();i<5;++p)
                hand[i++] =  *p;
            if (is_flush(hand))
                flush_count++;
             if(is_straight(hand))
                 str_count++;
             if(is_straight_flush(hand))
                 int str_flush_count++;
        }
        cout <<'Flushes'<<flush_count<<'out of'<<how_many<<endl;
        cout <<'Straights'<<str_count<<'out of'<<how_many<<endl;
        cout <<'Straight Flushes'<<str_flush_count<<'out of'<<how_many<<endl;
    }
    

    2)双向指针BidirectionalIterator
    双向指针支持双向移动,既有++又有--运算。
    STL库中一个用双向指针实现的经典的算法就是reverse()

    template<typename T>
    void reverse(BidirctionalIterator first, BidirctionalIterator last);
    
    //用双向指针检查是否是回文序列
    template<typename Bidirectional>
    bool isPalindrome(Bidirectional first, Bidirectional last){
        while(true){
            lass--;
            if(first==last)//assume >= undefined
                break;
            if(*first != *last)
                return false;
            first++;
            if(first == last)
                break;
        }
        return true;
    }
    

    3)随机指针 Random access iterator

    • 随机指针必须在O(1)实现查找
    • 可以对指针进行加减运算且运算可逆
    • 可以和其他随机指针比较大小
      STL中sort算法就是通过随机指针实现的快速排序
    template<class RandomAccessIterator>
    void sort(RandomAccessIterator first, RandomAccessIterator last);
    

    用随机指针实现随机选出元素

    #include<csddef> //ptrdiff_t 是signed integral type
    template<typename RandomAccess>
    RandomAccess pickRandEI(RandomAccess first, RandomAccess last){
        ptrdiff_t temp = last-first;
        return first+rand()%temp;
    }
    

    4.容器和算法

    • 非变异算法
      该算法不会修改所使用的的类的内容,一个典型算法是搜索并返回其位置。
      经典算法如下
    template<class InputIter, Class T>
    InputIter find(InputIter  b, InputIter e, const T& t); // 搜索t
    

    在STL中经常可以看到算法的另一种表示

    template<class InputIter, Class Predicte>
    InputIter find_if(InputIter  b, InputIter e, Predicte p);
    

    在这个版本中,我们搜索谓词而不是值,这样的形式增加了函数的功能
    另一个非变异算法还有的还有

    template<class InputIter, Class Function>
    InputIter for_each(InputIter  b, InputIter e, Function f);// apply f for value in range b to e
    

    5. Lambda表达式

    C++11有个新功能lambda,类似未命名的函数

    [capture list](params list) mutable exception->return type{function body}
    // capture list: 捕获外部变量列表
    // params list: 形参列表
    // mutable指示符:  说明是否可以修改捕获的外部变量
    // exception: 异常设定
    // return type: 返回类型,可以不声明
    //Unnamed function
    [](int i){cout<<i<<endl;}// 不需要声明返回值类型,编译器会自动识别返回值
    [](int n)->int{return ++n;} // explicit,声明了返回值类型为int
    

    相关文章

      网友评论

          本文标题:Coursera C++ Part B [Week1] C++进

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