日记3----C++专用

Posted on 2020-03-23 21:20  金色的省略号  阅读(437)  评论(0编辑  收藏  举报

1、C++  基类定义有纯虚函数,则子类必须重写纯虚函数,否则不能实例化。

2、for_each   // Applies function fn  to each of the elements in the range [first,last).

/*
完成以下程序,使得输入的整数x,以及若干正整数,将
大于x的正整数输出;然后输入若干字符串,将字符串长度大于x的字符串输出
        测试用例:
        2
        5 6
        1 3 59 30 2 40
        this is hello please me ha
        1 1
        4
        this
    
    输出:
    59,30,40,
    please,
    4,
    this,
*/

#include <algorithm> //for_each 头文件 算法
#include <iostream>
#include <string>
#include <vector>

using namespace std;


class Printer
{
    int size;
    
public:
    Printer(int x) : size(x) {}
    
    void operator()(int x)      //运算符()重载
    {
        if (x > size)
            cout << x << ',';
    }
    
    void operator()(string str) //运算符()重载
    {
        if (str.size() > size)
            cout << str << ',';
    }
};

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int x,n;
        cin >> x >> n;
        
        vector<int> intVec;
        for(int i = 0; i < n; ++i)
        {
            int y;
            cin >> y;
            intVec.push_back(y);
        }
        for_each(intVec.begin(), intVec.end(), Printer(x)); 
        cout << endl;
        
        vector<string> strVec;
        for(int j = 0; j < n; ++j)
        {
            string str;
            cin >> str;
            strVec.push_back(str);
        }
        for_each(strVec.begin(), strVec.end(), Printer(x));
            cout << endl;
    }
    
    return 0;
}
View Code

仿写 for_each ( func 函数模板  )

//模板实例化
Printer func (vector<string>::iterator first, vector<string>::iterator last, Printer fn )
{
  while (first!=last) {
    fn(*first);
    ++first;
  }
    return pn;
}*/

template<class InputIterator, class Function>
Function func (InputIterator first, InputIterator last, Function fn )
{
  while (first!=last) {
    fn(*first);
    ++first;
  }
    return fn;
}
View Code

3、c++ string 类对象str,str.erase(remove_if(str.begin(), str.end(), ispunct), str.end()); ,其中string类的成员函数erase,begin,end;remove_if函数包含在<algorithm>头文件,ispunct函数包含在<cctype>头文件,<iostream>包含<cctype>头文件;

#include <iostream>
#include <map>
#include <string>
#include <algorithm>
using namespace std;

/*单词计数器 */

string& strip(string &str)
{
    for (auto &ch : str)     
        ch = tolower(ch);// 转成小写
    str.erase( remove_if ( str.begin(), str.end(), static_cast<int(*)(int)>(&ispunct) ), str.end());

    return str;
};

std::map<std::string, std::size_t> count()
{
    std::map<std::string, std::size_t> counts;
    for (string w; cin >> w; ++counts[strip(w)])
        ;
    return counts;
}

void println(std::map<std::string, std::size_t> const &m)
{
    for (auto const &kv : m)
    {
        cout << kv.first << " -- " << kv.second << endl;
    }
} 

int main()
{
    println(count());
    cin.clear(); 
    return 0;
}
View Code

4、anacona 下载镜像站 https://pypi.tuna.tsinghua.edu.cn/simple

5、tensorflow,安装在windows上,import 出错的原因,是版本太高,不支持旧的cpupip install tensorflow==2.0.0 -i https://pypi.tuna.tsinghua.edu.cn/simple,python, import tensorflow as tf,查看安装目录,tf.__path__

6、pycharm安装新的社区版,设置Settings,(1) 、去掉提示信息,tools,勾上Server Certificates accepted non-trusted certificates auto;(2)、project interpreter

7、CSDN,Chinese Software Developer Network; MSDN,Mcrosoft Developer Network

8、键盘缓冲区的数据只有当遇到回车键时才送到 输入流缓冲区否则,留在键盘缓冲区里,没到输入流缓冲区里去

9、在二进制、八进制和十六进制下,101分别是十进制的什么数值? 二进制:101=1*2^2 + 0*2^1 + 1*2^0 = 5;八进制同理,101 = 1*8^2 + 0*8^1 + 1*8^0 = 65;十六进制同理,101 =  1*16^2 + 0*16^1 + 1*16^0 = 257

10、如果计算机有32根地址总线,则其存储器的最大容量可达 4 GB

11、创建锚点链接,用户能够快速定位到同一页的<li id="bb">目录内容</li> 方法正确的是,<a href="#bb">链接文本</a> 

12、python-docx库,读取word文档内容,jieba库,计算词频,wordcloud库,文档词云

13、Python不支持char数据类型;Python 中允许把多条语句写在同一行

14、C++在new时的初始化的规律可能为:对于有无参构造函数的类,不论有没有括号,都调用无参构造函数;如果没有构造函数,则调用默认构造函数(编译器自动生成),不加括号的new只分配内存空间,不进行内存的初始化,而加了括号的new会在分配内存的同时初始化为0。

15、用父类指针指向new出来的子类对象,对这个父类指针变量进行delete操作,父类的析构函数应该是虚函数,否则,子类的析构函数不会被调用,会造成内存泄漏

16、char *p = new char[65];  // 分配一个大小为65的char数组;  char *p = new char(65); //分配一个char ,并用65来初始化值

17、变量与参数:数组的数组 char c[8][10];  char (*c)[10]; \\数组指针;  指针数组 char *c[10];  char **c;  \\ 指针的指针;  数组指针(行指针) char (*c)[10]; char (*c)[10]; \\不改变;指针的指针 char **c; char **c;  \\ 不改变

18、ptr里存放的是一个内存地址,那么*ptr就是这个内存地址里存放的数据

19、静态类型即类型指针或引用的字面类型;而动态类型即类型指针或引用的实际类型。 这一对概念一般发生在基类和派生类之间

class Base
{
     //.....
};

class Derived : public Base
{
     //.....
};

Base *sbp = new Base; //静态类型与动态类型都是 Base*
Base *dbp = new Derived; //静态类型为 Base*,动态类型为 Derived*
View Code

20、当一个类有子类时,该类的析构函数必须是虚函数,原因:会有资源释放不完全的情况 

21、类的成员函数的返回值类型为类中定义的类型,该成员函数在类外定义时,前面必须加上关键字typename类作用域说明

22、switch的case常量不可以重复

23、sizeof不计算类静态数据成员的空间

24、常对象,调用常函数

#include <iostream>
using namespace std;

class A{
public:
    void fun()const{
        cout << "fun()const" << endl;
    }
    void fun(){
        cout << "fun()" << endl;
    }
};

int main()
{
    A a;
    a.fun();
    const A b; //常对象,调用常函数,函数重载
    b.fun();
    return 0;
}
View Code

25、类的const数据成员,构造函数进行初始化

26、友元类

#include <iostream>
using namespace std;

class A{
    int x;
public:
    friend class B; //友元类
    A():x(10){}
    void fun(){
        cout << "fun()" << endl;
    }
};

class B{
public:
    void fun(A &a){  //B类的成员函数相当于A类的成员函数
        cout << a.x << endl;  //相当于类内
    }
};
int main()
{
    A a;
    //cout << a.x << endl; // 类外不可, x私有的
    B b;
    b.fun(a);
    return 0;
}
View Code

27、一个类的成员函数可以声明为另外一个类的友元函数

28、类与类之间的关系:使用关系(use),组合关系(has),继承关系(is)

29、对数组名求值,将获得数组的首地址,数组名不是指针,是数组

30、const char* s { "Hello" }; // c++11标准,字符串是const的,因此不可以把一个字符串初始化一个char*,应该是const char*

31、不能重载的运算符  点操作符.  作用域操作符::  指向成员操作的指针操作符.* .->   条件操作符?:  sizeof  预处理符号#

32、参数的第一个操作数是普通类型的,而不是类类型的,不可以使用成员函数进行运算符重载,只能用普通函数或友元函数实现运算符的重载,没有类作用域

33、当一元运算符的操作数或者二元运算符的左操作数是该类的一个对象时,重载运算符函数为成员函数

34、不能用类的友元函数重载实现的运算符=   ()   []   ->

35、运算符的重载,关系运算符 >  <   ==   >=   <= ,自增自减运算符 ++  -- ,赋值运算符 = ,下标运算符 [] ,流操作运算符  <<    >>

36、当一个运算符的操作需要修改类对象状态时,应该以成员函数重载;如果以友元函数重载,可以使用引用参数修改对象

37、数组名是一个指针常量,如,int* const p;

38、成员函数,运算符重载,返回值类型,作为左值的返回类对象的引用,作为右值的返回类对象

39、运算符重载和构造函数

    ​在运算符重载的时候,参数的第一个操作数是普通类型的,使用普通函数,不能使用成员函数;当一元运算符的操作数或者二元运算符的左操作数是该类的一个对象时,重载运算符函数为成员函数;当一个运算符的操作需要修改类对象状态时,应该以成员函数重载;

    ​类的成员函数的概念是面向对象的,数据与行为绑定在一起,表示数据行为的成员函数可以修改数据,且有访问控制;普通函数不具有上述性质;
