STL-Tools
格式化输出
操作
- 基础设置
dec 置基数为10 相当于"%d"
hex 置基数为16 相当于"%X"
oct 置基数为8 相当于"%o"
setfill(c) 设填充字符为c 等价 cout.fill('*');
setprecision(n) 设显示小数精度为n位
setw(n) 设域宽为n个字符 等价 cout.width(12);fixed 以浮点数进行输出,并且开启填充
showpoint 强制显示小数点
showpos 强制显示符号
- 对齐
cout<<left<<c<<endl; 左对齐
cout<<right<<c<<endl; 右对齐
- 精度
- 小数位数 cout<<setprecision(8)<<fixed<<c<<endl; 小数,c必须为小数
- 有效位数 cout<<setprecision(8)<<c<<endl;
- 科学计数法
cout<<scientific<<c<<endl;
- printf
-:有-表示左对齐输出,如省略表示右对齐输出。
m.n:m指域宽,即对应的输出项在输出设备上所占的字符数。n指精度。用于说明输出的实型数的小数位数。为指定n时,隐含的精度为n=6位。
特点
- 只对一次cout有效
#include<iomanip>
示例
// hex
cout<<hex<<15<<endl;
// setw(n)
// setfill
cout<<setw(10)<<setfill('-')<<"nb"<<endl;//--------nb
// cout.fill(*)
cout.width(12);
cout.fill('*');
cout<<"nb"<<endl;
// 小数点后几位
double a= 10.2234;
cout << "a=" <<fixed<< setprecision(2) << a <<endl; //输出a=10.22
// 有效数位
cout<<setprecision(3)<<a<<endl;//10.2
math
函数
函数 | 作用 |
---|---|
int abs(int i); | 返回整型参数i的绝对值 |
double fabs(double x); | 返回双精度参数x的绝对值 |
long labs(long n); | 返回长整型参数n的绝对值 |
double exp(double x); | 返回指数函数e^x的值 |
double log(double x); | 返回logex的值 |
double log10(double x) | 返回log10x的值 |
double pow(double x,double y) | 返回x^y的值 |
double pow10(int p) | 返回10^p的值 |
double sqrt(double x) | 返回+√x的值 |
double acos(double x) | 返回x的反余弦arccos(x)值,x为弧度 |
double asin(double x) | 返回x的反正弦arcsin(x)值,x为弧度 |
double atan(double x) | 返回x的反正切arctan(x)值,x为弧度 |
double cos(double x) | 返回x的余弦cos(x)值,x为弧度 |
double sin(double x) | 返回x的正弦sin(x)值,x为弧度 |
double tan(double x) | 返回x的正切tan(x)值,x为弧度 |
double hypot(double x,double y) | 返回直角三角形斜边的长度(z),x和y为直角边的长度,z2=x2+y^2 |
double ceil(double x) | 返回不小于x的最小整数 |
double floor(double x) | 返回不大于x的最大整数 |
int rand() | 产生一个随机数并返回这个数 |
double atof(char *nptr) | 将字符串nptr转换成浮点数并返回这个浮点数 |
double atol(char *nptr) | 将字符串nptr转换成长整数并返回这个整数 |
double atof(char *nptr) | 将字符串nptr转换成双精度数,并返回这个数,错误返回0 |
int atoi(char *nptr) | 将字符串nptr转换成整型数, 并返回这个数,错误返回0 |
long atol(char *nptr) | 将字符串nptr转换成长整型数,并返回这个数,错误返回0 |
数据范围
有符号整数类型
类型名称 | 字节数 | 取值范围 |
---|---|---|
signed char | 1 | -2^7(-128) ~ 2^7-1(127) |
short int 或 short | 2 | -2^15(-32 768) ~ 2^15-1(32 767) |
int | 4 | -2^31(-2 147 483 648) ~ 2^31-1(2 147 483 647) |
long int 或 long | 4 | -2^31(-2 147 483 648) ~ 2^31-1(2 147 483 647) |
long long int 或 long long | 8 | -2^63(-9.2233720368548e+18) ~ 2^63-1(9.2233720368548e+18) |
无符号整数类型
类型名称 | 字节数 | 取值范围 |
---|---|---|
unsigned char | 1 | 0 ~ 2^8-1(255) |
unsigned short int 或 unsigned short | 2 | 0 ~ 2^16-1(65 535) |
unsigned int | 4 | 0 ~ 2^32-1(4 294 967 295) |
unsigned long int 或 unsigned long | 4 | 0 ~ 2^32-1(4 294 967 295) |
unsigned long long int 或 unsigned long long | 8 | 0 ~ 2^64-1(1.844674407371e+19) |
浮点类型
类型名称 | 字节数 | 取值范围 |
---|---|---|
float | 4 | -/+3.4e38(精确到6位小数) |
double | 8 | -/+1.7e308(精确到15位小数) |
long double | 12 | -/+1.19e4932(精确到18位小数) |
极限符号
浮点类型
类型名称 | 下限 | 上限 |
---|---|---|
float | FLT_MIN | FLT_MAX |
double | DBL_MIN | DBL_MAX |
long double | LDBL_MIN | LDBL_MAX |
有符号
类型名称 | 下限 | 上限 |
---|---|---|
char | CHAR_MIN | CHAR_MAX |
short | SHRT_MIN | SHRT_MAX |
int | INT_MIN | INT_MAX |
long | LONG_MIN | LONG_MAX |
long long | LLONG_MIN | LLONG_MAX |
无符号
类型名称 | 下限 | 上限 |
---|---|---|
unsigned char | 0 | UCHAR_MAX |
unsigned short | 0 | USHRT_MAX |
unsigned int | 0 | UINT_MAX |
unsigned long | 0 | ULONG_MAX |
unsigned long long | 0 | ULLONG_MAX |
read data
cin
definition
-
std::cin流对象在解析流缓冲区对象时,默认使用空白符(空格,或者制表符 \n等)作为分隔符,输入string的话,遇到空格,回车,tab都会结束;如果要接收带空格的字符串的话可以用getline()。
-
cin>>x;符返回值不是你输入的数,而是cin
-
流对象的内部状态是什么,它在读取失败就返地false
-
或者遇到EOF,比如你按(ctrl+z)
EX:
while(cin>> x){}
循环读取数据
-
example
//输入 hello world 它输出 hello
string s=" ";
cin>>s;
cout<<s<<endl;
//虽然输入hello world,但是只解析出hello并赋值给s,此时world仍然在流缓冲区中。hello也在,只是流对象中的当前指针指向了world处。
//
int a[3];
char A,B,C;
cin>>a[0]>>a[1]>>a[2];// 输入 1 2 3
cin>>A>>B>>C;// 输入 ABC
cin.get()
definition
- cin.get() 读取一个字符,常用来清除换行符,舍弃输入流中的不需要的字符
- cin.get(ch) 读取到ch
- ch=cin.get()
- cin.get(数组地址,接受字符数目) 不能读取到string,可以接受空格
注意
- cin.get 不适合string,适合char类型数组
- 与
ch=getchar();
类似
example
- 读取到数组
char a[20];
cin.get(a,20); //有些类似getline。可以输入多个单词,中间空格隔开。
cout<<a<<endl;
//输入:jkl jkl jkl
//输出:jkl jkl jkl
//输入:abcdeabcdeabcdeabcdeabcde (输入25个字符)
//输出:abcdeabcdeabcdeabcd (接收19个字符+1个'\0')
getline
definition
istream& getline ( istream &is , string &str , char delim );
- istream &is 表示一个输入流,譬如cin;
- string&str表示把从输入流读入的字符串存放在这个字符串中
- char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为'\n'
example
string name;
getline(cin, name);
cin.getline()
definition
- cin.getline(数组地址,接受的字符数); 与cin.get(arr,len)基本相同。
- cin.getline(数组地址,接受的字符数,结束字符);
注意
- cin.getline 不适合string,适合char类型数组
- 与
gets(arr);
类似
example
// 1.结束字符
char m[20];
cin.getline(m,5,'a');
//输入jkaljkljkl时,输出jk
// 2. 多维数组
for(int i=0;i<3;i++)
{
cout<<"\n请输入第"<<i+1<<"个字符串:"<<endl;
cin.getline(m[i],20);
}
file read
example
#include<fstream>
#include<sstream>
fileread(const string &filename){
ifstream file(filename);// 文件流
string line;
int a,b;// 假如读取a,b
if(file.is_open()){
getline(file,line);// 得到line
stringstream ss(line);// 由line得到ss
ss>>a>>b;
}
}
类型间转换
STL常用类型转换函数
操作
字符串转数字
- atoi(int x):ASCII to integer,将字符串转换成整形,从数字或正负号开始转换,一直到非数字为止,返回值为结果
- atof:ascii to double--字符串转换成double
- atol:ascii to long---字符串转换成long
整数转字符串
itoa(int x,char *str,int jz):转换成字符串,x是被转换的整数,str转换后储存字符串,jz为转换进制数,如2,8,10,16进制等,str是char_buffer
str或者返回值为结果
ltoa:将长整型值转换为字符串。
ultoa:将无符号长整型值转换为字符串。
浮点数转字符串
- gcvt:float转换成字符串(四舍五入)
- ecvt:将双精度浮点型值转换为字符串,转换结果中不包含十进制小数点。
字符串转数字(报告)
- strtod():将字符串转换为双精度浮点型值,并报告不能被转换的所有剩余数字。
- strtol():将字符串转换为长整值,并报告不能被转换的所有剩余数字。
- strtoul():将字符串转换为无符号长整型值,并报告不能被转换的所有剩余数字。
杂项
- toascii:将整形转换成合法的ASCII码字符
- _ttoi:可以将CString转换成整形
- _itot_s:将int转换成char*
example
// itoa
char str[100];
itoa(int1,str,10);
cout<<str<<endl;
// atoi
string string2="99";
cout<<atoi(string2.data())<<endl;
字符串和数字的转换
stringstream
操作
stringstream ss;
定义ss<<source;
输入ss>>result;
输出ss.str();
转化为字符串,如字符转化为字符串ss.clear();ss.str("");
清空缓冲区 clear()并不会真正清除内存
example
// 数字->字符串
#include<string>
#include<sstream>
int main(){
double source = 123.12;
string result;
stringstream ss;
ss<<source;
ss>>result;// 转化为字符串
return 0;
}
// 字符串->数字
#include<string>
#include<sstream>
int main(){
double result;
string source="123.12";
stringstream ss;
ss<<source;
ss>>result;// 转化为数字
return 0;
}
sprintf()与sscanf()
操作
sprintf(1,2的类型,2)
// 将2打印到1sscanf(1,2的类型,2)
// 将1输入到2
数字->字符串
#include <iostream>
#include <string>
using namespace std;
int main()
{
char str[10];
int a=1234321;
//将整数转化为字符串
sprintf(str,"%d",a);
int len=strlen(str);
cout<<"字符串"<<str<<endl;
cout<<"长度"<<len<<endl;
char str1[10];
double b=123.321;
/ /将浮点数转化为字符串
sprintf(str1,"%.3lf",b);
int len1=strlen(str1);
cout<<"字符串"<<str1<<endl;
cout<<"长度"<<len1<<endl;
return 0;
}
字符串->数字
#include <iostream>
#include <string>
using namespace std;
int main()
{
char str[]="1234321";
int a;
sscanf(str,"%d",&a);
cout<<a<<endl;
char str1[]="123.321";
double b;
sscanf(str1,"%lf",&b);
cout<<b<<endl;
return 0;
}
字符转化为字符串
操作
ss<<char;
ss>>str;或s=ss.str();
example
// example1
char c;
string s;
stringstream ss;
ss<<c;
ss>>str;//s=ss.str();
//example2: 重复利用别忘了清空+设置为空串
for(int i=0;i<9;i++){
ss<<ISBN[i];
tempString = ss.str();
ss.clear();
ss.str("");
ss<<tempString;
ss>>temp;
ss.clear();
ss.str("");
sum+= temp*(i+1);
}
string与char *转换
string转char *
- char* p=str.data();
- char* p=str.c_str();
char *转string
- str = p;// 赋值就能转换
- string str(char*);// 构造函数
常用常量
- π:
#define pi 3.1415926
高精度
模板
模板1(vector实现)
#include<iostream>
#include<sstream>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
using namespace std;
struct Wint:vector<int>//用标准库vector做基类,完美解决位数问题,同时更易于实现
{
// 进位函数,低位在前,高位在后
//将低精度转高精度的初始化,可以自动被编译器调用
//因此无需单独写高精度数和低精度数的运算函数,十分方便
Wint(int n=0)//默认初始化为0,但0的保存形式为空
{
push_back(n);
check();
}
Wint& check()//在各类运算中经常用到的进位小函数,不妨内置
{
while(!empty()&&!back())pop_back();//// 去高位的0,比如被借走了
if(empty())return *this;
for(int i=1; i<size(); ++i)//处理进位
{
(*this)[i]+=(*this)[i-1]/10;
(*this)[i-1]%=10;
}
while(back()>=10)
{
push_back(back()/10);
(*this)[size()-2]%=10;
}
return *this;//为使用方便,将进位后的自身返回引用
}
};
//输入输出
istream& operator>>(istream &is,Wint &n)// 将字符数字 输入到n,n里面是倒序存储
{
string s;
is>>s;
n.clear();
for(int i=s.size()-1; i>=0; --i)n.push_back(s[i]-'0');
return is;
}
ostream& operator<<(ostream &os,const Wint &n)
{
if(n.empty())os<<0;
for(int i=n.size()-1; i>=0; --i)os<<n[i];
return os;
}
//比较,只需要写两个,其他的直接代入即可
//常量引用当参数,避免拷贝更高效
bool operator!=(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return 1;
for(int i=a.size()-1; i>=0; --i)
if(a[i]!=b[i])return 1;
return 0;
}
bool operator==(const Wint &a,const Wint &b)
{
return !(a!=b);
}
bool operator<(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return a.size()<b.size();
for(int i=a.size()-1; i>=0; --i)
if(a[i]!=b[i])return a[i]<b[i];
return 0;
}
bool operator>(const Wint &a,const Wint &b)
{
return b<a;
}
bool operator<=(const Wint &a,const Wint &b)
{
return !(a>b);
}
bool operator>=(const Wint &a,const Wint &b)
{
return !(a<b);
}
//加法,先实现+=,这样更简洁高效
Wint& operator+=(Wint &a,const Wint &b)
{
if(a.size()<b.size())a.resize(b.size());
for(int i=0; i!=b.size(); ++i)a[i]+=b[i];
return a.check();
}
Wint operator+(Wint a,const Wint &b)
{
return a+=b;
}
//减法,返回差的绝对值,由于后面有交换,故参数不用引用
Wint& operator-=(Wint &a,Wint b)
{
if(a<b)swap(a,b);
for(int i=0; i!=b.size(); a[i]-=b[i],++i)
if(a[i]<b[i])//需要借位
{
int j=i+1;
while(!a[j])++j;// 寻找进位
while(j>i)
{
--a[j];
a[--j]+=10;
}
}
return a.check();
}
Wint operator-(Wint a,const Wint &b)
{
return a-=b;
}
//乘法不能先实现*=,原因自己想
Wint operator*(const Wint &a,const Wint &b)
{
// a位数*b位数=a位+b位-1位 或 a位+b位
Wint n;
n.assign(a.size()+b.size()-1,0);
for(int i=0; i!=a.size(); ++i)
for(int j=0; j!=b.size(); ++j)
n[i+j]+=a[i]*b[j];
// 第i位*第j位 结果在第i+j位(i,j从0开始)
// 第i位*第j位 结果在第i+j-1位(i,j从1开始)
return n.check();
}
Wint& operator*=(Wint &a,const Wint &b)
{
return a=a*b;
}
//除法和取模先实现一个带余除法函数
Wint divmod(Wint &a,const Wint &b)
{
// a位数/b位数=a位+b位+1位 或 a位-b位
Wint ans;
for(int t=a.size()-b.size(); a>=b; --t)
{
Wint d;
d.assign(t+1,0);//00...00
d.back()=1;//00...01
Wint c=b*d;//00...0[数组b] 共a.size()位
while(a>=c)
{
a-=c;
ans+=d;// 商增加d=00...01
}
}
return ans;//商
}
Wint operator/(Wint a,const Wint &b)
{
return divmod(a,b);
}
Wint& operator/=(Wint &a,const Wint &b)
{
return a=a/b;
}
Wint& operator%=(Wint &a,const Wint &b)
{
divmod(a,b);
return a;
}
Wint operator%(Wint a,const Wint &b)
{
return a%=b;
}
//顺手实现一个快速幂,可以看到和普通快速幂几乎无异
Wint pow(const Wint &n,const Wint &k)
{
if(k.empty())return 1;
if(k==2)return n*n;
if(k.back()%2)return n*pow(n,k-1);
return pow(pow(n,k/2),2);
}
int main()
{
Wint a,b;
cin>>a>>b;
cout<<"*: "<<a*b<<endl;
cout<<"-: "<<a-b<<endl;
cout<<"/: "<<a/b<<endl;
cout<<"+: "<<a+b<<endl;
}
example
example1-高精度求阶乘
#include<bits/stdc++.h>
using namespace std;
int a[2000];
int b[2000];
int c[2000];
int sum[2000];
void pplus(int *a,int *c){// 加到c里面
int jw=0;
for(int i=1;i<=1000;i++){
c[i]+=a[i]+jw;
jw=c[i]/10;
c[i]%=10;
}
}
void cheng(int *a,int c){// 乘到a 里面
int jw=0;
for(int i=0;i<=1000;i++){
a[i] = a[i]*c+jw;
jw=a[i]/10;
a[i]%=10;
}
}
int main(){
int n;
cin>>n;
a[1] =1;
for(int i=1;i<=n;i++){
cheng(a,i);
pplus(a,c);
}
bool flag=0;
for(int i=1000;i>=1;i--){
if(c[i]!=0) flag=1;
if(flag) cout<<c[i];
}
}
定义数组
静态
- int array[100]; 定义了数组array,并未对数组进行初始化
- int array[] = {xx,xx,...}; 定义并初始化了数组array
- int array[100]={}; 定义数组,全部初始化为0;
- int array[100]={12,32}; 前面的两个为12,32,剩下的初始化为0;
动态
-
int* array = new int[100]; delete []array; 分配了长度为100的数组array
-
int* array = new int[100](1,2); delete []array; 为长度为100的数组array初始化前两元素
-
二维动态数组
//n*m维 int **arr=new int*[n]; for(int i=0;i<n;++i){ arr[i]=new int[m]; } for(int i=0;i<n;i++){ delete []arr[i]; } delete []arr;
初始化
-
int array[100]={};定义数组,全部初始化为0;
-
int array[100]={12,32}; 前面的两个为12,32,剩下的初始化为0;
-
memset(数组名,0或者-1,sizeof(数组名));
建议使用memset()的时候初始化为0或者-1(其他值有可能出错),用fill较好
-
fill(begin(),end(),value);
-
fill(array,array+length,value);
比较器
用法
-
less
() //从小到大排序 < -
greater
() //从大到小排序 > -
less_equal
() // <= -
gtater_equal
()// >=
example
sort(numbers,numbers+5,greater<int>());
从0/1开始-公式推导
介绍
index | 公式 |
---|---|
i(从0开始) | n-i-1 |
j-1(j从1开始,j-1从0开始) | n-(j-1)-1 |
j-1+1(j从1开始) | n-(j-1)-1+1 |
j(从1开始) | n-j+1 |
lambda
介绍
[capture] (parameters) mutable ->return-type {statement}
capture
- [] //不捕获变量.试图在Lambda内使用任何外部变量都是错误的.
- [x] //仅仅x安装值捕获
- [x,&y] //x按值捕获,y按引用捕获.
- [&] //用到的任何外部变量都隐式按引用捕获
- [=] //用到的任何外部变量都隐式按值捕获
- [&,x] //x显式地按值捕获.其它变量按引用捕获
- [=,&z] //z按引用捕获.其它变量按值捕获
- [this] //函数体内可以使用 Lambda 所在类中的成员变量。
实例
- [] (int x, int y) { return x + y; } // 隐式返回类型
- [] (int x, int y) -> int
- [] (int& x) { ++x; } //没有return -> Lambda 函数的返回类型是 'void'
- [] () { ++global_x; } // 没有参数,仅访问某个全局变量
- [] { ++global_x; } // 与上一个相同,省略了 (操作符重载函数参数)
- auto f =[]{return xx;} cout<<f()<<endl;// 调用
注意
- []内捕获的参数和()传递的参数不同
example
//1
vector<int> some_list;
int total = 0;
for (int i = 0; i < 5; ++i) some_list.push_back(i);
for_each(begin(some_list), end(some_list), [&total](int x){
total += x;
});
//2
int a = 6;
int b = 8;
auto sum = [](int a,int b) ->int{return a + b;};
printf("sum[%d]\n",sum(a,b));
return 0;
//打印结果:sum[14]
for(auto x:array)
用法
- 只读
vector<int> arr;
for (auto n : arr)
{
std::cout << n << std::endl;
}
- 读写(加上引用符号)
vector<int> arr;
for (auto &n : arr)
{
std::cout << n << std::endl;
}
- 注意
- for循环的这种使用方式的内在实现实际上还是借助迭代器的,所以如果在循环的过程中对arr进行了增加和删除操作,将会导致错误