【刷题】C++ 版刷题指南

C++ 刷题指南(自用)

    • 小tips:
      • include
      • struct节点
      • io输入输出练习
      • 其它
      • 输入
      • 迭代器
      • string
      • vector
      • deque(双端队列)
      • 优先队列priority\_queue
        • 优先队列 + tuple
        • 优先队列 + 结构体(自定义排序)
      • map
      • set
      • pair
      • tuple
    • 函数
      • 数学
      • 字符、字符串
      • 对数组操作
    • 数学
      • 最大公约数
    • 语法
      • char[0] 柔性数组
      • 结构体中初始化数组
      • lambda表达式
      • const 和 constexpr

因为以后工作后用Java了,因此慢慢地也开始要用Java刷题了,之前攒的C++刷题用到的库、用法放出来,主要是刷LeetCode时自查、收集的一些用法。


小tips:

include

#include <bits/stdc++.h>    // c++万能库

struct节点

struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};

io输入输出练习

来自牛客网OJ在线编程常见输入输出练习场

数字队列求和:

#include <stdio.h>
int main(){int i,sum=0;while (scanf("%d",&i)!=EOF){sum=sum+i;if (getchar()=='\n'){printf ("%d\n",sum);sum=0;}}return 0;
}
// 或者#include <bits/stdc++.h>
using namespace std;int main(){int sum=0;int n;while(cin>>n){sum+=n;if(cin.get()=='\n'){cout<<sum<<endl;sum=0;}}return 0;
}

cin.get成员读取单个字符,包括任何白色空格字符。参考

字符串队列排序

#include<bits/stdc++.h>
using namespace std;int main(){string temp;while(getline(cin, temp)){stringstream strLineStream(temp);   // 这个必须每个循环建一个vector<string> target;string strtemp;while(getline(strLineStream, strtemp, ',')){target.push_back(strtemp);}sort(target.begin(),target.end());int tag = 0;while(tag < target.size()){if(tag == target.size()-1){cout<<target[tag]<<endl;}else{cout<<target[tag]<<",";}++tag;}}return 0;
}

注意stringstream ss如果想多次复用,下次使用前必须调用ss.clear方法.否则只能每次创建一个新的.

而如果是使用>>从stringstream输出的话似乎需要再使用.str(""),参考《https://blog.csdn.net/jcq521045349/article/details/49888751》

  • 保留小数

参考

#include <iomanip>  //不要忘了头文件//第一种写法
cout<<setiosflags(ios::fixed)<<setprecision(2);//第二种写法
cout.setf(ios::fixed);
cout<<setprecision(2);//第三种写法
cout<<fixed<<setprecision(2);

要保留几位小数setprecision(n)的括号里n就换成几。
前两种写法是一样的,第三种是简化写的。
上面的语句写一次就行了,对之后的数字都有效。

#include  <stdio.h>
int main()
{float PI=3.1415926;float R=5.3;printf("面积 = %.2f\n", PI * R * R); //输出:面积 = 88.25printf("面积 = %f\n", PI * R * R);   //输出:面积 = 88.247337printf("面积 = %.8f\n", PI * R * R); //输出:面积 = 88.24733734return 0;
}

%.2f\n中的“.2”即保留两位小数
//不设定保留几位小数,则默认六位

其它

func
move(将一个左值强制转化为右值引用)在指针类型的标准库对象赋值时避免内存的额外创建 ref
  • 随机数:使用srand((unsigned)time(NULL));每次提供不同的随机种子,否则调用rand()函数每次的输出一样

输入

参考C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法

  • cin >>
    用法1:最基本,也是最常用的用法,输入一个数字:
    用法2:接受一个字符串,遇“空格”、“TAB”、“回车”都结束
#include <iostream>
using namespace std;
main (){char a[20];cin >> a;cout << a << endl;
}
  • cin.get()
    用法1: cin.get(字符变量名)可以用来接收字符
    用法2:cin.get(字符数组名,接收字符数目)用来接收一行字符串,可以接收空格
#include <iostream>
using namespace std;
main (){char a[20];cin.get(a,20);cout << a << endl;
}

用法3:cin.get(无参数)没有参数主要是用于舍弃输入流中的不需要的字符,或者舍弃回车,弥补cin.get(字符数组名,接收字符数目)的不足.

  • cin.getline() // 接受一个字符串,可以接收空格并输出
#include <iostream>
using namespace std;
main ()
{char m[20];cin.getline(m,5);cout<<m<<endl;
}// 输入:jkljkljkl
// 输出:jklj

cin.getline()实际上有三个参数,cin.getline(接受字符串的看哦那间m,接受个数5,结束字符).当第三个参数省略时,系统默认为’\0’

// 当用在多维数组中的时候,也可以用cin.getline(m[i],20)之类的用法:#include<iostream>
#include<string>
using namespace std;main ()
{char m[3][20];for(int i=0;i<3;i++){cout<<"\n请输入第"<<i+1<<"个字符串:"<<endl;cin.getline(m[i],20);}cout<<endl;for(int j=0;j<3;j++)cout<<"输出m["<<j<<"]的值:"<<m[j]<<endl;}
  • getline() // 接受一个字符串,可以接收空格并输出,需包含“#include”
#include<iostream>
#include<string>
using namespace std;
main ()
{string str;getline(cin,str);cout << str << endl;
}

和cin.getline()类似,但是cin.getline()属于istream流,而getline()属于string流,是不一样的两个函数

  • cin.getline()是输入流对象的成员函数
  • getline()是string类的成员函数

C++文档:

  • std::getline (string)
    • Get line from stream into string
    • Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, ‘\n’, for (2)).
    1. istream& getline (istream& is, string& str, char delim);
    2. istream& getline (istream& is, string& str);
  • std::istream::getline
    • Extracts characters from the stream as unformatted input and stores them into s as a c-string, until either the extracted character is the delimiting character, or n characters have been written to s (including the terminating null character).
    • The delimiting character is the newline character (‘\n’) for the first form, and delim for the second: when found in the input sequence, it is extracted from the input sequence, but discarded and not written to s.
    1. istream& getline (char* s, streamsize n );istream& getline (char* s, streamsize n, char delim );
  • std::istream::get
    1. single character (1) int get();istream& get (char& c);
    2. c-string (2) istream& get (char* s, streamsize n);istream& get (char* s, streamsize n, char delim);
    3. stream buffer (3) istream& get (streambuf& sb);istream& get (streambuf& sb, char delim);
  • gets
    • [NOTE: This function is no longer available in C or C++ (as of C11 & C++14)]
    • Reads characters from the standard input (stdin) and stores them as a C string into str until a newline character or the end-of-file is reached.
    1. char * gets ( char * str );