View Code
#include <iostream>
#include <cstring>
using namespace std;
class Student{
private:
    int id;
    char name[20];
public:
    Student(int id = 0, char *name = "ssdut"):id(id){strcpy(this->name,name);}
    Student(Student &s):id(s.id){strcpy(name,s.name); }
    void show(){ cout << "id = " << id << ", name = " << name << endl;}
    void setName(char *n){ strcpy(name,n);}
};
int main()
{
    Student s0; //无参构造
    s0.show();  //显示函数
    Student s1(1,"Zhang San"); //有参构造
    s1.show();
    Student s2; //无参构造
    s2.setName("Li Si");  //设定函数
    s2.show();
    Student s3 = s1; //调用拷贝构造
    s3.show();
    Student s4(2);//转换构造
    s4.show();    
    return 0;
}
View Code
#include <iostream>
using namespace std;
class Rational{
    int m;   // 分母
    int n;   // 分子
public:
    Rational(int nn=1,int mm=1); //构造
    bool setM( int ); // 设置分母,注意不能为零
    void setN( int );  //设置分子
    Rational  R_add( const Rational& A);   //加法操作, 返回和对象
    void  R_sub(Rational & A, Rational &B);     //减法操作A-B
    Rational  R_mul(Rational & A);    //乘法操作,返回乘积对象
    void R_div(Rational & A, Rational &B); //除 A/B
    void simple( );  //约分
    void print(); //以分数形式显示,注意约分和符号
};
Rational::Rational(int nn, int mm):n(nn), m(mm){}
bool Rational::setM( int mm){ m = mm; }
void Rational::setN( int nn ) { n = nn; }
Rational  Rational::R_add( const Rational& A){
    return Rational(n*A.m+m*A.n, m*A.m);
}
void Rational::R_sub(Rational & A, Rational &B){
    n = A.n*B.m-A.m*B.n;
    m = A.m*B.m;
}
Rational  Rational::R_mul(Rational & A){
    return Rational(n*A.n,m*A.m);
}
void Rational::R_div(Rational & A, Rational &B){
    n = A.n*B.m;
    m = A.m*B.n;
}
void Rational::simple( ){
    if( n<0 && m<0 || n*m<0&&m<0 ){
        n = -n;
        m = -m;
    }
    int tn = n<0 ? -n : n;
    int t = tn<m ? tn : m;
    while(t){
        if(tn%t==0 && m%t==0) break;
        t--;
    }
    n /= t;
    m /= t;
}
void Rational::print(){
    simple();
    cout << n << " / " << m << endl;
}
int main()
{
    Rational r0;
    Rational r1(1,2);
    Rational r2(2,-3);
    r0 = r1.R_add(r2);
    r0.print();
    
    r0.R_sub(r1,r2);
    r0.print();
    
    r0 = r1.R_mul(r2);
    r0.print();
    
    r0.R_div(r1,r2);
    r0.print();
    return 0;
}
View Code

40、C++语言是从SIMULA语言和C语言两种语言发展来的

41、cin对象指定输入域宽的两种方法分别是,用操作符setw ()和直接调用width();setw()需要包含头文件 #include <iomanip>,width()是输入流类成员函数,cin对象调用

42、当变量超出它的作用域时就一定会被销毁,这句话是错的,比如函数的静态变量,它的生存期与程序相同,即使没有调用函数或函数调用结束,它都存在

43、实参的数据类型必须与形参的相同,这句话是错的,实参到形参会进行隐式类型转换

44、指向整型数的指针可以强制类型转换为指向char类型的指针

45、不可以将被调用函数内部的变量地址传递到调用函数,因为被调函数变量作用域局限于被调函数

#include <iostream>
using namespace std;

void InitBinStr(char *BinStr);
void NumToBinStr(char *BinStr, int n, int index);
void solution( const char *IpStr, char *BinStr );

int main()
{
    char IpStr[33],BinStr[33];
    cin >> IpStr;
    
    InitBinStr( BinStr );
    solution( IpStr, BinStr );
    
     return 0;
}

void InitBinStr(char *BinStr){ 
    char *p = BinStr; //为了更好理解 其实形参可以直接使用p
    for(int i=0; i<32; ++i) //赋值
        *p++ = '0';
    *p = '\0';  //保存二进制的字符数组,最后有个字符串结束符
}

void NumToBinStr(char *BinStr, int n, int index){
    while(n){
        BinStr[index--] = n%2 + '0';
        n /= 2;
    }
}

void solution( const char *IpStr, char *BinStr ){
    const char *p = IpStr; // 为了更容易书写
    for(int n=0,index=7; index<32; p++ )
    {        
        //if(*p && *p != '.')//读数字
        if(*p>='0' && *p<='9')
        {
            n = n*10 + *p - '0'; 
            continue;    
        }

        /* if((*p>'9' || *p<'0') && *p!='.'){
            cout << *p;
            cout<<"data error"<<endl;  
            return;
        } */
        if(*(p+1)=='.'){
            cout<<"data error"<<endl;  
            return;
        }
        NumToBinStr(BinStr,n,index);//遇到'.'或字符串读完 转换二进制
        index += 8;    //步长8
        n = 0;      //数字归零
    }
    if(*p){
        cout<<"data error"<<endl;  
        return;
    }
    cout << BinStr << endl;    
}
View Code

46、虚基类的构造函数在非虚基类之前调用

47、公有继承时,基类中的private成员在派生类中仍然是private的的说法是错误的,因为基类的private成员除了基类自己的成员函数以及基类自己的友元外,别的根本不能访问,就更不用说访问权限了

48、当派生类从基类公有继承时,不能 用派生类对象为基类对象赋值

49、C++的流格式控制符,与输出格式成员函数功能基本是一样的;流格式控制符一般与符号 << 联用包含头文件 #include <iomanip>

50、ofstream的对象,用来写文件

51、标准模板库,map,multimap的键是唯一的,set,multiset只有键,没有值,set的键是唯一的,multiset的键可以重复,map是无序的,set是有序的

52、结构体作为map的键 first,要求结构体有比较函数,set的键为对象时,对象要求有比较函数 -- 友元函数 或者 常函数 ( const函数 ,函数小括号后加 const )

#include <map>
#include <iostream>

struct  Test 
{
    int x;
    int y;

    bool operator < (const Test &o) const/* 键比较大小*/
    {
        return x < o.x || y < o.y;
    } 
};

int main()
{
    std::map<Test, std::string> mapTest;
    Test test = { 1, 2 };
    mapTest[test] = "Test1";  
     
    for (auto it = mapTest.begin(); it != mapTest.end();it++)
    {
        std::cout << it->first.x << " " << it->first.y << " " << it->second.c_str() << std::endl;
    } 

    return 0;
}
View Code
#include <iostream>
#include <set>
using namespace std;

struct weapon
{
    int number;
    int power;
    weapon(int n,int p):number(n),power(p) //构造
    {
        
    }
    bool operator < (const weapon &w) const/* 键比较大小 const 函数(常函数)*/
    {
        return number < w.number;
    } 
    /* friend bool operator < (const weapon& w1,const weapon& w2)//比较函数 ( 友元 )
    {
        return w1.number < w2.number;
    } */
}sword(0,100),bomb(1,101),arrow(2,102);

int main()
{
    set<weapon> wSet;
    
    wSet.insert(arrow); // 102
    wSet.insert(sword); // 100
    wSet.insert(bomb);  // 101
    
    set<weapon>::iterator it = wSet.begin();
    
    cout << it++ -> power << endl;  //100
    cout << it++ -> power << endl;  //101
    cout << it++ -> power << endl;  //102
    
    return 0;
}
View Code

53、二进制文件写读操作

#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;

int main()
{
    char  ss[100] = "Hello"; 
    char  s[100];
    
    ofstream file1("file.dat",ios::binary);
    file1.write((char*)ss, strlen(ss));
    file1.close();    
    
    ifstream in("file.dat",ios::binary);
    /* in.getline(s,strlen(ss)+1); // +1 字符串结束符的空间
    cout << s;*/
    while(in){
        char c;    
        in.get(c);
        if(in)
            cout << c;    
    }
    in.close();
    return 0;
}
View Code

54、函数子

#include<iostream>
#include <vector>
#include <algorithm>  //for_each 需要的头文件
using namespace std;

struct D {
    int num;
    D(int i=0) {num = i; }
};
struct print_D{
    void operator()(const D* d)const{
        cout << "I am D. my num=" << d->num << endl;
    }
};

int main()
{
    vector<D*> V;
    V.push_back(new D(1));
    V.push_back(new D(2));
    V.push_back(new D);
    V.push_back(new D(3));
    for_each(V.begin(), V.end(), print_D());  // print_D()  struct print_D 的对象
    return 0;
}
View Code

