1、C++绘制爱心图像
#include <iostream>
#include <cmath>
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;
}
2、旋转矩阵90°
#include <iostream>
#include <cmath>
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<int>
#include <iostream>
using namespace std;
class P {
public:
P(int, int) {std::cout << "(int, int)" << std::endl;}
P(std::initializer_list<int>) {
std::cout << "(std::initializer_list<int>)" << 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<int>)
(std::initializer_list<int>)
(std::initializer_list<int>)
#include <iostream>
using namespace std;
class P {
public:
P(int, int) {std::cout << "(int, int)" << std::endl;}
// P(std::initializer_list<int>) {
// std::cout << "(std::initializer_list<int>)" << 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 <iostream>
using namespace std;
void print() {}
template<typename T, typename... Type>
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 <iostream>
using namespace std;
template <typename T>
void print(const T& arg) {
std::cout << arg << std::endl;
}
template<typename T, typename... Type>
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 <iostream>
#include <functional>
using namespace std;
std::function<int(int,int)> 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 <iostream>
#include <string>
#include <fstream>
#include <vector>
vector<double> getFileData(char* fileName) {
vector<double> 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++异常体系
异常类定义于许多头文件中,为了能够处理标准库可能抛出的所有异常,必须包含:
#include <exception>
#include <stdexcept>
#include <system_error>
#include <new>
#include <ios>
#include <future>
#include <typeinfo>
9、bind(), async()的使用
#include <iostream>
#include <functional>
#include <memory>
#include <future>
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<C> 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<int, float> IntFloatPair;
IntFloatPair p(42, 3.14);
std::get<0>(p);
std::get<1>(p);
std::tuple_size<IntFloatPair>::value;
std::tuple_element<0, IntFloatPair>::type
10、C++用迭代器删除map元素
int main(int argc, char* argv[]) {
vector<int> 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<int, int> 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 <iostream>
#include <string>
#include <tuple>
using namespace std;
// tuple的输入输出
// helper: print element with index IDX of tuple with MAX elements
template<int IDX, int MAX, typename ...Args>
struct PRINT_TUPLE {
static void print(std::ostream& strm, const std::tuple<Args...>& t) {
strm << std::get<IDX>(t) << (IDX+1 == MAX? "": ",");
PRINT_TUPLE<IDX+1, MAX, Args...>::print(strm, t);
}
};
// partial specialization to end the recursion
template<int MAX, typename... Args>
struct PRINT_TUPLE<MAX, MAX, Args...>{
static void print(std::ostream& strm, const std::tuple<Args...>& t) {}
};
// ou
template <typename... Args>
std::ostream& operator<< (std::ostream& strm, const std::tuple<Args...> &t) {
strm << "[";
PRINT_TUPLE<0, sizeof...(Args), Args...>::print(strm, t);
strm << "]";
}
int main(int argc, char* argv[]) {
std::tuple<int, float, string> t(44, 2.2, "more light");
std::cout << "io: " << t << endl;
return 0;
}
18、智能指针删除器
#include <iostream>
#include <string>
#include <tuple>
#include <memory>
using namespace std;
// 自定义智能指针的删除器
int main(int argc, char* argv[]) {
// 使用lambda函数
std::shared_ptr<int> p(new int[10], [](int* p) {
delete []p;
});
std::shared_ptr<int> p1(new int[10],
std::default_delete<int[]>());
std::unique_ptr<int[]> p2(new int[10]); //ok
std::shared_ptr<int[]> p3(new int[10]); // error
// unique_ptr必须明确第二个模板参数,指出自己的deleter
std::unique_ptr<int, void(*)(int*)> p4(new int[10],
[](int* p) {
delete[] p;
});
return 0;
}
指向某个文件的最后一个引用销毁时,该文件被移除:
#include <iostream>
#include <string>
#include <fstream>
#include <tuple>
#include <memory>
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<std::ofstream> fp(new std::ofstream("tmpfile.txt"), FileDeleter("tmpfile.txt"));
*fp << "ddd";
return 0;
}
使用shared_ptr处理共享内存
linux 共享内存 shm_open ,mmap的正确使用-CSDN博客
#include <iostream>
#include <string>
#include <fstream>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <cerrno>
#include <tuple>
#include <memory>
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<int> 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<int>(static_cast<int*>(mem), SharedMemoryDetacher());
}
int main(int argc, char* argv[]) {
std::shared_ptr<int> smp(getSharedIntMemory(100));
for (int i = 0; i < 100; i++) {
smp.get()[i] = i*42;
}
// deal with shared memory somewhere else
std::cout << "<return>" << std::endl;
std::cin.get();
smp.reset();
return 0;
}
19、weak_ptr的使用
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
//weak_ptr
class Person {
public:
string name;
shared_ptr<Person> mother;
shared_ptr<Person> father;
vector<shared_ptr<Person>> kids;
Person(const string& n, shared_ptr<Person> m = nullptr,
shared_ptr<Person> f = nullptr) :name(n), mother(m), father(f) {}
~Person() {
cout << "delete " << name << endl;
}
};
shared_ptr<Person> initFamily(const string& name) {
shared_ptr<Person> mom(new Person(name + "'s mom"));
shared_ptr<Person> dad(new Person(name + "'s dad"));
shared_ptr<Person> 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<Person> 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;
}
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
//weak_ptr
class Person {
public:
string name;
shared_ptr<Person> mother;
shared_ptr<Person> father;
vector<weak_ptr<Person>> kids; //使用weak_ptr
Person(const string& n, shared_ptr<Person> m = nullptr,
shared_ptr<Person> f = nullptr) :name(n), mother(m), father(f) {}
~Person() {
cout << "delete " << name << endl;
}
};
shared_ptr<Person> initFamily(const string& name) {
shared_ptr<Person> mom(new Person(name + "'s mom"));
shared_ptr<Person> dad(new Person(name + "'s dad"));
shared_ptr<Person> 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<Person> 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
如果不确定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<string> sp(new string("hi"));
weak_ptr<string> wp = sp;
sp.reset();
cout << wp.use_count() << endl; // 0
cout << boolalpha << wp.expired() << endl; // true
shared_ptr<string> p(wp); // bad_weak_ptr
} catch (const std::exception& e) {
cerr << "exception: " << e.what() << endl;
}