迭代器

《C++ STL prev()和next()函数》

set<int> sset;
set<int>::iterator it = sset.begin();// it 至少为双向迭代器。n 默认为 1
// 当 n 为正数时,其返回的迭代器将位于 it 左侧;反之,当 n 为负数时,其返回的迭代器位于 it 右侧。
it = prev(it, n);
// it 最少为前向迭代器。n 默认为 1
// 当 it 为前向迭代器时,n 只能为正数,该函数最终得到的新迭代器位于 it 右侧;
// 当 it 为双向迭代器或者随机访问迭代器时,若 n 为正数,则得到的新迭代器位于 it 右侧,反之位于 it 左侧。
it = next(it, n);

string

  • reverse
string s;
reverse(s.begin(), s.end());
reverse(s.begin(), s.begin()+s.length());
  • to_string:将数字常量转化为字符串
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
  • 其它:
string s(n, 'c');   // 初始化为连续n个字符串c组成的串
getline(cin, s);    // 从cin中读取一行赋给sif(b.find(a)==string::npos) cout<<"no find"<<endl;  // 在b中查找a,若没找到返回string::npos
// 正向查找在原字符串中第一个与指定字符串(或字符)中的某个字符匹配的字符,返回它的位置。
// 若查找失败,则返回npos。(npos定义为保证大于任何有效下标的值。)
if(b.find_first_of(a)==string::npos) cout<<"no find"<<endl;    
// 逆向查找在原字符串中最后一个与指定字符串(或字符)中的某个字符匹配的字符,返回它的位置。
// 若查找失败,则返回npos。(npos定义为保证大于任何有效下标的值。)
if(b.find_last_of(a)==string::npos) cout<<"no find"<<endl;  stoi(str); // 将str 的内容 解析为一个 特定base的int数值。//  std::string 类本身就提供了类似「入栈」和「出栈」的接口,因此我们直接将需要被返回的字符串作为栈即可
s.empty();
s.back(); s.front();
s.push_back();
s.pop_back();
  • C风格字符串(不建议使用)
    ——《C++ Prime》P109
#include <cstring>char ca1[] = "string example 1";
char ca2[] = "string example 2";    // 以空字符('\0')结束if(ca1 < ca2)   // 未定义:试图比较两个无关地址(使用数组时其实使用的是指向首元素的指针)strlen(p);      // 返回p的长度
strcmp(p1, p2); // 比较:p1 == p2 返回0;p1 > p2 返回正值;否则返回一个负值
strcat(p1, p2); // 将p2附加到p1后,返回p1(注意p1的容量)
strcpy(p1, p2); // 将p2拷贝给p1,返回p1