55、类型的名字(包括类的名字)本身也是一种运算符,即类型强制转换运算符,类型强制转换运算符是单目运算符,也可以被重载,但只能重载为成员函数,不能重载为全局函数,(类型名)对象或者类型名(对象),这个对对象进行强制类型转换的表达式就等价于对象.operator类型名() ,即变成对运算符函数的调用

56、int a[] = {1,2,3,4};   &a 是指向一个有4个元素的int数组的指针(类型是 int(*)[4]),测试代码:

#include<typeinfo>
#include<iostream>
using namespace std;

int main()
{
    int a[4] = {1, 2, 3, 4};
    cout << typeid(&a).name() << endl; //类型PA4_i
    return 0;
}
View Code
#include<typeinfo>
#include<iostream>
using namespace std;

int main()
{
    int a[4] = {1, 2, 3, 4};
    int (*p)[4] = &a;
    cout << *p[0] << endl; // 1
    return 0;
}
View Code

57、面向对象筛法求素数

#include <iostream>
#include <cstring>
#include <cmath>

class ShowPrime{
public:
    ShowPrime(): isPrime(NULL),n(0){ }
    void display(int n){
        solvePrime(n);
        show(n);
    }
    ~ShowPrime(){ delete []isPrime; }
    
private:
    void solvePrime(int n){    
        if(this->n < n){            
            init(n);        
            for(int i=2; i<sqrt(n);++i)
                if(isPrime[i]) shift(i);
        }        
    }
    void init(int n){
        delete []isPrime;
        this->n = n;
        isPrime = new int[n];
        memset(isPrime,1,n*sizeof(int));
    }
    void shift(int i){
        for(int j=2*i; j<n; j+=i)
            isPrime[j] = 0; //划掉不是素数的数
    }
    void show(int n){
        for(int j=2; j<n; ++j)
            if(isPrime[j])
                printf("%d ", j);
        printf("\n");
    }
    
private: 
    int n;
    int *isPrime;
};

int main()
{
    ShowPrime sp;
    sp.display(50);
    sp.display(100);
    
    return 0;
}
View Code

58、读写文件

#include<iostream>
#include<fstream>
#include <cstring>
using namespace std;

class Student {
    char name[20];
    int score;
public:
    void writefile();
    void readfile();
    void modify();
    void search();
};

void Student::writefile() {
    ofstream OutFile("student.dat", ios::out | ios::binary);
    if (!OutFile) {
        cout << "error" << endl;
        exit(0);
    }
    cout << "请输入学生的姓名和成绩";
    while (cin>>this->name>>this->score){
        OutFile.write((char*)&(*this), sizeof(*this));
    }
    cin.clear();
    OutFile.close();
}
void Student::readfile() {
    ifstream inFile("student.dat", ios::in | ios::binary);
    if (!inFile) {
        cout << "error" << endl;
        exit(0);
    }
    while (inFile.read((char*)&(*this), sizeof(*this))) {
        cout << this->name <<"," << this->score << endl;
    }
    inFile.close();
}
void Student::modify() {
    fstream iofile("student.dat", ios::in |ios::out| ios::binary);
    if (!iofile) {
        cout << "error" << endl;
        exit(0);
    }
    char name[20];
    cout << "请输入要修改的信息的同学名字:";
    cin >> name;
    int pos=0;
    while (iofile.read((char*)this, sizeof(*this))){
        if (strcmp(name, this->name) == 0) {
            cout << "请输入修改后的名字、分数:";
            cin >> this->name >> this->score;
            
            iofile.seekp(pos * (sizeof(*this)), ios::beg);            
            iofile.write((char*)this, sizeof(*this));
            
            break;
        }
        pos++;
    }
    iofile.close(); 
    /*
    Student s;       
    fstream ioFile("student.dat", ios::in|ios::out);//用既读又写的方式打开
    if(!ioFile) {
        cout << "error" ;
        return ;
    }
    
    char name[20];
    cout << "请输入要修改的信息的同学名字:";
    cin >> name;
    
    int pos = 0;
    while( ioFile.read((char *)&s, sizeof(s)) ){    
        int tmp = strcmp( s.name,name);
        if(tmp == 0) { //找到了
            cout << "请输入学生的姓名和成绩";
            cin >> name >> score;    
            strcpy(s.name,name);
            s.score = score;
            
            ioFile.seekp(pos*sizeof(Student),ios::beg);
            ioFile.write((char*)&s, sizeof(s));
            break;
        }
        pos++;
    }*/ 
    /* 
    ioFile.seekg(0,ios::end); //定位读指针到文件尾部,
                              //以便用以后tellg 获取文件长度
    int L = 0,R; // L是折半查找范围内第一个记录的序号
                  // R是折半查找范围内最后一个记录的序号
    R = ioFile.tellg() / sizeof(Student) - 1;
    //首次查找范围的最后一个记录的序号就是: 记录总数- 1
    do {
        int mid = (L + R)/2; //要用查找范围正中的记录和待查找的名字比对
        ioFile.seekg(mid *sizeof(Student),ios::beg); //定位到正中的记录
        ioFile.read((char *)&s, sizeof(s));
        int tmp = strcmp( s.name,name);
        if(tmp == 0) { //找到了
            cout << "请输入学生的姓名和成绩";
            cin >> name >> score;    
            strcpy(s.name,name);
            s.score = score;
            ioFile.seekp(mid*sizeof(Student),ios::beg);
            ioFile.write((char*)&s, sizeof(s));
            break;
        }
        else if (tmp > 0) //继续到前一半查找
            R = mid - 1 ;
        else  //继续到后一半查找
            L = mid + 1;
    }while(L <= R); 
    ioFile.close();
    */   
}
void Student::search() {
    ifstream iofile("student.dat", ios::in | ios::out | ios::binary);
    if (!iofile) {
        cout << "error" << endl;
        exit(0);
    }
    char name[20];
    cout << "请输入要修改的信息的同学名字:";
    cin >> name;
    while (iofile.read((char*)&(*this), sizeof(*this))) {
        if (strcmp(name, this->name) == 0) {
            cout << this->name << "  " << this->score << endl;
        }
    }
}
class Test{
    Student s;
public:
    void run(){        
        char select = '0';
        while (select != '5') {
            cout << "建立文件请输1"<<endl;
            cout << "输出文件请输2" << endl;
            cout << "修改文件某个信息3" << endl;
            cout << "查找某个同学信息4" << endl;
            cout << "退出输入5" << endl;
            cin >> select;
            switch (select) {
            case'1':
                s.writefile();
                break;
            case'2':
                s.readfile();
                break;
            case'3':
                s.modify();
                break;
            case'4':
                s.search();
                break;
            }            
        } 
    }
};
int main() {
    Test t;
    t.run();
    system("pause");
    return 0;
}
View Code

59、临时对象是右值可以用const来绑定const是只读模式

60、继承层次的根类,定义虚析构函数

61、任意非static成员函数都可是虚函数,保留字只在类内部的成员函数声明中出现,不能用在类定义体外部出现的函数定义上

62、派生类只能通过派生类对象访问其基类的protected成员,在派生类的成员函数里,基类的对象也不能访问protected成员
用作基类的类必须是已定义的,只声明了类,没有定义,则不可以作为基类
在某些情况下,希望覆盖虚函数只要在调用函数的前面加上基类作用域就可以调用基类的函数

63、父类赋值给子类,要写强转构造函数,即类型转换,子类可以赋值给父类

class A
{
    
};

class B:public A
{
public:
    B():A(){}
    B(const A& a):A(a){ } //强转, A 转为 B    
};  //父类赋值给子类,缺少子类的成员,所以要写强转

int main()
{
    A a;
    B b;
    b = (B)a;  //可以写成 b = a;  
    //a = b;   //子类对象可以赋值给父类对象,因为子类包含父类
    return 0;
}
View Code

64、map 的 clear() 操作

#include <iostream>  
#include <map>
using namespace std;  
 
class A{
public:
    int i;
    A():i(100){}
    ~A(){ cout << "~A" << endl; }
};
 
int main()
{
    
    map<int, A*> m;
    
    m[0] = new A();
    m[1] = new A();
    
    delete m[0]; //释放内存
    
    cout << m.size() << endl; //没有删除元素的操作
    
    m.clear(); //删除所有元素( 指针 ),不释放指针指向的内存
    cout << "----------------------" << endl;
    
    return 0;
}
View Code

