C++相关闲碎记录(1)

1、C++绘制爱心图像

#include 
#include 

using namespace std;

int main() {
    // 心形曲线公式 (x^2 + y^2 - a)^3 - x^2*y^3 = 0
    double a = 1;
    double bound = 1.5 * sqrt(a);
    double step = 0.05;
    for (double y = bound; y >= -bound; y -= step) {
        for (double x = -bound; x <=  bound; x += 0.5*step) {
            double result = pow((pow(x,2) + pow(y, 2) - a), 3) - pow(x,2) * pow(y, 3);
            if(result <= 0) {
                cout << "*";
            } else {
                cout << " ";
            }
        }
        cout << "\n";
    }
    return 0;
}

C++相关闲碎记录(1)_第1张图片

2、旋转矩阵90°

#include 
#include 

using namespace std;

int main() {
    // 矩阵旋转
    const int n = 4;
    int image[n][n] = {
        {5, 1, 8, 11},
        {2, 4, 8, 10},
        {13, 3, 6, 7},
        {15, 14, 12, 16}
    };
    // 矩阵转置
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            swap(image[i][j], image[j][i]);
        }
    }
    // 行内翻转
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n/2; j++) {
            swap(image[i][j], image[i][n-j-1]);
        }
    }
    // 输出
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << image[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

3、std::initializer_list

#include 

using namespace std;

class P {
public:
    P(int, int) {std::cout << "(int, int)" << std::endl;}
    P(std::initializer_list) {
        std::cout << "(std::initializer_list)" << std::endl;
    }
};

int main(int argc, char* argv[]) {
    P p1(77, 5);
    P p2{77, 5};
    P r{77, 5, 42};
    P s = {77, 5};
    return 0;
}

输出
(int, int)
(std::initializer_list)
(std::initializer_list)
(std::initializer_list)

#include 

using namespace std;

class P {
public:
    P(int, int) {std::cout << "(int, int)" << std::endl;}
    // P(std::initializer_list) {
    //     std::cout << "(std::initializer_list)" << std::endl;
    // }
};

int main(int argc, char* argv[]) {
    P p1(77, 5);
    P p2{77, 5};
    // P r{77, 5, 42};
    P s = {77, 5};
    return 0;
}
输出:
(int, int)
(int, int)
(int, int)

4、template

#include 

using namespace std;

void print() {}

template
void print(const T& firstArgs, const Type&... args) {
    std::cout << firstArgs << std::endl;
    print(args...);
}

int main(int argc, char* argv[]) {
    print("aaaa", 1, "fefefe", 1.3, 'a');
    return 0;
}

输出:
aaaa
1
fefefe
1.3
a

下面的代码也可以:
#include 

using namespace std;

template 
void print(const T& arg) {
    std::cout << arg << std::endl;
}

template
void print(const T& firstArgs, const Type&... args) {
    std::cout << firstArgs << std::endl;
    print(args...);
}

int main(int argc, char* argv[]) {
    print("aaaa", 1, "fefefe", 1.3, 'a');
    return 0;
}

5、lambda表达式

int main(int argc, char* argv[]) {
    int x = 0, y = 32;
    auto qqq = [x, &y]() {
        std::cout << "x: " << x << std::endl;
        std::cout << "y: " << y << std::endl;
        ++y;
    };
    x = y = 77;  //这一步y会跟新到lambda中y,但是x不会
    qqq();
    qqq();
    std::cout << "final y: " << y << std::endl; 
    return 0;
}
输出:
x: 0
y: 77
x: 0
y: 78
final y: 79
#include 
#include 

using namespace std;

std::function returnLambda() {
    return [](int x, int y) {
        return x*y;
    };
}
int main(int argc, char* argv[]) {
    auto f = returnLambda();
    std::cout << f(6, 7) << std::endl;
    return 0;
}
输出:42

6、算法

You are given numbers, an array of non-negative integers. Your task is to perform the following algorithm on this array:
        step 1. Find the index i of the leftmost non-zero element numbers[i] = x != 0, if there is no         such element, finish the algorithm.
        step 2. Starting at index i and going to eht right, attemp to subtract x from each element.
                if the element is strictly less than x, move on to step 3;
                Otherwise, subtract x from the element and move on to the next element;
                if you reach the end of the array, move on to the step 3;
        step 3. Add x to the final result.
        step 4. Go back to step 1.

import random

def algo(num_list, x):
    if x <= 0:
        return 0
    final_result = 0
    flag_find_leftmost_x = False
    # 记录那些将来会被找到的num_list[i] = x的下标
    record_list = []
    # 向下传递的减法操作的次数
    op_times = 0
    for i, n in enumerate(num_list):
        # 找到leftmost 等于x
        if num_list[i] == x and not flag_find_leftmost_x:
            flag_find_leftmost_x = True
            record_list.append([i, 0])
            op_times = 1
            continue
        # 表示减法在这里传递失败,更新可以向下传递的次数
        if flag_find_leftmost_x and n - op_times * x <= 0:
            op_times = n // x
            # 如果上次记录的x的后面还没有出现一个小于x的,则标记为出现,在这个题里面record_list中的元素的第二个数字并没有实际用到,
            # 但是如果题目稍作更改,则第二维度的数字就可以排上用场了
            if record_list[-1][1] == 0:
                record_list[-1][1] = 1
        # 减完之后还能够等于x,则这个位置就是下一轮能够找到的num_list[i] = x的位置
        elif flag_find_leftmost_x and n - op_times * x == x:
            op_times += 1
            record_list.append([i, 0])
    # 没有找到x,则返回0
    if not flag_find_leftmost_x:
        return final_result
    # print(record_list)
    total_len = len(record_list)
    final_result = total_len * x
    return final_result


# 最原始的方法
def algo_complexity(num_list, x):
    if x <= 0:
        return 0
    total_len = len(num_list)
    i = 0
    final_result = 0
    # print(num_list)
    while i < total_len:
        if num_list[i] == x:
            flag = False
            for j in range(i, total_len):
                if num_list[j] >= x:
                    num_list[j] -= x
                else:
                    final_result += x
                    i = -1
                    flag = True
                    break
            if not flag:
                final_result += x
            # print(num_list)
        i += 1

    return final_result


# num_list = [1, 2, 1, 3, 4, 2, 4, 6]
# num_list = [1, 2, 1, 1, 3, 4, 2, 3, 4, 6]
# num_list = [1, 2, 3, 1, 1, 3, 4, 2, 3, 4, 6]

# num_list = [1, 2, 3, 4, 1, 3, 4, 2, 3, 4, 6]
# num_list = [1, 0, 1, 2, 1, 3, 4, 2, 3, 4, 6]  # 2
# num_list = [1, 0, 1, 0, 1, 3, 4, 2, 3, 4, 6]  # 2 + 2
# num_list = [1, 0, 1, 0, 1, 3, 4, 0, 1, 2, 4]  # 2 + 2 + 2
# num_list = [1, 0, 1, 0, 1, 3, 4, 0, 1, 0, 2]  # 2 + 2 + 2 + 2
# num_list = [1, 0, 1, 0, 1, 3, 4, 0, 1, 0, 0]  # 2 + 2 + 2 + 2 + 2

# print(algo(num_list, 20))
# print(algo_complexity(num_list.copy(), 20))


# 进行10000次测试
for i in range(10000):
    # 随机生成测试列表的长度
    list_len = random.randint(6, 500)
    # 随机生成列表
    num_list = [random.randint(1, 100) for j in range(list_len)]
    x = random.randint(1,100)
    # print("output1: ", algo(num_list, x))
    # print("output2: ", algo_complexity(num_list, x))
    a1 = algo(num_list, x)
    a2 = algo_complexity(num_list.copy(), x)
    if a1 != a2:
        print(a1, ",", a2)
        print(num_list)
        print(x)

print("finished")

7、C++解析CSV文件到vector中

CSV文件格式:a,b,c
#include 
#include 
#include 
#include 

vector getFileData(char* fileName) {
    vector res;
    ifstream is(fileName);
    if (!is) {
        return res;
    }
    string temp;
    const char* split = ",";
    while(getline(is, temp)) {
        char* line = (char*)temp.c_str();
        char* data = strtok(line, split);
        whlie(data!=NULL) {
            res.push_back(atof(data));
            data = strtok(NULL, split);
        }
    }
    is.close();
    return res;
}

8、C++异常体系

C++相关闲碎记录(1)_第2张图片

异常类定义于许多头文件中,为了能够处理标准库可能抛出的所有异常,必须包含:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

9、bind(), async()的使用

#include 
#include 
#include 
#include 
using namespace std;

void func(int x, int y) {
    std::cout << "func" << std::endl;
}

auto l = [](int x, int y) {
    std::cout << "lambda l" << std::endl;
};

class C {
public:
    void operator() (int x, int y) const {
        std::cout << "class C operator" << std::endl;
    }
    void memfunc(int x, int y) const {
        std::cout << "memfunc" << std::endl;
    }
};



int main(int argc, char* argv[]) {
    C c;
    std::shared_ptr sp(new C);

    // bind()
    std::bind(func, 22, 22)();                  // calls func(22, 22)
    std::bind(l, 22, 33)();                     // calls l(22, 33)
    std::bind(C(), 33, 333)();                  // calls C::operator()(33, 333)
    std::bind(&C::memfunc, c, 22, 33)();        // calls c.memfunc(22, 33)
    std::bind(&C::memfunc, sp, 33, 33)();       // calls sp->memfunc(33, 33)

    // async()
    std::async(func, 23, 43);                   // calls func(22, 43)
    std::async(l, 112, 32);                     // calls l(112, 32)
    std::async(c, 23, 32);                      // calls c.operator()(23, 32)
    std::async(&C::memfunc, &c, 23, 23);        // calls c.memfunc(23, 23)
    std::async(&C::memfunc, sp, 23, 23);        // calls sp->memfunc(42, 77)
    return 0;
}

typedef std::pair IntFloatPair;
IntFloatPair p(42, 3.14);
std::get<0>(p);
std::get<1>(p);
std::tuple_size::value;
std::tuple_element<0, IntFloatPair>::type     

10、C++用迭代器删除map元素

int main(int argc, char* argv[]) {
    vector nums{1, 2, 3};
    for (auto it = nums.begin(); it != nums.end(); ) {
        if (*it == 2) {
            it = nums.erase(it);
        } else {
            it++;
        }
    }
    for (int i = 0; i < nums.size(); i++) {
        cout << nums[i] << " ";
    }

    map mp{{1, 2}, {3, 4}, {5, 6}};
    for (auto it = mp.begin(); it != mp.end();) {
        if(it->first == 3) {
            it = mp.erase(it);
        } else {
            it++;
        }
    }
    for (auto it = mp.begin(); it != mp.end(); it++) {
        cout << it->first << " " << it->second << endl;
    }
    return 0;
}

11、map和unordered_map底层实现

unordered_map和map的区别,从算法,底层实现原理区别,效率,桶树等结构等等多个层面解析(c++角度)_unordermap和map性能比较-CSDN博客

12、从非常大的数据里面找出出现次数最多的数

经典面试问题: Top K 之 ---- 海量数据找出现次数最多或,不重复的。 - 指尖下的幽灵 - 博客园 (cnblogs.com)

13、connect函数HOOK

14、unique_ptr如何实现独享

C++ 智能指针unique_ptr原理与自定义实现_unique_ptr move_newchenxf的博客-CSDN博客

15、share_ptr是否线程安全?

c++11总结15——shared_ptr在多线程下的安全性问题_shared_ptr多线程-CSDN博客

所以当我们多个线程访问同一个shared_ptr时,应该要进行加锁操作。 

16、线程有哪些数据是独享的

线程的共享资源与独立资源_线程独有的资源-CSDN博客

17、tuple的输出

#include 
#include 
#include 
using namespace std;

// tuple的输入输出
// helper: print element with index IDX of tuple with MAX elements
template
struct PRINT_TUPLE {
    static void print(std::ostream& strm, const std::tuple& t) {
        strm << std::get(t) << (IDX+1 == MAX? "": ",");
        PRINT_TUPLE::print(strm, t);
    }
};
// partial specialization to end the recursion
template
struct PRINT_TUPLE{
    static void print(std::ostream& strm, const std::tuple& t) {}
};

// ou
template 
std::ostream& operator<< (std::ostream& strm, const std::tuple &t) {
    strm << "[";
    PRINT_TUPLE<0, sizeof...(Args), Args...>::print(strm, t);
    strm << "]";
}

int main(int argc, char* argv[]) {
    std::tuple t(44, 2.2, "more light");
    std::cout << "io: " << t << endl;
    return 0;
}

18、智能指针删除器

#include 
#include 
#include 
#include 
using namespace std;

// 自定义智能指针的删除器

int main(int argc, char* argv[]) {
    // 使用lambda函数
    std::shared_ptr p(new int[10], [](int* p) {
        delete []p;
    });
    
    std::shared_ptr p1(new int[10],
        std::default_delete());
    
    std::unique_ptr p2(new int[10]);  //ok
    std::shared_ptr p3(new int[10]);  // error

    // unique_ptr必须明确第二个模板参数,指出自己的deleter
    std::unique_ptr p4(new int[10], 
        [](int* p) {
            delete[] p;
        });
    
    return 0;
}

指向某个文件的最后一个引用销毁时,该文件被移除:

#include 
#include 
#include 
#include 
#include 
using namespace std;

// 自定义智能指针的删除器

class FileDeleter {
private:
    std::string filename;
public:
    FileDeleter(const std::string& file):filename(file){}
    void operator() (std::ofstream* fp) {
        fp->close();
        std::remove(filename.c_str());
    }
};

int main(int argc, char* argv[]) {
    std::shared_ptr fp(new std::ofstream("tmpfile.txt"), FileDeleter("tmpfile.txt"));
    *fp << "ddd";
    return 0;
}

 使用shared_ptr处理共享内存

linux 共享内存 shm_open ,mmap的正确使用-CSDN博客

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

// 自定义智能指针的删除器
// 使用shared_ptr处理共享内存
class SharedMemoryDetacher {
public:
    void operator()(int* p) {
        std::cout << "unlink /tmp1234" << std::endl;
        if (shm_unlink("/tmp1234") != 0) {
            std::cerr << "OOPS: shm_unlink() failed" << std::endl;
        }
    }
};

std::shared_ptr getSharedIntMemory(int num) {
    void* mem;
    int shmfd = shm_open("/tmp1234", O_CREAT | O_RDWR, S_IRWXU | S_IRWXG);
    if (shmfd < 0) {
        throw std::string(strerror(errno));
    }
    if (ftruncate(shmfd, num*sizeof(int)) == -1) {
        throw std::string(strerror(errno));
    }
    mem = mmap(nullptr, num*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
    if (mem == MAP_FAILED) {
        throw std::string(strerror(errno));
    }
    return std::shared_ptr(static_cast(mem), SharedMemoryDetacher());
}

int main(int argc, char* argv[]) {
    std::shared_ptr smp(getSharedIntMemory(100));
    for (int i = 0; i < 100; i++) {
        smp.get()[i] = i*42;
    }
    // deal with shared memory somewhere else

    std::cout << "" << std::endl;
    std::cin.get();

    smp.reset();
    return 0;
}

19、weak_ptr的使用

#include 
#include 
#include 
#include 

using namespace std;

//weak_ptr
class Person {
public:
    string name;
    shared_ptr mother;
    shared_ptr father;
    vector> kids;

    Person(const string& n, shared_ptr m = nullptr,
           shared_ptr f = nullptr) :name(n), mother(m), father(f) {}
        
    ~Person() {
        cout << "delete " << name << endl;
    }
};

shared_ptr initFamily(const string& name) {
    shared_ptr mom(new Person(name + "'s mom"));
    shared_ptr dad(new Person(name + "'s dad"));
    shared_ptr kid(new Person(name, mom, dad));
    mom->kids.push_back(kid);
    dad->kids.push_back(kid);
    return kid;
}


int main(int argc, char* argv[]) {
    shared_ptr p = initFamily("nico");
    cout << "nico's family exists" << endl;
    cout << "- nico is shared " << p.use_count() << " times" << endl;
    cout << "- name of 1st kid of nico's mom: "
         << p->mother->kids[0]->name << endl;
    
    // 重新修改p的指向,会发现没有delete函数被调用
    p = initFamily("jim");
    cout << "jim's family exists" << endl;
    return 0;
}

C++相关闲碎记录(1)_第3张图片

#include 
#include 
#include 
#include 

using namespace std;

//weak_ptr
class Person {
public:
    string name;
    shared_ptr mother;
    shared_ptr father;
    vector> kids;   //使用weak_ptr

    Person(const string& n, shared_ptr m = nullptr,
           shared_ptr f = nullptr) :name(n), mother(m), father(f) {}
        
    ~Person() {
        cout << "delete " << name << endl;
    }
};

shared_ptr initFamily(const string& name) {
    shared_ptr mom(new Person(name + "'s mom"));
    shared_ptr dad(new Person(name + "'s dad"));
    shared_ptr kid(new Person(name, mom, dad));
    mom->kids.push_back(kid);
    dad->kids.push_back(kid);
    return kid;
}


int main(int argc, char* argv[]) {
    shared_ptr p = initFamily("nico");
    cout << "nico's family exists" << endl;
    cout << "- nico is shared " << p.use_count() << " times" << endl;
    cout << "- name of 1st kid of nico's mom: "
         << p->mother->kids[0].lock()->name << endl;    //使用weak_ptr时,这里需要修改,因为weak_ptr没有* ->操作符
    
    // 重新修改p的指向,会发现没有delete函数被调用
    p = initFamily("jim");
    cout << "jim's family exists" << endl;
    return 0;
}

输出:
nico's family exists
- nico is shared 1 times
- name of 1st kid of nico's mom: nico
delete nico
delete nico's dad
delete nico's mom
jim's family exists
delete jim
delete jim's dad
delete jim's mom

C++相关闲碎记录(1)_第4张图片

 如果不确定weak_ptr背后的对象是否存活,可以使用如下三个方法检查weak_ptr

(1)调用expired(),它会在weak_ptr不再共享对象时,返回true,等同于检查use_count()是否为0.

(2)使用响应的shared_ptr构造函数明确的将weak_ptr转换为一个shared_ptr,如果对象不存在,构造函数会抛出异常bad_weak_ptr异常,其what()会产生bad_weak_ptr。

(3)调用use_count(),询问相应对象拥有者的数量,返回0表示不存在任何有效对象。

try {
    shared_ptr sp(new string("hi"));
    weak_ptr wp = sp;
    sp.reset();
    cout << wp.use_count() << endl;  // 0
    cout << boolalpha << wp.expired() << endl; // true
    shared_ptr p(wp); // bad_weak_ptr

} catch (const std::exception& e) {
    cerr << "exception: " << e.what() << endl;
}

你可能感兴趣的:(c++)