可以用字符数组初始化string,不能反过来(反过来要用c_str()

string s("Hello");
const char *str = s.c_str();

vector

  • 初始化:
vector<T> v1;
vector<T> v2(v1);
vector<T> v3{a, b, c};
vector<T> v3 = {a, b, c};// 使用数组初始化vector——《C++ Prime》P112
int int_arr[] = {0, 1, 2, 3};
vector<int> ivec(begin(int_arr), end(int_arr));     // begin和end函数返回数组的首指针和尾后指针
vector<int> subVec(int_arr + 1, int_arr + 4);   // [1, 2, 3]
  • 插入:
test.insert(test.begin(), 1)
vec.insert(vec.end(),3,100);//Inserting 100, 3 times to the vector
  • 合并:
vector<int> vec1 = {...};
vector<int> vec2 = {...};// vec1和vec2都存有内容vector<int> vec3;//vec3是空的
vec3.insert(vec3.end(), vec1.begin(), vec1.end())//将vec1压入
vec3.insert(vec3.end(), vec2.begin(), vec2.end())//继续将vec2压入
  • 获取值:
    可以通过使用 * vector.begin()*( vector.end() - 1) 来获得 vector 中第一个或最后一个的值;
    也可以直接使用 vector.front()vector.back() 来得到 vector 首尾的值。
vec.front();    // 返回的是第一个元素的引用。
vec.back();     // 返回的的是最后一个元素的引用。
  • 添加值
vec.push_back()     // 将一个新的元素加到vector的最后面
vec.pop_back()      // 删除Vector容器中的最后一个元素
  • resize 和 reverse
// https://blog.csdn.net/yiyeshuanglinzui/article/details/126060891
vec.capacity();
vec.resize(count)
vec.reserve(count)

vec.capacity();表示的容器内可以容纳多少个对象,表示的是能力,是可以,不代表容器内就有这么多个对象。

resize 会调用构造函数,而 reserve 仅仅是开辟内存空间。直观的表现就是 resize 会改变 vector size 的值(此时 capacity 也可能会改变),而 reserve 改变的是 capacity。

  • resize()-实实在在的默认构造

    • count小于当前实际的size,则会析构掉多余的对象
    • count大于当前实际的size,小于等于capacity,则会调用默认构造。
    • count大于capacity,则会调用默认构造和复制构造(构造之前就存在的对象)。
  • reserve()-只分配足够的内存,不构造

    • count大于当前的capacity,则会调用复制构造,构造之前就存在的对象。
    • count小于capacity,则不会有任何影响。
  • 其它

vec.resize(int n, element)   // 表示调整容器vec的大小为n,扩容后的每个元素的值为element,默认为0// 删除指定位置position的元素,并返回删除元素的下一个元素的迭代器
iterator erase (iterator position);  
// 删除从first到last(不包过last)之间的元素 [first,last),并返回last位置迭代器
iterator erase (iterator first, iterator last); vec.front();    // 返回的是第一个元素的引用。
vec.back();     // 返回的的是最后一个元素的引用。// std::vector::data() 是 C++ 中的 STL,它返回一个指向内存数组的直接指针,该内存数组由向量内部用于存储其拥有的元素。
vector<int> vec = { 10, 20, 30, 40, 50 };
int* pos = vec.data();      // 该函数不接受任何参数
for (int i = 0; i < vec.size(); ++i) cout << *pos++ << " ";

deque(双端队列)

容器 deque (发音为“deck”)和 vector 非常相似。它也采用dynamic array来管理元素,提供随机访问,并有着和 vector 几乎一模一样的接口。不同的是 deque 的 dynamic array 头尾都开放,因此能在头尾两端进行快速安插和删除

  • deque 与 vector 的用法基本一致,除了以下几处不同:
    • deque 没有 reserve 和 capacity,而 vector 有;
    • deque 有 push_front() 和 pop_front() 函数,而 vector 没有;
    • deque 没有 data() 函数,而 vector 有。
// https://blog.csdn.net/qq_43448856/article/details/123009040
c.push_back(elem);	    // 附加一个 elem 的拷贝于末尾
c.pop_back();	    // 移除最后一个元素,但是不返回它
c.push_front(elem);	    // 在头部插入 elem 的一个拷贝
c.pop_front();	    // 移除第一元素(但不返回)

优先队列priority_queue

堆实现的优先队列的时间复杂度为$O(log_n)$

《priority_queue优先队列的使用方法》值得一提的是priority_queue与pair结合:

// 原文链接:https://blog.csdn.net/qq_40946453/article/details/112169855
// 小顶堆 .top 输出是从小到大
priority_queue <pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>> > q;
priority_queue <pair<int,int>,vector<pair<int,int>>,greater< > > q;
priority_queue <tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> pq;// 默认大顶堆 .top 输出是从大到小
priority_queue <pair<int,int>,vector<pair<int,int>>,less<pair<int,int>> > q;
priority_queue <pair<int,int>,vector<pair<int,int>>,less< > > q;
priority_queue <pair<int,int>,vector<pair<int,int>> > q;
priority_queue <pair<int,int>> q;
优先队列 + tuple

Dijkstra(节点用两个数据标记)的部分代码

    // 保存的线: 当前节点dis,当前节点(本例为二维节点)priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> pq;// pq.push({0, 0, 0});  // 这个不对// pq.push(tuple<int, int, int>{0, 0, 0});// pq.push(tuple<int, int, int>(0, 0, 0));pq.emplace(0, 0, 0);dis[0][0] = 0;while(!pq.empty()){// auto &[t, x, y] = pq.top();  // 不对// 这个地方不能加引号auto [t, x, y] = pq.top();pq.pop();// 注意这里done标记的位置done[x][y] = true;...}

其中emplace这样接受新对象的时候,自己会调用其构造函数生成对象然后放在容器内。而push,只能让其构造函数构造好了对象之后,再使用复制构造函数!相当于emplace直接把原料拿进家,造了一个。而push是造好了之后,再复制到自己家里,多了复制这一步。

所以emplace相对于push,使用第三种方法会更节省内存。

优先队列 + 结构体(自定义排序)
struct Node{int cnt, pos, val;Node(int cnt, int pos, int val) : cnt(cnt), pos(pos), val(val){};
};
struct cmp{bool operator()(Node &a,Node &b){return a.cnt == b.cnt ? a.pos < b.pos : a.cnt < b.cnt;};
};
priority_queue<Node, vector<Node>, cmp> pq;
// https://en.cppreference.com/w/cpp/container/priority_queueconst auto data = {1,8,5,6,3,4,0,9,7,2};
// Using a custom function object to compare elements.
struct {bool operator() (const int l, const int r) const { return l > r; }
} customLess;
std::priority_queue minq3(data.begin(), data.end(), customLess);// Using lambda to compare elements.
auto cmp = [](int left, int right) { return (left ^ 1) < (right ^ 1); };
std::priority_queue<int, std::vector<int>, decltype(cmp)> q5(cmp);

其它高级用法参考《题目求助|C++11关键字decltype用法》

map

map中的元素进行了排序,而unordered_map并未进行排序。

  • 初始化:map是键-值对的组合,有以下的一些定义的方法:
map<k, v> m;
map<k, v> m(m2);
map<k, v> m(b, e);
  • 插入
    insert函数的插入方法主要有如下:
m.insert(e)
m.insert(beg, end)
m.insert(iter, e)
  • 插入:
    上述的e一个value_type类型的值。beg和end标记的是迭代器的开始和结束。更详细的说明:
unordered_map<int, string> m;m[1] = "zhangsan";  // 如果已经存在键值 1,则会作赋值修改操作,如果没有则插入
// 插入单个键值对,并返回插入位置和成功标志,插入位置已经存在值时,插入失败
pair<iterator,bool> insert (const value_type& val);
// eg.
map<int, string> mapStudent;
mapStudent.insert(map<int, string>::value_type (1, "student_one"));//在指定位置插入,在不同位置插入效率是不一样的,因为涉及到重排
iterator insert (const_iterator position, const value_type& val);void insert (InputIterator first, InputIterator last);  // 插入多个
void insert (initializer_list<value_type> il);  //c++11开始支持,使用列表插入多个   
  • 查找
    若只是查找该元素是否存在,可以使用函数m.count(k),该函数返回的是k出现的次数;若是想取得key对应的值,可以使用函数m.find(k),该函数返回的是指向该元素的迭代器,若失败返回的是m.end()
auto it = m.find(e);
if(it != m.end()){cout << it->first << " " << it->second << endl;
}
  • 遍历
map<int, int> mp;
for (auto p : mp) cout << p.first << ' ' <<   p.second << endl;
// 或
map<int, int> mp;
map<int, int>::iterator iter;
for(iter = mp.begin();iter != mp.end();iter ++)cout << iter->first << ' ' << iter->second << endl;

set

参考《c++ unordered_set详细操作》

对于另一种 unordered_set 容器,可直译为“无序 set 容器”。即 unordered_set 容器和 set 容器很像,唯一的区别就在于 set 容器会自行对存储的数据进行排序,而 unordered_set 容器不会。

unordered_set<int> set1;        // 创建空的set
unordered_set<int> set2(set1);  // 拷贝构造
unordered_set<int> set3(set1.begin(), set1.end());  // 使用迭代器构造
unordered_set<int> set4(arr,arr+5);     // 使用数组作为其初值进行构造
unordered_set<int> set5(move(set2));    // 移动构造
unordered_set<int> set6 {1,2,10,10};    // 使用处置列表进行构造set1.rbegin();set1.rend();  // 指向起始和末尾的逆向迭代器

常用内置函数:

set1.empty();   // 若容器为空,则返回 true;否则 false
set1.find(2);   // 查找2,找到返回迭代器,失败返回end()
set1.count(2);  // 返回指2出现的次数,0或1
set1.emplace(3);    // 使用转移构造函数添加新元素3,比insert效率高
set1.clear();   // 清空

insert插入元素:

set1.insert(3);     //插入元素,返回pair<unordered_set<int>::iterator, bool>
set1.insert({1,2,3});   //使用initializer_list插入元素
set1.insert(set1.end(), 4); //指定插入位置,如果位置正确会减少插入时间,返回指向插入元素的迭代器
set1.insert(set2.begin(), set2.end());  //使用范围迭代器插入

关于insert函数的返回值:
insert()只传入单个参数(待插入元素):

  1. 会返回一个 pair 对象
  2. 这个 pair 对象包含一个迭代器,以及一个附加的布尔值用来说明插入是否成功
  3. 如果元素被插入,返回的迭代器会指向新元素
  4. 如果没有被插入,迭代器指向阻止插入的元素
auto pr = words.insert("ninety"); // Returns a pair - an iterator & a bool value

insert()传入两个参数(迭代器+待插入元素):

  1. 可以用一个迭代器作为insert()的第一个参数,它指定了元素被插入的位置
  2. 在这种情况下,只会返回一个迭代器
auto iter = words.insert (pr.first, "nine"); // 1st arg is a hint. Returns an iterator

insert()传入初始化列表:

  1. 插入初始化表中的元素
  2. 在这种情况下,什么都没有返回
words.insert({"ten", "seven", "six"});  // Inserting an initializer list

erase()函数——删除元素

int flag = set1.erase(1);  //删除操作,成功返回1,失败返回0// 删除操作,成功返回下一个pair的迭代器
// 可使用该方法进行循环删除
set<int>::iterator it = set1.erase(set1.find(1));   // 删除set1的所有元素,返回指向end的迭代器
set<int>::iterator it = set1.erase(set1.begin(), set1.end());   

XXX注意,删除最后一个元素的迭代器,会返回指向新的最后一个元素的迭代器,参考

TODO:输出end()的迭代器能够输出最后一个值

#include <iostream>
#include <bits/stdc++.h>
using namespace std;int main()
{// cout << "Hello World";set<int> sset = {1,2,3,4,5};auto it = sset.begin();for(auto i=it;i!=sset.end();i++) cout << *i << " ";cout << endl;int cnt = 7;auto t = it;for(;t!=sset.end() && cnt > 0;t++,cnt--) cout << *t << " ";cout << ": " << bool(t == sset.end()) << endl;cnt = 5;t = it;t++;for(;t!=sset.end() && cnt > 0;++t,++t,cnt--) cout << *t << " ";cout << ": " << bool(t == sset.end()) << endl;cout << ": " << *t << endl;t++;cout << ": " << *t << endl;cnt = 5;t = it;for(;t!=sset.end() && cnt > 0;++t,++t,cnt--) cout << *t << " ";cout << ": " << bool(t == sset.end()) << endl;t = sset.erase(t);cout << ": " << bool(t == sset.end()) << endl;cout << *t << endl;cout << endl;return 0;
}

pair

//原文链接:https://blog.csdn.net/sevenjoin/article/details/81937695// 创建一个空的pair对象(使用默认构造),它的两个元素分别是T1和T2类型,采用值初始化。
pair<T1, T2> p1;            
// 创建一个pair对象,它的两个元素分别是T1和T2类型,其中first成员初始化为v1,second成员初始化为v2。
pair<T1, T2> p1(v1, v2);    
// 以v1和v2的值创建一个新的pair对象,其元素类型分别是v1和v2的类型。
make_pair(v1, v2);          
// 两个pair对象间的小于运算,其定义遵循字典次序:如 p1.first < p2.first 或者 !(p2.first < p1.first) && (p1.second < p2.second) 则返回true。
p1 < p2;                    
// 如果两个对象的first和second依次相等,则这两个对象相等;该运算使用元素的==操作符。
p1 == p2;                  
p1.first;                   // 返回对象p1中名为first的公有数据成员
p1.second;                 // 返回对象p1中名为second的公有数据成员

vector后入pair(eg. {a, b})的四种写法:

  • emplace(a, b)
  • emplace(make_pair(a, b))
  • push_back({a, b})
  • push_back(make_pair(a, b))

tuple

参考
元组tuple是C++的一个模板,不同tuple类型的成员类型也不相同,但是一个tuple可以有任意数量的成员。
每个tuple类型的成员个数是一定的,但是不同的tuple成员个数可以不同。

// 初始化
tuple<int, string, vector<int>> test{1, "hello,world", {4, 5, 6}};
auto test2 = make_tuple(3.14, "wasd");// 在C++标准库里,有一个名为get的函数模板。为了使用get,
// 我们必须指定一个显式模板实参来指示访问的第几个成员,并在函数参数中给予它一个tuple对象。
tuple<int, string, vector<int>> test{ 1,"hello,world",{4,5,6} };
cout << get<0>(test) << endl;		//打印test第一个成员,其类型为int
cout << get<1>(test) << endl;		//打印test第二个成员,其类型为string
cout << get<2>(test)[0] << endl;	//打印test第三个成员vector<int>的第一个元素

函数

数学

  • 统计数字在二进制下“1”的个数——__builtin_popcount()
    该函数是C++自带的库函数,内部实现是用查表实现的。
    作用:统计数字在二进制下“1”的个数。

字符、字符串

isalpha()   // 用来判断一个字符是否为字母
isalnum()   // 用来判断一个字符是否为数字或者字母,也就是说判断一个字符是否属于a~ z||A~ Z||0~9。
isdigit()   // 用来检测一个字符是否是十进制数字0-9
islower()   // 用来判断一个字符是否为小写字母,也就是是否属于a~z。
isupper()   // 和islower相反,用来判断一个字符是否为大写字母。// 以上部分为宏定义,并非真正函数。toupper()   // 将小写字母转换为大写字母
tolower()   // 将大写字母转换为小写字母
// 或
char c = 'a'; c ^= 32;
// 由于每个字符的大小写形式刚好差了 32,因此在大小写装换时可以用 c⊕32 来进行转换和恢复。

对数组操作

  • 二分查找:

lower_bound() 函数用于在指定区域内查找不小于目标值的第一个元素。

int right = lower_bound(arr.begin(), arr.end(), x) - arr.begin();

相对应的upper_bound 用于在指定范围内查找大于目标值的第一个元素。

//查找[first, last)区域中第一个大于 val 的元素。
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val);
//查找[first, last)区域中第一个不符合 comp 规则的元素
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);

