本篇适合初学或基础较薄弱的人,大佬们自动绕行
目录
常用头文件
#include<iostream>
#include<sstream>
#include<cmath>
#include<algorithm>
#include<string>
字符串的各种操作
创建读取对象
string s;
char ss[5000];//scanf不支持string对象
scanf("%s",&ss);//scanf的速度要比cin快很多
string s3(4, 'K'); // s3 = "KKKK",
string s4("12345", 1, 3); //s4 = "234",即 "12345" 的从下标 1 开始,长度为 3 的子串
string s1("12345");
s3.assign(s1); // s3 = s1
s2.assign(s1, 1, 2); // s2 = "23",即 s1 的子串(1, 2)
s2.assign(4, 'K'); // s2 = "KKKK"
s2.assign("abcde", 2, 3); // s2 = "cde",即 "abcde" 的子串(2, 3)
查看大小
s.length();
添加
尾部直接相加
s.append("balabala");
中间添加
string s1("Limitless"), s2("00");
s1.insert(2, "123"); //在下标 2 处插入字符串"123",s1 = "Li123mitless"
s1.insert(3, s2); //在下标 2 处插入 s2 , s1 = "Li10023mitless"
s1.insert(3, 5, 'X'); //在下标 3 处插入 5 个 'X',s1 = "Li1XXXXX0023mitless"
string::iterator it;
it=s.begin();
s.insert(it+x,'c');//这里只能是一个字符,若添加多个字符有警告但正常运行,添加了多个字符中的最后一个。多个字符可使用for循环实现。
访问
s[0]
s[0]-'a'
string s1 = "this is ok";
string s2 = s1.substr(2, 4); // s2 = "is i"
s2 = s1.substr(2); // s2 = "is is ok"
删除
s.erase(it+x);
s.erase(it+x,it+x+y);//删除区间
s="";//清空
替换
string s1("West”), s2("East");
s1.swap(s2); // s1 = "East",s2 = "West"
s.replace(x,y,str,a,b);//s的第x个开始,连续y个替换为str的第a个开始的b个。
翻转
string s="123456";
reverse(s.begin(),s.end());//s="654321"
搜索
- find:从前往后查找子串或字符出现的位置。
- rfind:从后往前查找子串或字符出现的位置。
- find_first_of:从前往后查找何处出现另一个字符串中包含的字符。例如:
- s1.find_first_of(“abc”); //查找s1中第一次出现"abc"中任一字符的位置
- find_last_of:从后往前查找何处出现另一个字符串中包含的字符。
- find_first_not_of:从前往后查找何处出现另一个字符串中没有包含的字符。
- find_last_not_of:从后往前查找何处出现另一个字符串中没有包含的字符。
- s.find(“xxx”);//找不到返回string::npos
比较
s.compare("xxx");s比字符串大,返回1,相等返回0,小于返回-1
s1.compare(1, 2, s2, 0, 3); //比较s1的子串 (1,2) 和s2的子串 (0,3)
分离子串
string s1,s2,s3;
char sa[100],sb[100],sc[100];
char haha[]="abc 123 pc";
sscanf(haha,"%s %s %s",sa,sb,sc);//对应sa sb sc子串
s1=sa;
s2=sb;
s3=sc;
//当用到数字的时候,跟scanf一样,他要传送指针地址
//字符串分离为数字
int a,b,c;
sscanf("1 2 3","%d %d %d",&a,&b,&c);
类型转换
//将string字符串转换为字符串数组
#include<string.h> //调用strcpy()函数所需头文件
char c[20];
string str="abcd";
strcpy(c,str.c_str());
//int转string
int n = 0;
stringstream ss;
string str;
ss<<n;
ss>>str;
ss.clear();//清空
//string转int
std::string str = "123";
int n = atoi(str.c_str());
下面这个是简易版的正数转换
int strtoint(string s)
{
int len=s.length();
int x=0;
for(int i=0;i<s.length();i++)
{
int t=1;
for(int j=1;j<=len-1-i;j++)
{
t=t*10;
}
x+=(s[i]-'0')*t;
}
return x;
}
string inttostr(int t)
{
string s="";
while(t!=0)
{
s+=t%10+'0';
t=t-t%10;
t=t/10;
}
reverse(s.begin(),s.end());
return s;
}
查找子示例
string a,b;
cin>>a>>b;
int res=0;
for(int i=0;i<a.length()-b.length()+1;i++)
{
if(b==a.substr(i,b.length()))
{
res++;
}
}
cout<<res<<endl;
return 0;
其他操作
字符字母转换
char类型的大写字母直接+32变为相应小写,相反,char类型的小写字母直接-32变为相应大写(‘A’:64,‘0’:48)
char类型的数字与int类型数字转化
char a='6';
int b=a-'0';//b=6
===================
int a=6;
char b=a+'0';//b='6'
scanf,cin
scanf的返回值由后面的参数决定scanf("%d%d", &a, &b);
如果a和b都被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
while(cin>>a)的调用,这里并不是cin的返回值,而是>>操作重载函数
istream& operator>>(istream&, T &);的返回值,其中第二个参数由cin>>后续参数类型决定。其返回值类型为istream&类型,大多数情况下其返回值为cin本身(非0值),只有当遇到EOF输入时,返回值为0。
输入EOF的方法,windows下输入ctrl+z, Linux下输入ctrl+d。
while (cin >> n, n)表示输入n,并且n不为零,则运行while循环里面的,如果为零,则跳出循环
相当于
while (cin >> k) {
n = k;
if (n == 0)
break;
}
小数点
cout.precision(3);
cout<<fixed<<x<<endl;
//或
cout<<setprecision(3)<<s<<endl;//需要#include <iomanip>
iomanip输出格式控制
这里面#include <iomanip>的作用比较多:主要是对cin,cout之类的一些操纵运算子,比如setfill,setw,setbase,setprecision等等。它是I/O流控制头文件,就像C里面的格式化输出一样.以下是一些常见的控制函数的:
dec 置基数为10 相当于"%d"
hex 置基数为16 相当于"%X"
oct 置基数为8 相当于"%o"
setfill(c) 设填充字符为c
setprecision(n) 设显示小数精度为n位
setw(n) 设域宽为n个字符,这个控制符的意思是保证输出宽度为n
setioflags(ios::fixed) 固定的浮点显示
setioflags(ios::scientific) 指数表示
setiosflags(ios::left) 左对齐
setiosflags(ios::right) 右对齐
setiosflags(ios::skipws) 忽略前导空白
setiosflags(ios::uppercase) 16进制数大写输出
setiosflags(ios::lowercase) 16进制小写输出
setiosflags(ios::showpoint) 强制显示小数点
setiosflags(ios::showpos) 强制显示符号
如:
cout<<setw(3)<<1<<setw(3)<<10<<setw(3)<<100; 输出结果为
1 10100 (默认是右对齐)当输出长度大于3时(<<1000),setw(3)不起作用
cout<<setiosflags(ios::fixed)<<setiosflags(ios::right)<<setprecision(2);
合在一起的意思就是,输出一个右对齐的小数点后两位的浮点数
等比数列
等比数列前n项和 S n = a 1 ( 1 − q n ) 1 − q , ( q ≠ 1 ) S_n=\frac{a_1(1-q^n)}{1-q},(q\neq1) Sn=1−qa1(1−qn),(q=1)
最大公约数
欧几里得方法:只要两数不相等,就反复用大数减小数,直到相等为止,此相等的数就是两数的最大公约数
int gcd(int x,int y)
{
while(x!=y)
{
if(x>y)
{
x=x-y;
}
else
{
y=y-x;
}
}
return x;
}
最小公倍数
最 小 公 倍 数 = x / g c d ( x , y ) ∗ y \mathrm{最小公倍数}=x/gcd(x,y)\ast y 最小公倍数=x/gcd(x,y)∗y
res=x/gcd(x,y)*y;//gcd定义见上方
素数
bool isprime(int n)
{
int sqr=sqrt(n*1.0);
for(int i=2;i<=sqr;i++)
{
if(n%i==0)
{
return false;
}
}
return true;
}
十进制转化为二进制
string trans(int n)
{
string s="";
for(int a=n;a;a=a/2)
{
s=s+(a%2?'1':'0');
}
reverse(s.begin(),s.end());
return s;
}
溢出问题
标准只规定long不小于int的长度,int不小于short的长度
double与int类型的存储机制不同,long int的8个字节全部都是数据位,而double是以尾数,底数,指数的形式表示的,类似科学计数法,因此double比int能表示的数据范围更广。
long long在win32中是确实存在,长度为8个字节;定义为LONG64。
为什么会出现long int呢?在win32现在系统中,长度为4;在历史上,或者其他某些系统中,int长度为2,是short int。
即便是long long,在TI的有款平台中,长度为5也就是说,每种类型长度,需要sizeof才知道,如果可能,最好用union看看里面的数据,可以消除一些类型的假象长度。
类型名称 | 字节数 | 取值范围 |
---|---|---|
signed char | 1 | -128~+127 |
short int | 2 | -32768~+32767 |
int | 4 | -2147483648~+2147483647 |
long int | 4 | -2147483648~+2141483647 |
long long long int | 8 | -9223372036854775808~+9223372036854775807 |
- unsigned int (unsigned long)
4字节8位可表达位数:2^32=42 9496 7296
范围:0 ~ 42 9496 7295 (42*10^8) - int (long)
4字节8位可表达位数:2^32=42 9496 7296
范围:-21 4748 3648 ~ 21 4748 3647 (21*10^8) - long long (__int64)
8字节8位可表达位数:2^64=1844 6744 0737 0960 0000
范围:-922 3372 0368 5477 5808 ~ 922 3372 0368 5477 5807 (922*10^16) - unsigned long (unsigned __int64)
8字节8位可表达位数:2^64=1844 6744 0737 0960 0000
范围:0 ~ 1844 6744 0737 0955 1615 (1844*10^16)
贴一个解决100!的代码,把每个数分开存储,数字逐位计算
#include<stdio.h>
#define max 1000
int a[max]={0};
int main()
{
a[0]=1;
for(int i=2;i<=100;i++)
{
int carry=0;
for(int j=0;j<max;j++)
{
int s=a[j]*i+carry;
a[j]=s%10;
carry=s/10;
}
}
int i=0;
for(i=max-1;i>0;i--)
{
if(a[i]!=0)
{
break;
}
}
for(int j=i;j>=0;j--)
{
printf("%d",a[j]);
}
printf("\n");
}
三角形面积坐标公式
在△ABC中,若A(x1,y1),B(x2,y2),C(x3,y3) 则△ABC的面积
S
=
1
2
×
∣
(
x
1
y
2
+
x
2
y
3
+
x
3
y
1
−
x
2
y
1
−
x
3
y
2
−
x
1
y
3
)
∣
\begin{array}{l}S=\frac12\times\vert(x_1y_2+x_2y_3+x_3y_1-x_2y_1-x_3y_2-x_1y_3)\vert\\\end{array}
S=21×∣(x1y2+x2y3+x3y1−x2y1−x3y2−x1y3)∣
S
=
1
2
×
∣
(
(
x
2
−
x
1
)
×
(
y
3
−
y
1
)
×
(
x
3
−
x
1
)
×
(
y
2
−
y
1
)
)
∣
\begin{array}{l}S=\frac12\times\vert((x_2-\;x_1)\times(y_3-y_1)\times(x_3-x_1)\times(y_2-y_1))\vert\\\end{array}
S=21×∣((x2−x1)×(y3−y1)×(x3−x1)×(y2−y1))∣
海伦公式:
p
=
(
a
+
b
+
c
)
/
2
p=(a+b+c)/2
p=(a+b+c)/2
S
=
p
(
p
−
a
)
(
p
−
b
)
(
p
−
c
)
S=\sqrt{p(p-a)(p-b)(p-c)}
S=p(p−a)(p−b)(p−c)
数学函数
分解
double modf (double x, double* y); 将参数的整数部分通过指针(y)回传,函数返回小数部分
起到分解函数的作用
取余
double fmod (double, double); 返回两参数相除的余数:
取整
double ceil (double); 取上整 2.345->3
double floor (double); 取下整 2.345->2
指数与对数
double exp (double);
double pow (double, double);
double sqrt (double);
double log (double); 以e为底的对数
double log10 (double);c++中自然对数函数:log(N) 以10为底:
log10(N)但没有以2为底的函数但是可以用换底公式解决:log2(N)=log10(N)/log10(2)
时间与日期计算
闰年判断
(year%400 || year%4==0 && year%100!=0)
关于时间计算的time.h
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
time_t convert(tm* tp,int year, int month, int day, int hour,
int minute, int second) {
tm info;
info.tm_year = year - 1900;
info.tm_mon = month - 1;
info.tm_mday = day;
info.tm_hour = hour;
info.tm_min = minute;
info.tm_sec = second;
time_t miaoshu= mktime(&info);
*tp = info;
return miaoshu;
}
int main() {
time_t now = time(NULL);
printf("%d\n", now); //打印当前时间的秒数
tm info = *localtime(&now); //把秒数转换为年月日时分秒还有周几 tm是一个结构体
now += 300 * 24 * 3600;
info = *localtime(&now); //计算300天后的信息
tm* f_info=(tm*)malloc(sizeof(tm*));
time_t start = convert(f_info,2013, 2, 5, 0, 0, 0); //将输入的日期转化为秒数,同时也会得到日期信息
printf("%d", (*f_info).tm_wday);
time_t end = convert(f_info, 2015, 4, 6, 0, 0, 0);
// 差值
int diff = (int)(end - start);
// 计算是多少天
int days = diff / (24 * 3600);
printf("%d\n", days);
return 0;
}
表达式求值
先贴一个简单版的
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
double a[100],sum=0;
char c;
int i=0;
scanf("%lf",&a[0]);
c=getchar();
while(c!='\n')
{
double temp;
scanf("%lf",&temp);
switch(c)
{
case '+':a[++i]=temp;break;
case '-':a[++i]=-temp;break;
case '*':a[i]*=temp;break;
case '/':a[i]/=temp;break;
}
c=getchar();
}
for(int j=0;j<=i;j++)
{
sum=sum+a[j];
}
if(sum-int(sum)<=1e-6) printf("%.0f\n",sum);
else printf("%.1f\n",sum);
}
return 0;
}
持续更新中!
Ref
字符串:http://c.biancheng.net/view/400.html
https://www.cnblogs.com/helloforworld/p/5655493.html
https://www.cnblogs.com/aminxu/p/4704281.html
溢出:https://blog.csdn.net/qq_16234613/article/details/77541722
常用技巧:
https://blog.csdn.net/weixin_36406616/article/details/89381176
dev:
支持c++11:https://blog.csdn.net/u011500062/article/details/44628441
时间:
https://blog.csdn.net/l773575310/article/details/53258230
https://blog.csdn.net/momingqimiao71/article/details/84728845