对c++常用的解题方法进行记录,主要是STL。
变量名
ans
cnt
sum
num
输入输出
取消cin与stdin的同步
ios::sync_with_stdio(false);
这样做了之后要注意不要同时混用cout和printf。
std::cin.tie(0);
解除cin与cout的绑定,进一步加快执行效率。
大量的数据读写可能会造成运行超时,所以,使用cin
读数据,使用printf
输出数据。原因:即使取消同步,cout
和printf
速度还是有较大差距。
freopen
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
fclose(stdin);
fclose(stdout);
fopen
FILE *fin, *fout;
fin = fopen("in.txt", "rb");
fout = fopen("out.txt", "wb");
fscanf(fin, "%d", &x);
fprintf(fout, "%d", x);
fclose(fin);
fclose(fout);
for
range-based-for
vector<int> vec {1,2,3,4,5,6,7,8,9,10};
for (auto n : vec)
cout << n;
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//输出数组的全部空间
for (auto n : arr)
cout << n;
vector<int> vec {1,2,3,4,5,6,7,8,9,10};
for (auto& n : vec)
n++;
char
isalpha、isdigit、islower、isupper
isalpha()//字母
isdigit()//数字
islower()//小写字母
isupper()//大写字母
double
sqrt
double sqrt(double x);//平方根
fix、floor、ceil和round
double fix(double x);//朝零方向取整
double round(double x);//四舍五入到最近的整数
double floor(double x);//朝负无穷方向取整
double ceil(double x);//朝正无穷方向取整
数组
memcpy
#include <cstring>
memcpy(b, a, sizeof(a));
memcpy(b, a, sizeof(int) * k);//数组a复制k个元素到数组b
memset
#include <cstring>
memset(a, 0, sizeof(a));
字符串
读取
c
char c = getchar();
gets(str);
c++
cin.get(str).get();//不忽略回车
cin.getline(str);//忽略回车
getline(cin, str);//忽略回车
sscanf
从字符串中读进与指定格式相符的数据。
%[a-z] 匹配a到z中任意字符或字符串
%[ab] 匹配a和b中的一员
%[^a] 取到指定字符集为止的字符串
sscanf("1995:11:18", "%d:%d:%d", &a, &b, &c);
int ret;
char *string;
int digit;
char buf1[255];
char buf2[255];
char buf3[255];
char buf4[255];
/*1.最简单的用法*/
string = "china beijing 123";
ret = sscanf(string, "%s %s %d", buf1, buf2, &digit);
printf("1.string=%s\n", string);
printf("1.ret=%d, buf1=%s, buf2=%s, digit=%d\n\n", ret, buf1, buf2, digit);
/*
**执行结果:
**1.ret=3, buf1=china, buf2=beijing, digit=123
**可以看出,sscanf的返回值是读取的参数个数
*/
/*2.取指定长度的字符串*/
string = "123456789";
sscanf(string, "%5s", buf1);
printf("2.string=%s\n", string);
printf("2.buf1=%s\n\n", buf1);
/*
**执行结果:
**2.buf1=12345
*/
/*3.取到指定字符为止的字符串*/
string = "123/456";
sscanf(string, "%[^/]", buf1);
printf("3.string=%s\n", string);
printf("3.buf1=%s\n\n", buf1);
/*
**执行结果:
**3.buf1=123
*/
/*4.取到指定字符集为止的字符串*/
string = "123abcABC";
sscanf(string, "%[^A-Z]", buf1);
printf("4.string=%s\n", string);
printf("4.buf1=%s\n\n", buf1);
/*
**执行结果:
**4.buf1=123abc
*/
/*5.取仅包含指定字符集的字符串*/
string = "0123abcABC";
sscanf(string, "%[0-9]%[a-z]%[A-Z]", buf1, buf2, buf3);
printf("5.string=%s\n", string);
printf("5.buf1=%s, buf2=%s, buf3=%s\n\n", buf1, buf2, buf3);
/*
**执行结果:
**5.buf1=123, buf2=abc, buf3=ABC
*/
/*6.获取指定字符中间的字符串*/
string = "ios<android>wp7";
sscanf(string, "%*[^<]<%[^>]", buf1);
printf("6.string=%s\n", string);
printf("6.buf1=%s\n\n", buf1);
/*
**执行结果:
**6.buf1=android
*/
/*7.指定要跳过的字符串*/
string = "iosVSandroid";
sscanf(string, "%[a-z]VS%[a-z]", buf1, buf2);
printf("7.string=%s\n", string);
printf("7.buf1=%s, buf2=%s\n\n", buf1, buf2);
/*
**执行结果:
**7.buf1=ios, buf2=android
*/
/*8.分割以某字符隔开的字符串*/
string = "android-iphone-wp7";
/*
**字符串取道'-'为止,后面还需要跟着分隔符'-',
**起到过滤作用,有点类似于第7点
*/
sscanf(string, "%[^-]-%[^-]-%[^-]", buf1, buf2, buf3);
printf("8.string=%s\n", string);
printf("8.buf1=%s, buf2=%s, buf3=%s\n\n", buf1, buf2, buf3);
/*
**执行结果:
**8.buf1=android, buf2=iphone, buf3=wp7
*/
/*9.提取邮箱地址*/
string = "Email:beijing@sina.com.cn";
sscanf(string, "%[^:]:%[^@]@%[^.].%s", buf1, buf2, buf3, buf4);
printf("9.string=%s\n", string);
printf("9.buf1=%s, buf2=%s, buf3=%s, buf4=%s\n\n", buf1, buf2, buf3, buf4);
/*
**执行结果:
**9.buf1=Email, buf2=beijing, buf3=sina, buf4=com.cn
*/
/*10.过滤掉不想截取或不需要的字符串--补充,
**在%号后面加一*号,代表过滤这个字符串,不读取
*/
string = "android iphone wp7";
sscanf(string, "%s %*s %s", buf1, buf2);
printf("10.string=%s\n", string);
printf("10.buf1=%s, buf2=%s\n\n", buf1, buf2);
/*
**执行结果:
**10.android wp7
*/
sprintf
把格式化的数据写入字符串
sprintf(buffer, "%d:%d:%d", a, b, c);
string和char*转换
char* str = s.c_str();
string s(str);
strlen
int len = strlen();
strcpy、strcmp、strcat
strcpy(a, b);
strcmp(a, b);
strcat(a, b);
容器
string
头文件:<string>
find
string s = "123";
string::size_type pos1 = s.find("4");
if (pos1 == s.npos) printf("not found");
int pos2 = s.find("4");
if (pos2 == -1) printf("not found");
insert
s.insert(2, s2);//在s的下标位置2插入字符串s2
substr
string s("123456");
string s2 = s.substr(1, 3);//截取从下标位置1开始,长度为3个字符组成的串"234"
string s3 = s.substr(1);//截取从下标位置1开始,一直到结尾的串"23456"
erase
string s("123456");
s.erase(1, 3);//删除从标位置1开始的长度为3的字符串
append
也可以用+=
实现
s.append(s2);//s后面追加s2
replace
s.replace(1, 3, s2);//从标位置1开始的长度为3的字符串用s2来代替
assign
赋值。也可以用=
实现
s.assign(s2);
compare
也可以用< > ==
实现.
如果两个字符串相等,那么返回0,调用对象大于参数返回1,小于返回-1。
数值转换
c++11
string和数值转换 | |
---|---|
to_string(val) | 把val转换成string |
stoi(s,p,b) | 把字符串s从p开始转换成b进制的int |
stol(s,p,b) | long |
stoul(s,p,b) | unsigned long |
stoll(s,p,b) | long long |
stoull(s,p,b) | unsigned long long |
stof(s,p) | float |
stod(s,p) | double |
stold(s,p) | long double |
s=to_string(100);
int a = stoi("-123");
map
对应的数据结构是红黑树.
插入数据
用insert函数插入数据,当map中有这个关键字时,insert操作是插入数据不了的;但是用数组方式可以覆盖以前该关键字对应的值。
map<int, int> m;
m[1] = 1;//数组方式
m.insert(pair<int, int>(1, 2));//insert插入pair
erase
m.erase(1);//删除关键字为1的键值对
clear
删除所有元素。
unordered_map
对应的数据结构是哈希表,用于高效率查询的情况。
使用方法与map类似。
vector
初始化
vector<int> v;//初始化一个size为0的vector
vector<int> v(10);//初始化size,但每个元素值为默认值
vector<int> v(10,1);//初始化size,并且设置初始值
int a[5] = {1,2,3,4,5};
vector<int> v(a, a+5);//通过数组地址初始化
vector<int> a(10,1);
vector<int> v(a);//通过同类型的vector初始化
push_back
vector<int> v;
v.push_back(1);
struct Num {
int a, b;
};
vector<Num> v;
v.push_back({1, 2});//添加结构体或类对象时可以用{}来初始化对象,{}内变量的顺序为结构体或类中成员对象的声明顺序
resize
改变容器的大小,并插入新元素。
void resize (size_type n);
void resize (size_type n, value_type val);//用val来初始化这些新插入的元素
- 当n小于当前size()值时候,vector首先会减少size()值,保存前n个元素,然后将超出n的元素删除
- 当n大于当前size()值时候,vector会插入相应数量的元素,使得size()值达到n,并对这些元素进行初始化。
v.resize(5, 1);
algorithm
sort
//默认升序排序
vector<int> v;
sort(v.begin(), v.end());
//使用自己的排序函数
bool cmp(int a, int b) {
return a > b;
}
sort(v.begin(), v.end(), cmp);
//排序元素是结构体,排序传参建议用“const+引用”传参,这样更快
struct Num {
int a, b;
};
bool cmp(const Num &n1, const Num &n2) {
return n1.a == n2.a ? n1.b < n2.b : n1.a > n2.a;//这么写
}
find
vector<int> v;
vector<int>::iterator it = find(v.begin(), v.end(), 1);
int index = it - v.begin();//若找不到,则返回last的位置(last越界)
lower_bound和upper_bound
lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置(last越界)
pos = lower_bound(a, a + 5, 1) - a
pos = lower_bound(a, a + 5, 1, greater<int>()) - a//在降序数组中查找第一个小于或等于val的第一个元素位置
upper_bound()在first和last中的前闭后开区间进行二分查找,返回大于val的第一个元素位置。如果所有元素都小于val,则返回last的位置(last越界)
pos = upper_bound(a, a + 5, 1) - a
pos = upper_bound(a, a + 5, 1, greater<int>()) - a//在降序数组中查找第一个小于val的第一个元素位置
distance
计算两个iterator的距离(非线性容器的iterator不能加减)
list<int> l;
list<int>::iterator it = find(l.begin(), l.end(), 1);
int dis = distance(l.begin(), it);
functional
greater
sort(a, a+5, greater<int>());//降序排序