lower_bound重写排序方法lambda函数,实际上第一个参数是数组的个体,第二个参数是lower_bound的第三个参数即查询值即可。

int cp = lower_bound(col[j].begin(), col[j].end(), down, [&](auto &a, auto &b){return a.first > b;
}) - col[j].begin();

还有equal_range该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的值为 val 的元素(但特殊的,对于set 容器自实现的equal_range方法,由于set中各个元素是唯一的,因此该范围最多包含一个元素)。

XXX注意:对于部分STL容器来说使用其自带的lower_bound等方法更快(eg. set是红黑树)。参考

  • 快速获取最大最小元素
/*
param begin : 序列起始地址(迭代器)
param end  : 序列结束地址(迭代器)
return   : 序列中最小元素地址(迭代器)
*/
min_element(nums.begin(), nums.end());/*
param begin : 序列起始地址(迭代器)
param end  : 序列结束地址(迭代器)
return   : 序列中最大元素地址(迭代器)
*/
max_element(nums.begin(), nums.end());// 前面加*直接取值
vector<int> nums = {1, 2, 3};
int maxv = *max_element(nums.begin(), nums.end());
  • 快读获取第n个元素
// 从某个序列中找到第 n 小的元素 K,并将 K 移动到序列中第 n 的位置处。
// 无返回值
nth_element(nums.begin(), nums.begin() + nums.size() / 2, nums.end());
auto nth_v = nums[nums.size() / 2];
  • 用递增序列对数组初始化——iota(希腊字母表的第9个字母,艾欧塔) 文档:用一个从value递增的数列给[first, last)的容器赋值
