STL-Tools

格式化输出

操作

  1. 基础设置

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 强制显示符号

  1. 对齐
  • cout<<left<<c<<endl; 左对齐

  • cout<<right<<c<<endl; 右对齐

  1. 精度
  • 小数位数 cout<<setprecision(8)<<fixed<<c<<endl; 小数,c必须为小数
  • 有效位数 cout<<setprecision(8)<<c<<endl;
  1. 科学计数法

cout<<scientific<<c<<endl;

  1. 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

  1. 读取到数组
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打印到1
  • sscanf(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

实例

  • [] (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)

用法

  1. 只读
vector<int> arr;
for (auto n : arr)
{
   std::cout << n << std::endl;
}
  1. 读写(加上引用符号)
vector<int> arr;
for (auto &n : arr)
{
   std::cout << n << std::endl;
}
  1. 注意
  • for循环的这种使用方式的内在实现实际上还是借助迭代器的,所以如果在循环的过程中对arr进行了增加和删除操作,将会导致错误
posted @ 2020-03-30 19:38  身在迷途  阅读(301)  评论(0)    收藏  举报