65、时间 计算类

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class Date
 5 {
 6     int day,month,year;    
 7 public:    
 8     Date(int year=2000,int month=1,int day=1):
 9         year(year),month(month),day(day)
10     {
11     }
12     void SetDate(int year, int month,int day){
13         this->year=year;
14         this->month=month;
15         this->day=day;
16     }
17     bool IsLeapYear(){
18         return (year%4==0&&year%100!=0||year%400==0);
19     }
20     bool IsEndofMonth(){
21         int m[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
22         if(IsLeapYear())
23             m[2]++;
24         return day==m[month];
25     }
26     void print_ymd(){
27         cout << year << "-" << month << "-" << day << endl;
28     }
29     
30     int DayCalc(){
31         int date=0, m[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
32         for(Date d; d.year<year;d.year++){
33             date+=365;
34             if(d.IsLeapYear())
35                 date++;
36         }
37         if(IsLeapYear())
38             m[2]++;
39         for(int i=1; i<month;  ++i)
40             date+=m[i];
41         date+=day;
42         return date;
43     }    
44     void AddDay(int n){
45         for(int i=1;  i<=n; ++i){
46             day++;
47             if(IsEndofMonth()){
48                 day++; //月份或年份进位
49                 if(month<12){
50                     day=1;
51                     month++;
52                 }
53                 else{
54                     day=1;
55                     month=1;
56                     year++;
57                 }
58                 day--//外面多加抵消
59             }                
60         }
61     }
62 };
63 
64 int main()
65 {
66     Date d1,d2;
67     int y,m,d;
68     d1.print_ymd();  //2000-1-1
69     
70     cin >>y>>m>>d;    //2016 5 16
71     d1.SetDate(y,m,d);
72     d1.AddDay(365);   //+365
73     d1.print_ymd();   //2017 5 16
74     
75     cin >>y>>m>>d;
76     d2.SetDate(y,m,d);
77     d2.print_ymd();
78     
79     cout << d2.DayCalc()-d1.DayCalc() << endl;
80     return 0;
81 }
View Code

66、C++关键字

C++11中有73个关键字
一、数据类型相关
1booltruefalse
   bool即为布尔类型,属于基本类型中的整数类型,取值为真和假。true和false是具有布尔类型的字面量,为右值,即表示真和假。
注:字面量:用于表达源代码中一个固定值的表示法。

2char、wchar_t
   表示字符型和宽字符型这些整数类型(属于基本类型),但一般只专用于表示字符。char(和signed char、unsigned char一起)事实上定义了字节的大小。char表示单字节字符,wchar_t表示多字节字符

3intdoublefloatshortlong、signed、unsigned
  signed和unsigned作为前缀修饰整数类型,分别表示有符号和无符号。signed和unsigned修饰char类型,构成unsigned char和signed char,和char都不是相同的类型;不可修饰wchar_t、char16_t和char32_t。其它整数类型的signed省略或不省略,含义不变。signed或unsigned可单独作为类型,相当于signed int和unsigned int。
  double和float专用于浮点数,double表示双精度,精度不小于float表示的浮点数。long double则是C++11指定的精度不小于double的浮点数。

4explicit
    该关键字的作用就是避免自定义类型隐式转换为类类型。

5、auto 
   auto关键字会根据初始值自动推断变量的数据类型。不是每个编译器都支持auto。
   例:
       auto  x = 7;  //使用整数7对变量x进行初始化,可推断x为int型。
       auto  y=1.234;  //使用浮点数1.234对变量y进行初始化,可推断y为double型。

二、语句相关
1switchcasedefault
   switch分支语句的起始,根据switch条件跳转到case标号或defalut标记的分支上。

2doforwhile
  循环语句的组成部分,C和C++都支持这3种循环。

3、if和else
   条件语句的组成部分。if表示条件,之后else表示否定分支。

4break、cotinue、goto 
   break用于跳出for、while循环或switch语句。continue用于调到一个循环的起始位置。goto用于无条件跳转到函数内得标号处。一般情况不建议使用goto,风险较大。

三、定义、初始化相关  

1constvolatile
   const和volatile是类型修饰符,语法类似,用于变量或函数参数声明,也可以限制非静态成员函数。const表示只读类型(指定类型安全性,保护对象不被意外修改),volatile指定被修饰的对象类型的读操作是副作用(因此读取不能被随便优化合并,适合映射I/O寄存器等)。
  volatile:
  a、当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中,以后再取变量值时,就直接从寄存器中取值。
  b、优化器在用到volatile变量时必须每次都小心地重新读取这个变量的值,而不是使用保存到寄存器里的备份。
  c、volatile适用于多线程应用中被几个任务共享的变量。

2enum
  构成枚举类型名的关键字。

3、export
  使用该关键字可实现模板函数的外部调用。对模板类型,可以在头文件中声明模板类和模板函数;在代码文件中,使用关键字export来定义具体的模板类对象和模板函数;然后在其他用户代码文件中,包含声明头文件后,就可以使用该这些对象和函数。
4extern
  当出现extern “C”时,表示 extern “C”之后的代码按照C语言的规则去编译;当extern修饰变量或函数时,表示其具有外部链接属性,即其既可以在本模块中使用也可以在其他模块中使用。

5publicprotectedprivate
   这三个都为权限修饰符。public为公有的,访问不受限制;protected为保护的,只能在本类和友元中访问;private为私有的,只能在本类、派生类和友元中访问。

6、template
    声明一个模板,模板函数,模板类等。模板的特化。

7static
    可修饰变量(静态全局变量,静态局部变量),也可以修饰函数和类中的成员函数。static修饰的变量的周期为整个函数的生命周期。具有静态生存期的变量,只在函数第一次调用时进行初始化,在没有显示初始化的情况下,系统把他们初始化微0.

8structclass、union
  用于类型声明。class是一般的类类型。struct在C++中是特殊的类类型,声明中仅默认隐式的成员和基类访问限定与class不同(struct是public,class是private)。union是联合体类型。满足特定条件类类型——POD struct或POD union可以和C语言中的struct和union对应兼容。
注:POD类型(Plain Old Data),plain---代表普通类型,old---代表可以与C语言兼容。

9、mutable
  mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。

10virtual
    声明虚基类,虚函数。虚函数=0时,则为纯虚函数,纯虚函数所在的类称为抽象类。

四、系统操作相关
1catchthrowtry
   用于异常处理。try指定try块的起始,try块后的catch可以捕获异常。异常由throw抛出。throw在函数中还表示动态异常规范。
2newdelete
   new、delete属于操作符,可以被重载。new表示向内存申请一段新的空间,申请失败会抛出异常。new会先调用operator new函数,再在operator new函数里调用malloc函数分配空间,然后再调构造函数。delete不仅会清理资源,还会释放空间。delete县调用析构函数,其次调用operator delete函数,最后在operator delete函数里面调用free函数。malloc申请内存失败会返回空。free只是清理了资源,并没有释放空间。
3、friend
  友元。使其不受访问权限控制的限制。例如,在1个类中,私有变量外部是不能直接访问的。可是假如另外1个类或函数要访问本类的1个私有变量时,可以把这个函数或类声明为本类的友元函数或友元类。这样他们就可以直接访问本类的私有变量。
4、inline
   内联函数,在编译时将所调用的函数代码直接嵌入到主调函数中。各个编译器的实现方式可能不同。

5operator   
   和操作符连用,指定一个重载了的操作符函数,比如,operator+6、register
  提示编译器尽可能把变量存入到CPU内部寄存器中。

7、typename
    typename关键字告诉编译器把一个特殊的名字解释为一个类型。

五、命名相关
1using
     (1)、在当前文件引入命名空间,例using namespace std;
     (2)、在子类中使用,using声明引入基类成员名称。
2namespace
  C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。命名空间除了系统定义的名字空间之外,还可以自己定义,定义命名空间用关键字“namespace”,使用命名空间时用符号“::”指定。

3、typedef
    typedef声明,为现有数据类型创建一个新的名字。便于程序的阅读和编写。

六、函数和返回值相关
1void
    特殊的""类型,指定函数无返回值或无参数。
2return
  return表示从被调函数返回到主调函数继续执行,返回时可附带一个返回值,由return后面的参数指定。return通常是必要的,因为函数调用的时候计算结果通常是通过返回值带出的。如果函数执行不需要返回计算结果,也经常需要返回一个状态码来表示函数执行的顺利与否(-1和0就是最常用的状态码),主调函数可以通过返回值判断被调函数的执行情况.
3sizeof
   返回类型名或表达式具有的类型对应的大小。
4、typeid
    typeid是一个操作符,不得不提的是RTTI(Run-Time Type Identification,运行时类型识别),其实就是说在运行期得到对象的实际的类型,这立刻使我们想到了“可以通过基类的指针和引用可以指向实际的派生类型”,这就是typeid这个强大操作符所做的事,该操作符的返回类型是type_info的标准库类型的引用 , 这是定义在标准库的一个类类型class type_info,该类的拷贝构造函数以及赋值操作符被定义为private,这是禁止复制该类型的对象,创建type_info对象的唯一方法,便是调用typeid操作符,该类中最常用的成员函数name函数,该函数的返回类型是一个C风格的字符串,用于表示类型的id,该函数同样是一个异常安全的函数,即不抛出异常
七、其他

1this
    每个类成员函数都隐含了一个this指针,用来指向类本身。this指针一般可以省略。但在赋值运算符重载的时候要显示使用。静态成员函数没有this指针。
2、asm
   _asm是一个语句的分隔符。不能单独出现,必须接汇编指令。一组被大括号包含的指令或一对空括号。
例:
    _asm
    {
        mov al,2
        mov dx,0xD007
        out al,dx
    }
也可以在每个汇编指令前加_asm
    _asm  mov al,2
    _asm  mov dx,0xD007
    _asm  out al,dx

3、*_cast
   即 const_cast、dynamic_cast、reinterpret_cast、static_cast。
   C++类型风格来性转换。const_cast删除const变量的属性,方便赋值;dynamic_cast用于将一个父类对象的指针转换为子类对象的指针或引用;reinterpret_cast将一种类型转换为另一种不同的类型;static_cast用于静态转换,任何转换都可以用它,但他不能用于两个不相关的类型转换。
View Code

67、矩阵相乘

#include<iostream>
using namespace std;

int main()
{   //当矩阵A的列数等于矩阵B的行数时,A与B可以相乘
    //矩阵C的行数等于矩阵A的行数,C的列数等于B的列数
    int a[3][4]={1, 2, 3, 4,
                 5, 6, 7, 8,
                 9, 10,11,12};
    int b[4][4]={1, 2, 3, 4,
                 5, 6, 7, 8,
                 9, 10,11,12,
                 13,14,15,16};
    int c[3][4] = {0};
    
    //x=3,y=4,z=4
    //a[x][y],b[y][z],c[x][z]
    
    int x=3,y=4,z=4;
    
    for(int i=0; i<x; i++){
        for(int j=0; j<z; ++j){
            for(int k=0; k<y; ++k){//k是a的列,b的行
                c[i][j]+=a[i][k]*b[k][j]; //通项式
            }            
        }
    }
    
    for(int i=0; i<x; i++){
        for(int j=0; j<z; ++j){            
                cout << c[i][j] << "\t";        
        }
        cout << endl;
    }
    return 0;
}
View Code

68、数组的引用传递

#include<iostream>
using namespace std;

template<typename T,int N>
void f(const T (&arr)[N]){
    cout << sizeof(arr)/sizeof(T) << endl;
    //arr[0]=50;
}

int main()
{
    int arr[20]={ 100 };
    f(arr);
    cout << arr[0];
    return 0;
}
View Code

69、huffman树,数组存储

#include<fstream>
#include<vector>
#include<map>
#include<string.h>
#include<iostream>
#include<limits.h>
#include <queue>
using namespace std;

typedef struct {
    int weight;
    int parent, lchild, rchild;
}HTNode, *HuffmanTree;


//查处权值最小且双亲为0的2的节点
void Select(HuffmanTree HT, int len, int& s1, int& s2)
{
    int i, min1 = INT_MAX, min2 = INT_MAX; //先赋予最大值
    for (i = 1; i <= len; i++)
    {
        if (HT[i].weight < min1 && HT[i].parent == 0)
        {
            min1 = HT[i].weight;
            s1 = i;
        }
    }
    int temp = HT[s1].weight; //将原值存放起来,然后先赋予最大值,防止s1被重复选择
    HT[s1].weight = INT_MAX;
    for (i = 1; i <= len; i++)
    {
        if (HT[i].weight < min2 && HT[i].parent == 0)
        {
            min2 = HT[i].weight;
            s2 = i;
        }
    }
    HT[s1].weight = temp; //恢复原来的值
}

void CreateHffmanTree(HuffmanTree& HT, int n, map<char, int> ms);
int main()
{
    char ch;
    vector<char>v1;
    map<char, int> ms;                        //关联性容器,键值对形式,创建一个map对象,key是字母,value是出现次数 
    map<char, int>::iterator p, mEnd;        //创建两个map迭代器

    ifstream infile;
    infile.open("WData.txt", ios::in);
    if (!infile.is_open())
    {
        cout << "读取文件失败" << endl;
        return 0;
    }

    //逐行读取文件中的字符(包括空格)
    while ((ch = infile.get()) != EOF)
    {
        v1.push_back(ch);
        cout << ch;
    }

    for (int i = 0; i < v1.size(); i++)                 //对于s的每个字符 
    {
        p = ms.find(v1[i]);                         //在迭代器中查找该字符
        if (p != ms.end())                            //如果没有查找到最后一个
            p->second++;                            //对应字符个数+1
        else                                         //如果ms中并没有该字符 
            ms.insert(pair<char, int>(v1[i], 1));    //插入 
    }

    p = ms.begin();
    mEnd = ms.end();
    int count = 0;
    for (; p != mEnd; p++) {
        printf("%c:%d\n", p->first, p->second);
        count++;
    }


    /*测试容器里面的东西
    * cout << endl << endl;
    for (int i = 0; i < v1.size(); i++)
    cout << v1.at(i);
    */
    cout << endl << endl;
    for (int i = 0; i < v1.size(); i++)
        cout << v1.at(i);

    HuffmanTree HT;
    CreateHffmanTree(HT, count, ms);

    for (int i = 1; i <= count*2-1; ++i){
        cout << HT[i].weight << ",";
    }

    //cout << HT[2].weight << "," << HT[ HT[2].parent ].weight;

    cout << "哈夫曼树建立完毕!\n";/**/
    system("pause");
    return 0;
}
void CreateHffmanTree(HuffmanTree& HT, int n, map<char, int> ms) {
    int m, s1, s2, i;
    m = 2 * n - 1;
    if (n <= 1)
        return;
    map<char, int>::iterator p;
    p = ms.begin();
    HT = new HTNode[m + 1];  //0号单元未用,分配m+1个单元。0号表示根节点。

    for (int i = 1; i <= m; i++) {
        HT[i].lchild = 0;
        HT[i].rchild = 0;
        HT[i].parent = 0;
    }

    for (int i = 1; i <= n; i++,p++) // 1~n 叶节点
        HT[i].weight = p->second; //把map中映射的权值赋值。
    for (i = n + 1; i <= m; ++i)     // n+1~m 父节点
    {                             //通过n-1次的选择、删除、合并来创建赫夫曼树
        Select(HT, i - 1, s1, s2);
        //在HT[k](1≤k≤i-1)中选择两个其双亲域为0且权值最小的结点,
        // 并返回它们在HT中的序号s1和s2
        HT[s1].parent = i; //它们父亲的序号
        HT[s2].parent = i;
        //得到新结点i,从森林中删除s1,s2,将s1和s2的双亲域由0改为i
        HT[i].lchild = s1;
        HT[i].rchild = s2;                            //s1,s2分别作为i的左右孩子
        HT[i].weight = HT[s1].weight + HT[s2].weight; //i 的权值为左右孩子权值之和 //它们父亲的权值
    }
}
View Code

70、如果使用#include <iostream.h>,得到的是置于全局空间的iostream库的元素,在全局空间获取元素会导致名字冲突

71、单例模式

#include <iostream>
using namespace  std;

class Printer{
public:
    static Printer* getSingalInstance(){ //3.
        return singalPrinter;
    }
    void print(){
        cout << "SingalInstance()" << endl;
    }
private:
    static Printer* singalPrinter;  //1.
private:
    Printer(){}                     //2.
    Printer(const Printer& obj){}
};
//静态成员初始化并构造对象
Printer* Printer::singalPrinter = new Printer;

int main(int argc, char *argv[])
{
    Printer* p = Printer::getSingalInstance();
    p->print();

    return 0;
}
View Code

72、全局变量应该定义在 .cpp中,如果.h文件需要调用该变量,则需要在.h文件中添加extern关键字,若其他文件要调用该变量,则需要在文件中的变量前添加extern,可以不包含对应的.h文件,预编译、头文件都是包含在 .cpp中

73、gcc命令行,编译  .cpp  :  gcc -Og -o prog   XX.cpp  XX.cpp ,其中 prog 是编译成功后的执行文件 ( .exe ) 名字, 后面的 XX.cpp 是要编译的 .cpp文件

74、观察者模式

#include <iostream>
#include <vector>
#include <string>
using namespace std;

//前置声明
class CObserverBase;

//主题接口
class SecretaryBase{
public:
    virtual void registerObserver( CObserverBase* ob) = 0;
    virtual void notifyObserver() = 0;
    virtual ~SecretaryBase(){ cout << "~Secretary\n";} //
};

//观察者接口
class CObserverBase{ 
public:
    virtual void Update() = 0;
    virtual ~CObserverBase(){ cout << "~CObserverBase\n"; } //
};


//具体主题  包含观察者接口类,此类需要前置声明
class Secretary:public SecretaryBase{
    vector<CObserverBase*> observes;  
public:
    virtual void registerObserver( CObserverBase* ob);
    virtual void notifyObserver();
};


//具体观察者1
class NBAObserver:public CObserverBase{    
    string name;
    Secretary* sp;
public:
    NBAObserver(string name, Secretary* sp):name(name),sp(sp){
        this->sp->registerObserver(this );
    }
    virtual void Update();
    virtual ~NBAObserver(){ cout << "~NBAObserver\n";}
};
//具体观察者2
class StockObserver:public CObserverBase{    
    string name;
    Secretary* sp;
public:
    StockObserver(string name, Secretary* sp):name(name),sp(sp){
        this->sp->registerObserver(this );
    }
    virtual void Update();
};


void Secretary::registerObserver( CObserverBase* ob){
    observes.push_back(ob );
}

void Secretary::notifyObserver(){
    vector<CObserverBase*>::iterator it = observes.begin();
    while(it!=observes.end()){
        (*it) -> Update();
        it++;
    }
}

void NBAObserver:: Update(){
    cout << name << ":" << "不要看NBA了" << endl;
}

void StockObserver:: Update(){
    cout << name << ":" << "不要看股票了" << endl;
}

int main()
{    
    Secretary* sp = new Secretary();
    CObserverBase* co1 = new NBAObserver( "NBAObserver1", sp );
    CObserverBase* co2 = new NBAObserver( "NBAObserver2", sp );
    CObserverBase* co3 = new StockObserver("StockObserver1",sp);
    
    sp->notifyObserver( );
    
    
    delete co1;
    delete co2;
    delete co3;
    delete sp;
    cout << "----------------------\n";
    return 0; 
}
View Code

75、partition

#include <cstdio>

void swap(int &a, int &b ){       //1、C++ 引用
    int t=a; a=b; b=t;    
}

int isOdd(int a ){
    return a%2 == 1;
}

template<typename T, typename T1>  //2、C++函数模板
T partition(T first, T last, T1 f ){
//int * partition(int *first, int *last, int(*f)(int ) ){
    while(first!=last ){
        while(f(*first) ){   //符合条件
            ++first;
            if(first==last)
                return first;
        }
        do{                  //
            --last;
            if(first==last)
                return first;
        }while(!f(*last) );  //不符合 
        swap(*first, *last );//交换
        ++first;             //移动指针    
    }
    return first;    
}

int main()
{    
    int arr[] = {1,2,3,4,5,6,7,8,9 };
    int *bound = partition(arr, arr+9, isOdd );
    //1 9 3 7 5 6 4 8 2
    for(int *p=arr;   p!=bound; ++p )
        printf("%d ",*p );
    for(int *q=bound; q!=arr+9; ++q )
        printf("%d ",*q );
    /* for(int i=0; i<9; ++i )
        printf("%d ",arr[i] ); */
    return 0;
}
View Code

76、map

#include <iostream>
#include <algorithm>
#include <map>
#include <set>
using namespace std;

int bitAdd(int n)
{
    int sum=0;
    while(n) {
        sum+=n%10;
        n/=10;
    }
    return sum;
}

int main()
{
    freopen("d:\\1.txt","r",stdin );
    int n, m;
    cin >> n >> m;

    map<int,set<int> > mp;
    for(int i=1; i<=n; ++i) {
        mp[bitAdd(i)].insert(i);
    }

    int count=0;
    for( map<int,set<int> >::iterator it = mp.begin();it!=mp.end(); ++it) {
        for( set<int>::iterator its = (it->second).begin(); its!=(it->second).end(); ++its)
        {
            count++;
            if(count==m)
                cout << *its << ",";
        }                    
    }

    return 0;
}
View Code
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int bitAdd(int n)
{
    int sum=0;
    while(n) {
        sum+=n%10;
        n/=10;
    }
    return sum;
}

struct node {
    int num;
    node(int num):num(num) { }
    friend bool operator <(const node &a,const node &b)
    {
        if(bitAdd(a.num) == bitAdd(b.num ))
            return a.num < b.num;
        return bitAdd(a.num) < bitAdd(b.num );
    }
};

int main()
{
    freopen("d:\\1.txt","r",stdin );
    int n, m;
    cin >> n >> m;

    vector<node> v;
    for(int i=1; i<=n; ++i) {
        v.push_back(node(i) ) ;
    }

    sort( v.begin(),v.end() );
    cout << v[m-1].num;  //m-1,下标是从0开始的
    cout << endl;

    for(vector<node>::iterator it = v.begin(); it!=v.end(); ++it)
        cout << it->num << ",";

    return 0;
}
View Code
#include <iostream>
#include <algorithm>
using namespace std;

int bitAdd(int n)
{
    int sum=0;
    while(n) {
        sum+=n%10;
        n/=10;
    }
    return sum;
}

bool compare(int a, int b)
{
    if(bitAdd(a) == bitAdd(b ))
        return a < b;
    return bitAdd(a) < bitAdd(b );
}

int main()
{
    freopen("d:\\1.txt","r",stdin );
    int n, m;
    cin >> n >> m;

    int *arr = new int[n+1];
    for(int i=0; i<=n; ++i) {
        arr[i] = i;
    }

    sort( arr,arr+n+1,compare );
    cout << arr[m];
    cout << endl;

    for(int i=1; i<=n; ++i)
        cout << arr[i] << ",";
    cout << endl;

    delete[] arr;

    return 0;
}
View Code
#include <stdio.h>
#include <stdlib.h>

int bitAdd(int n){
    int sum=0;
    while(n){
        sum+=n%10;
        n/=10;
    }
    return sum;
}

int compare ( const void * a, const void * b){
    if(bitAdd( *(int*)a ) == bitAdd(*(int*)b ))
        return *(int*)a - *(int*)b;
    return bitAdd( *(int*)a ) - bitAdd(*(int*)b );            
}    

int main()
{
    freopen("d:\\1.txt","r",stdin);  

    int n, m;
    scanf("%d%d",&n,&m );
    
    int *arr = (int*)malloc( (n+1) * sizeof(int) );
    for(int i=0; i<=n; ++i){
        arr[i] = i;
    }

    qsort(arr,n+1, sizeof(int), compare );
    printf("%d\n",arr[m] );
    for(int i=1; i<=n; ++i)
        printf("%d,",arr[i] );
    free(arr );

    return 0;
}
View Code

 77、巧克力

#include <algorithm> 
#include <queue>
#include <map>

#include <iostream>
using namespace std;

const int N = 1e5+10;
struct node{
    long long a;
    long long b;
    long long c;
    int id;
}goods[N];

int x,n;

bool cmp(struct node x1, struct node x2 ){             //sort 按保质期排序
    return x1.b > x2.b;
}
struct cmp1{
    bool operator()(const node &p,const node &q){   //priority_queue  按价格排序
        return p.a > q.a;
    }
};

map<int,int> mp;

int main()
{    
    //freopen("d:\\1.txt","r",stdin );
    cin>>x>>n;
    for(int i=1; i<=x; ++i){
        cin>> goods[i].a >> goods[i].b >> goods[i].c;
        goods[i].id = i;
    }
    
    sort(goods+1,goods+n+1,cmp );              //按保质期排序
    
    long long ans = 0;
    priority_queue<node,vector<node>,cmp1 > q; //按价格排序空队列
    int j=1;
    
    for(int i=x; i>=1; i--){
        
        while(goods[j].b>=i&&j<=n ){
            //cout << j << endl;
            q.push(goods[j] );
            j++;
        }
        //cout << "Here" << endl;
        if(!q.size()){
            cout << "-1" << endl;
            return 0;
        }
        
        node temp = q.top();
        mp[temp.id]++;     //以巧克力的编号为键,计算该编号的巧克力的使用个数
        ans += temp.a;
        if(temp.c == mp[temp.id] )
            q.pop();    //从优先队列中剔除            
    }
        
    cout << ans << endl;
        
    return 0; 
}


/* 10 3
1 6 5
2 7 3
3 10 10 */
View Code

78、数字三角形

#include <iostream>
#include <cmath>
using namespace std;

#define MAX 101
int D[MAX ][MAX ], *maxSum;
int n;

int main()
{
    freopen("d:\\1.txt","r",stdin );
    cin >> n;
    for(int i=1; i<=n; ++i){
        for(int j=1; j<=i; ++j){
            cin >> D[i][j];
        }
    }
    
    for(int i=n-1; i>=1; --i){
        for(int j=1; j<=i; ++j){
            D[i][j] += max(D[i+1][j], D[i+1][j+1] ) ;
        }
    }    
    cout << D[1][1] << endl;

    return 0; 
}

/* 5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5 
*/
View Code
#include <iostream>
#include <cmath>
using namespace std;

#define MAX 101
int D[MAX ][MAX ];
int n, *maxSum;

int main()
{
    freopen("d:\\1.txt","r",stdin );
    cin >> n;
    for(int i=1; i<=n; ++i){
        for(int j=1; j<=i; ++j){
            cin >> D[i][j];
        }
    }
    maxSum = D[n];
    for(int i=n-1; i>=1; --i){
        for(int j=1; j<=i; ++j){
            maxSum[j] = max(maxSum[j], maxSum[j+1] ) + D[i][j];
        }
    }    
    cout << maxSum[1] << endl;
    
    return 0; 
}

/* 5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5 */
View Code

左右路径相差1

#include <iostream>
#include <cmath>
using namespace std;

#define MAX 101
int D[MAX ][MAX ];
int n, *maxSum;

int main()
{
    freopen("d:\\1.txt","r",stdin );
    cin >> n;
    for(int i=1; i<=n; ++i){
        for(int j=1; j<=i; ++j){
            cin >> D[i][j];
        }
    }
    maxSum = D[1];
    for(int i=2; i<=n; ++i){
        for(int j=1; j<=i; ++j){
            D[i][j] = max(maxSum[j], maxSum[j-1] ) + D[i][j];
            //cout << D[i][j] << ",";
        }        
        //cout << endl; 
        maxSum = D[i];
    }
    
    cout << max ( maxSum[(n+1)/2], maxSum[(n+2)/2] )  << endl;        
    
    return 0; 
}
View Code
#include <iostream>
#include <cmath>
using namespace std;

#define MAX 101
int D[MAX ][MAX ], *maxSum;
int n;

int main()
{
    freopen("d:\\1.txt","r",stdin );
    cin >> n;
    for(int i=1,revise=-(n/2); i<=n; ++i,++revise ){
        for(int j=1; j<=i; ++j){
            cin >> D[i][j];
        }
        for(int k=1; k<=revise; ++k ){
            D[i][k] = D[i][i-k+1] = 0;
        }
        /* for(int j=1; j<=i; ++j){
            cout << D[i][j] << ",";
        }
        cout << endl; */
    }
    
    for(int i=n-1; i>=1; --i){
        for(int j=1; j<=i; ++j){
            D[i][j] += max(D[i+1][j], D[i+1][j+1] ) ;
        }
    }    
    cout << D[1][1] << endl;

    return 0; 
}

/* 5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5 
*/
View Code

79、STL 中提供的算法对它们要操纵的数据一无所知,它所需要的一切信息都必须由Iterator取得,这样算法才能正常运行,迭代器分类标签用来进行编译期间的算法选择,这有两层意思:这个标签用来做针对迭代器的算法选择,算法选择发生在编译阶段

80、虚基类的构造

#include <iostream>
using namespace std;

class A{
public:
    int a;
    A(int a1=0):a(a1) { } //带默认值的有参构造
};

class B:virtual public A{    //virtual public A
public:
    int b;
    B(int a1=0,int b1=0):A(a1),b(b1) { }
};

class C:public virtual A{    //public virtual A
public:
    int c;
    C(int a1=0,int c1=0):A(a1),c(c1) { }
};

class D:public B, public C{
public:
    int d;
    //D(int a=0,int b=0,int c=0,int d=0):A(a),B(a,b),C(a,c), d(d) { }         //调用A的有参构造
    D(int a1=0,int b1=0,int c1=0,int d1=0):B(a1,b1),C(a1,c1), d(d1) { }     //调用A的默认值构造
};

int main()
{
    D dd(1,2,3,4 );
    cout << dd.a << endl;  // 0  //D是最远派生类,先调用A构造,B、C不再调用A构造,共享虚基类的状态
    cout << dd.b << endl;  // 2
    cout << dd.c << endl;  // 3
    cout << dd.d << endl;  // 4        
    
    return 0;
}
View Code

81、由于在STL容器中不能使用 auto_ptr,因此新的编译器可能会限制其使用,相反,如果您不想要对象的一个以上副本,则应使用std::unique_ptr;如果您需要复制指针,则应使用std::shared_ptr

82、数组与模板

#include <iostream>
using namespace std;

class Array
{
public:
    template<typename T,size_t M, size_t N >
    void display(const T(&arr)[M][N] )
    {
        for(size_t i=0;i<M; ++i){
            for(size_t j=0; j<N; ++j)
                cout << arr[i][j] << ",";
            cout <<  endl;
        }
    }
};

int main()
{
    int array[3][2] = {1,2,3,4,5,6 };
    Array a;    
    a.display(array );

    return 0;
}
View Code
#include <iostream>
#include <vector>
using namespace std;

template<typename T >
class Array
{
    vector<T> v;
public:
    void add(const T &t)
    {
        v.push_back(t);
    }
    void display()
    {
        for(auto t: v) {
            for(auto t1:t)
                cout << t1 << ",";
            cout << endl;
        }
    }
};


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

    vector<int > v0(array[0],array[0]+2) ;
    vector<int > v1(array[1],array[1]+2) ;
    vector<int > v2(array[2],array[2]+2) ;

    Array<vector<int> > td;
    td.add(v0 );
    td.add(v1 );
    td.add(v2 );
    td.display();

    return 0;
}
View Code
#include <iostream>
using namespace std;

template<typename T,size_t M, size_t N >
class Array
{
    T arr[M][N];
public:
    Array(const T(&arr)[M][N] ){
        for(size_t i=0;i<M; ++i){
            for(size_t j=0; j<N; ++j)
                this->arr[i][j] =  arr[i][j];
        }
    }
    void display( )
    {
        for(size_t i=0;i<M; ++i){
            for(size_t j=0; j<N; ++j)
                cout << arr[i][j] << ",";
            cout <<  endl;
        }
    }
};

int main()
{
    int array[3][2] = {1,2,3,4,5,6 };
    Array<int, 3, 2> a(array );    
    a.display( );

    return 0;
}
View Code
#include <iostream>
using namespace std;

template<typename T,size_t M, size_t N >
class Array
{
    T* arr;
public:
    Array(const T(&arr)[M][N] ):arr( new T( M*N*sizeof(T)) )
    {
        size_t index = 0;
        for(size_t i=0; i<M; ++i) {
            for(size_t j=0; j<N; ++j)
                this->arr[index++] = arr[i][j];
        }
    }
    void display( )
    {
        for(size_t i=0; i<M; ++i) {
            for(size_t j=0; j<N; ++j)
                cout << arr[ i*N+j ] << ",";
            cout <<  endl;
        }
    }
};

int main()
{
    int ia[3][2] = {1,2,3,4,5,6 };
    Array<int,3,2> a1(ia );
    a1.display( );
    
    double da[3][2] = {1.1,2.2,3.3,4.4,5.5,6.6 };
    Array<double,3,2> a2(da);
    a2.display( );
    
    return 0;
}
View Code

83、模板形参为模板类

#include <iostream>
#include <typeinfo>
#include <string>
#include <algorithm>
using namespace std;


template<typename T>
class B{
    
};

template<typename T>
class Less:public B<T>{
public:
    bool operator()(const T& a, const T& b)const {
        return a < b;
    }
};

template<typename T>
class Greater:public B<T>{
public:
    bool operator()(const T& a, const T& b)const {
        return a > b;
    }
};

template< template<typename > class T2 ,  typename T1>//模板形参为模板类
class A{
public:
    A(){ }
    bool operator ()()const{
        
        if(typeid(T2<T1>)!=typeid(Less<T1> ) ){            
            return 0;
        }                //cout << "Here";    
        return 1;
    }
};

int main()
{
    ;
    int a[] = {1,2,3,4,5,6 }; 
    string str[] = {"1","2","333"};
    
    /* //A< Less ,string >()() ;
    A< Less ,string > aa;
    aa.operator()(); */
        
    sort(str,str+3,Greater<string>() );
    for(auto i:str)
        cout << i << endl;
    
    
    sort(a,a+6,Greater<int>() );
    for(auto i:a)
        cout << i << endl;    
        
 
    return 0;
}
View Code

84、迭代器

#include <iostream>
#include <typeinfo>
#include <string>
#include <algorithm>
using namespace std;

template<typename  T>
class MyIterator{ // 迭代器
    T *ptr;
public:
    MyIterator(T *ptr=nullptr ):ptr(ptr) { }
    T& operator*(){
        return *ptr;
    }
    T* operator->(){
        return ptr;
    }
    T* operator++(T){
        return ptr++;
    }
    template<typename  T1>
    friend bool operator!=(const MyIterator<T1>& mi1, const MyIterator<T1>& mi2 );
};

template<typename  T1>
bool operator!=(const MyIterator<T1>& mi1, const MyIterator<T1>& mi2 ){
    return mi1.ptr != mi2.ptr;
}

class Array{  //容器 Array
    int arr[3];
public:
    Array():arr{1,2,3} { }
    MyIterator<int> begin(){
        return MyIterator<int>(&arr[0] );
    }
    MyIterator<int> end(){
        return MyIterator<int>(&arr[3] );
    }
};

int main()
{
    Array a;
    for( MyIterator<int> it = a.begin(); it!=a.end(); it++)
        cout << *it;
 
    return 0;
}
View Code
#include <iostream>
#include <typeinfo>
#include <string>
#include <algorithm>
using namespace std;

class Array{  //容器 Array
    int arr[3];
public:
    Array():arr{1,2,3} { }
        
    struct MyIterator{ // 迭代器
        int *ptr;
        MyIterator(int *ptr=nullptr ):ptr(ptr) { }
        int& operator*(){
            return *ptr;
        }
        int* operator->(){
            return ptr;
        }
        int* operator++(int){
            return ptr++;
        }
        friend bool operator!=(const MyIterator& mi1, const MyIterator& mi2 ){
            return mi1.ptr != mi2.ptr;
        }
    };

    MyIterator begin(){
        return MyIterator(&arr[0] );
    }
    MyIterator end(){
        return MyIterator(&arr[3] );
    }
};

int main()
{
    Array a;
    for( Array::MyIterator it = a.begin(); it!=a.end(); it++)
        cout << *it;
 
    return 0;
}
View Code
// std::iterator example
#include <iostream>     // std::cout
#include <iterator>     // std::iterator, std::input_iterator_tag

class MyIterator : public std::iterator<std::input_iterator_tag, int>
{
  int* p;
public:
  MyIterator(int* x) :p(x) {}
  MyIterator(const MyIterator& mit) : p(mit.p) {}
  MyIterator& operator++() {++p;return *this;}
  MyIterator operator++(int) {MyIterator tmp(*this); operator++(); return tmp;}
  bool operator==(const MyIterator& rhs) const {return p==rhs.p;}
  bool operator!=(const MyIterator& rhs) const {return p!=rhs.p;}
  int& operator*() {return *p;}
};

int main () {
  int numbers[]={10,20,30,40,50};
  MyIterator from(numbers);
  MyIterator until(numbers+5);
  for (MyIterator it=from; it!=until; it++)
    std::cout << *it << ' ';
  std::cout << '\n';

  return 0;
}
View Code
#include <iostream>
#include <typeinfo>
#include <string>
#include <algorithm>
//using namespace std;

template <class Container>  
auto begin (Container& cont) -> decltype (cont.begin())
{
    return cont.begin(); 
}

class Array{  //容器 Array
    int arr[3];
public:
    Array():arr{1,2,3} { }
        
    struct MyIterator{ // 迭代器
        int *ptr;
        MyIterator(int *ptr=nullptr ):ptr(ptr) { }
        int& operator*(){
            return *ptr;
        }
        int* operator->(){
            return ptr;
        }
        int* operator++(int){
            return ptr++;
        }
        template<typename T>
        friend bool operator!=(const T& mi1, const T& mi2 ){
            return mi1.ptr != mi2.ptr;
        }
    };

    MyIterator begin(){
        return MyIterator(&arr[0] );
    }
    MyIterator end(){
        return MyIterator(&arr[3] );
    }
};

int main()
{
    Array a;
    /* for( Array::MyIterator it = a.begin(); it!=a.end(); it++)
        cout << *it; */
    Array::MyIterator it = begin(a);
    std::cout << *it;
 
    return 0;
}
View Code
#include <iostream>
#include <typeinfo>
#include <string>
#include <algorithm>
//using namespace std;

template <class Container>  
auto begin (Container& cont) -> decltype (cont.begin())
{
    return cont.begin(); 
}

struct node{
    int data;
    node(int i):data(i){ }
    void func(){
        std::cout << "Hello World";
    }
    friend std::ostream& operator<<(std::ostream& o, const node& n){
        o << n.data;
        return o;
    }
};

class Array{  //容器 Array
    node arr[3];
public:
    Array():arr{1,2,3} { }
        
    struct MyIterator{ // 迭代器
        node *ptr;
        MyIterator(node *ptr=nullptr ):ptr(ptr) { }
        node& operator*(){
            return *ptr;
        }
        node* operator->(){
            return ptr;
        }
        node* operator++(int){
            return ptr++;
        }
        template<typename T>
        friend bool operator!=(const T& mi1, const T& mi2 ){
            return mi1.ptr != mi2.ptr;
        }
    };

    MyIterator begin(){
        return MyIterator(&arr[0] );
    }
    MyIterator end(){
        return MyIterator(&arr[3] );
    }
};

int main()
{
    Array a;
    /* for( Array::MyIterator it = a.begin(); it!=a.end(); it++)
        cout << *it; */
    Array::MyIterator it = begin(a);
    
    //解引用操作符和点操作符的表达式的同义词,是箭头操作符
    std::cout <<it->data;    //结点的数据  (*it).data;
    it->func();               //结点的函数  (*it).func();  
 
    return 0;
}
View Code
#include <iostream>
#include <typeinfo>
#include <string>
#include <algorithm>
//using namespace std;

template <class Container>  
auto begin (Container& cont) -> decltype (cont.begin())
{
    return cont.begin(); 
}

struct node{
    int data;
    node(int i):data(i){ }
    void func(){
        std::cout << "Hello World";
    }
    friend std::ostream& operator<<(std::ostream& o, const node& n){
        o << n.data;
        return o;
    }
};

template<typename T>
class Array{  //容器 Array
    T arr[3];
public:
    Array():arr{1,2,3} { }
        
    struct MyIterator{ // 迭代器
        T *ptr;
        MyIterator(T *ptr=nullptr ):ptr(ptr) { }
        T& operator*(){
            return *ptr;
        }
        T* operator->(){
            return ptr;
        }
        T* operator++(int){
            return ptr++;
        }
        template<typename T1>
        friend bool operator!=(const T1& mi1, const T1& mi2 ){
            return mi1.ptr != mi2.ptr;
        }
    };

    MyIterator begin(){
        return MyIterator(&arr[0] );
    }
    MyIterator end(){
        return MyIterator(&arr[3] );
    }
};

int main()
{
    Array<node> a;
    /* for( Array<node>::MyIterator it = a.begin(); it!=a.end(); it++)
        std::cout << *it; */
    Array<node>::MyIterator it = begin(a);
    
    //解引用操作符和点操作符的表达式的同义词,是箭头操作符
    std::cout <<it->data;    //结点的数据  (*it).data;
    it->func();               //结点的函数  (*it).func();  
 
    return 0;
}
View Code

85、成员函数指针,为函数参数

#include <iostream>
using namespace std;

void f(){ //全局函数
    std::cout << "void  f()";
}

class A{
public:
    static void f(){ //局部静态函数
        std::cout << "static void A:: f(),";
    }
    void f1(){  //成员函数
        std::cout << "void f1(),";
    }
    void f2(){  //成员函数
        std::cout << "void f2(),";
    }
};

void func(void (A::*f)( ) ){ //参数:成员函数指针
    //A *p = new A;
    //(p->*f)( );
    A a;
    (a.*f)();
    A::f();
    ::f();
}

int main ()
{
    func(A::f2 );//func(A::f1 );    
    return 0;
}
View Code

86、线程构造函数的参数:成员函数指针,对象的地址,成员函数的参数

#include <thread>
#include <vector>
#include <iostream>
using namespace std;

class A{
public:
    void f1(size_t n){  //成员函数
        std::cout << "void f1(";
        std::cout << n << "),";
    }
    void f2(size_t n){  //成员函数
        std::cout << "void f2(";
        std::cout << n << "),";
    }
};

int main ()
{
    vector<std::thread> tv;
    using Afun = void (A::*)( size_t );
    Afun arr[]{  &A::f1, &A::f2 };    
    
    A a;
    
    for(int i=0; i<2; ++i){
        tv.emplace_back( arr[i],&a  ,i ); //构造线程对象放入tv//线程对象参数:A类成员函数指针,A类的对象地址,A类成员函数的参数
    }
    
    for(auto &t:tv )
        t.join();
    
    return 0;
}
View Code

87、线程构造函数的参数:func函数,func函数的两个参数(其中有一个参数为成员函数指针)

#include <thread>
#include <vector>
#include <iostream>
using namespace std;

class A{
public:
    void f1(size_t n){  //成员函数
        std::cout << "void f1(";
        std::cout << n << "),";
    }
    void f2(size_t n){  //成员函数
        std::cout << "void f2(";
        std::cout << n << "),";
    }
};

void func(void (A::*f)( size_t i) ,size_t n ){ //参数:成员函数指针,size_t
   A a;
   (a.*f)(n ); 
}

int main ()
{
    vector<std::thread> tv;
    using Afun = void (A::*)( size_t );
    Afun arr[]{  &A::f1, &A::f2 };    //成员函数指针
    
    A a;
    
    for(int i=0; i<2; ++i){
        tv.emplace_back( func, arr[i], i );//线程对象构造 //线程构造函数的参数:func函数,func函数的两个参数
    }
    
    for(auto &t:tv )
        t.join();
    
    return 0;
}
View Code

88、可变参数模板与非可变参数模板

#include <iostream>

template<typename T> //非可变参数模板 !!!
std::ostream& print(std::ostream &o, const T &t){    
    return o << t;
}

//非可变参数模板必须声明在作用域中,否则可变参数模板会无限递归
template<typename T, typename... Args> //可变参数模板
std::ostream& print(std::ostream &o, const T &t, const Args &...args){
    o << t << ",";
    return print(o,args...); //!!!
}

int main()
{
    print(std::cout, 1.3, 2, "Hello", 4, 5 );
    
    return 0;
}
View Code

89、boost

#include <functional>
#include <iostream>
#include <utility> 
#include <boost/type_index.hpp>

template<typename Func, typename... Arg>
void test(Func&& f,Arg&&... arg){
    auto bfunc = std::bind(f,std::forward<Arg>(arg)...);
    std::type_id_with_cvr<decltype(bfunc>>().pretty_name();
}

void func(int &a, int & b){
    
}

int main ()
{ 
    int  a=3;
    int b=5;
    test(func, a, b );   
    return 0;
}
View Code

90、头文件(#include <type_traits> )

这个头文件定义了一系列在编译时获取类型信息的类is_same是标识T是否与U相同类型的Trait类