#include <numeric>int numbers[10];
std::iota (numbers,numbers+10,100);     // fill with 100 101 102 103 104 105 106 107 108 109
  • 数组去重——unique
    unique函数可以删除有序数组中的重复元素:
    • 这里的删除不是真的delete,而是将重复的元素放到容器末尾
    • unique函数的返回值是去重之后的尾地址
    • 一定要先对数组进行排序才可以使用unique函数
#include <algorithm>int arr[10]={5,8,4,12,6,8,9,5,10,3};
sort(arr, arr + 10);       //记得先排序
int len;            //用一个len来记录无重复元素的数组的长度 
len = unique(arr, arr + 10) - arr;
  • 求和
    参考《C++ accumulate函数用法详解》:
    前两个参数是定义序列的输入迭代器,第三个参数是和的初值;第三个参数的类型决定了返回值的类型。第二个版本的第 4 个参数是定义应用到总数和元素之间的二元函数对象。这时,我们在必要时可以定义自己的加法运算。例如:
std::vector<int> values {2, 0, 12, 3, 5, 0, 2, 7, 0, 8};
int min {3};
auto sum = std::accumulate(std::begin(values), std::end(values), 0, [min] (int sum, int v)
{if(v < min)return sum;return sum + v;
})

数学

最大公约数

#include <algorithm>
inline int gcd(int a,int b) {    return __gcd(a,b);
}

其它自实现最大公约数可参考:《【C++】gcd函数的写法》

语法

char[0] 柔性数组

本来是为了探究cv::Mat初始化的一种参数data的类型为什么可以是uchar*,(并且mmdeploy也是这么用的),但是还是不太懂,先记一下。

《char a[0] 柔性数组》
《[C/C++] char data[0](柔性数组)》

结构体中初始化数组

以字典序模板为例

struct Node{// vector<Node*> chld(26);  // 编译器可能无法区分这是一个成员函数声明还是一个成员变量声明// Node *chld[26]{};     // 应采用这种// https://blog.csdn.net/qq_32523711/article/details/107798999vector<Node*> chld = vector<Node*>(26);     // 明确这是一个成员变量声明int score = 0;int cnt = 0;friend bool operator < (Node &a, Node &b) {return a.score < b.score;}Node(int score) : score(score), cnt(cnt) {};
};

lambda表达式

《C++ Lambda表达式的基本使用》

const 和 constexpr

C++ const 和 constexpr 的区别? - 知乎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/2997.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件摆渡:安全、高效的摆渡系统助力提升效率

很多组织和企业都会通过网络隔离的方式来保护内部的数据&#xff0c;网络隔离可以是物理隔离&#xff0c;也可以是逻辑隔离&#xff0c;如使用防火墙、VPN、DMZ等技术手段来实现&#xff0c;隔离之后还会去寻找文件摆渡方式&#xff0c;来保障日常的业务和经营需求。 进行网络隔…

Python的一些高级用法

Python的高级用法涵盖了更深入的编程技巧、设计模式、并发编程、性能优化等方面。以下是Python的一些高级用法&#xff1a; 1.装饰器 用于修改函数或类的行为的函数&#xff0c;常用于日志记录、性能分析等。 def my_decorator(func):def wrapper():print("Something i…

数据库变更时,OceanBase如何自动生成回滚 SQL

背景 在开发中&#xff0c;数据的变更与维护工作一般较频繁。当我们执行数据库的DML操作时&#xff0c;必须谨慎考虑变更对数据可能产生的后果&#xff0c;以及变更是否能够顺利执行。若出现意外数据丢失、操作失误或语法错误等情况&#xff0c;我们必须迅速将数据库恢复到变更…

jsp+springboot+java二手车交易管理系统258u6

设计而成的系统要有以下目标&#xff1a;管理员和用户能够跳转到不同的页面当中。因此要把系统的目标设置为如下几项&#xff1a; (1) 系统在操作上不能过于复杂。 (2) 用户对应着不同的角色 (3) 设计完成的数据库要有能够处理并发和安全的作用 (4) 设计完成的管理…

Python——目标检测标签中的英文名转化为对应的类别编号

Yolov5进行目标检测流程在下文中已做说明&#xff1a; Python——一文详解使用yolov5进行目标检测全流程&#xff08;无需gpu&#xff09;_yolo不用gpu-CSDN博客 在Yolov5使用中中&#xff0c;标签数据里类别的中文名&#xff0c;需要转换成类别编号。相关代码如下&#x…

亚马逊云科技提高企业生产力神器Amazon Q评测分析

一年一度的全球云计算春晚&#xff0c;亚马逊云科技Re:invent在2023年11月27于Vegas震撼来袭&#xff0c;其中最令人关注的就是CEO Adam在Keynote中分享的内容。其中一个新内容就是提升生产力神器: Amazon Q&#xff0c;可以说它重新定义了企业的工作模式。那具体它神在哪里呢&…

设计模式- 代理模式(Proxy Pattern)结构|原理|优缺点|场景|示例

设计模式&#xff08;分类&#xff09; 设计模式&#xff08;六大原则&#xff09; 创建型&#xff08;5种&#xff09; 工厂方法 抽象工厂模式 单例模式 建造者模式 原型模式 结构型&#xff08;7种&#xff09; 适配器…

Python构建学生信息管理系统:网站路由补充和首次运行

在之前的内容中&#xff0c;我们已经完成了学生信息管理系统&#xff08;Student Information Management System, SIMS&#xff09;的需求分析、环境搭建、数据库创建、项目结构的初始化&#xff0c;以及运行。正常做下来的朋友&#xff0c;会发现项目运行后输入http://127.0.…

vulfocus靶场thinkphp命令执行cve-2018-1002015

thinkPHP 5.0.x版本和5.1.x版本中存在远程代码执行漏洞&#xff0c;该漏洞源于ThinkPHP在获取控制器名时未对用户提交的参数进行严格的过滤。远程攻击者可通过输入‘&#xff3c;’字符的方式调用任意方法利用该漏洞执行代码 开启靶场&#xff1a; 使用工具&#xff1a; think…

使用微软Phi-3-mini模型快速创建生成式AI应用

微软Phi-3大语言模型是微软研究院推出的新一代系列先进的小语言模型。Phi-3系列包括phi-3-mini、phi-3-small和phi-3-medium三个不同规模的版本。这些模型在保持较小的参数规模的同时&#xff0c;通过精心设计的训练数据集和优化的算法&#xff0c;实现了与大型模型相媲美的语言…

VaR(Value at Risk)模型代码

Value at Risk&#xff08;VaR&#xff09;是一种用于衡量投资组合可能损失的风险的模型。它可以帮助投资者评估他们面临的潜在风险&#xff0c;并做出相应的风险管理决策。以下是一个简单的VaR模型案例。 假设一个投资组合由两个资产组成&#xff1a;股票A和股票B。股票A的市…

Edge下载文件提示无法安全下载的解决方法

问题描述&#xff1a;最近Edge在下载文件时总是提示&#xff1a;无法安全下载&#xff0c;本文记录一下解决方法。 提示截图&#xff1a; 解决方式一&#xff1a; 1. 点击下图红框的三个点&#xff0c;选择保留 2. 选择仍然保留 解决方式二&#xff1a; 第一种方式每下载一次…

JavaScript、Java、C#标记过时方法

JavaScript、Java、C#标记过时方法 在JavaScript、Java和C#中&#xff0c;可以使用特定的注解或标记来表示一个方法是不推荐的&#xff0c;以便在使用该方法时发出警告或提示。虽然没有专门用于标记不推荐方法的内置标记&#xff0c;但是可以结合使用deprecated、[Obsolete]等…

✅为什么MySQL默认使用RR隔离级别?

对于数据库的默认隔离级别&#xff0c;Oracle默认的隔离级别是 RC&#xff0c;而MySQL默认的隔离级别是 RR。 那么&#xff0c;你知道为什么Oracle选择RC作为默认级别&#xff0c;而MySQL要选择RR作为默认的隔离级别吗&#xff1f; Oracle的隔离级别 Oracle支持ANSI/ISO SQL…

逝去的韶光

韶光易逝&#xff0c;岁月难留。春夏之交&#xff0c;正是时光交替的节点&#xff0c;仿佛一切都在默默地诉说着曾经的往事。我站在这个特殊的时刻&#xff0c;不禁想起那些已经远去的日子。 阳光穿过树梢&#xff0c;斑驳地洒在小径上。微风拂过&#xff0c;树叶轻轻摇曳&…

【OpcUA开发笔记 3】Open62541证书登录方式

前言: OpcUA的登录方式有3种,分别是匿名,用户名+密码,证书。其中前两个比较简单,我们就从最复杂的说起,前两个顺带说下也就会了,属于抛砖引玉讲述解决思路,非保姆式教程。 材料:open62541-1.4.0,cmake 3.29.2,openssl 3.3.0.9,visual studio2022,python3.8.6 一、…

HTB靶场 Perfection

端口 打开了ssh和http服务 访问 Perfection靶机的网站 是一个根据权重计算总成绩的网站 Wappalyzer查看网页用的什么编写搭建的 抓包看一下是怎么工作的 发送,&#xff0c;返回的结果 如果我在 类别 后面多加一句命令 就会出现提示 恶意输入阻止 大概率有命令注入 通过插件…

【第34天】SQL进阶-SQL高级技巧-Window Funtion(SQL 小虚竹)

回城传送–》《100天精通MYSQL从入门到就业》 文章目录 零、前言一、练习题目二、SQL思路初始化数据什么是Window Funtion窗口函数的分类语法结构第一种写法:第二种写法:实战体验序号函数:row_number()序号函数:rank()序号函数:dense_rank()

动手学深度学习——pandas

1. 简介 作用&#xff1a;对数据进行预处理&#xff0c;是数据科学常使用的库。 支持多种数据格式读取&#xff1a; CSV/Excel/SQL/JSON/HTML数据清洗&#xff1a;处理缺失值、重复值、异常值、数据转换合并数据过滤&#xff1a;灵活的索引、切片、筛选功能&#xff0c;方便选…

2024最新版JavaScript逆向爬虫教程-------基础篇之JavaScript密码学以及CryptoJS各种常用算法的实现

目录 一、密码学介绍1.1 为什么要学密码学?1.2 密码学里面学哪一些 二、字符编码三、位运算四、Hex 编码与 Base64 编码4.1 Hex 编码4.2 Base64 编码 五、消息摘要算法5.1 简介5.2 JS中的MD5、SHA、HMAC、SM3 六、对称加密算法6.1 介绍6.2 加密模式和填充方式6.3 CryptoJS 中D…