万能头文件
#include<bits/stdc++.h>
数组最大范围
int型一维数组:小于
4e8
,即4亿int型二维数组:小于
2e4
, 即2万
数据类型范围
int
和long
都是用32位来存储最大值和最小值分别为2147483647(231-1 ~ 109), -2147483648(-231);
long long
是用64位来存储最大值和最小值分别为9223372036854775807(1018),-9223372036854775808;
float
的最大值和最小值分别为3.40282e+038(1038),1.17549e-038(10-38);
double
的最大值和最小值分别为1.79769e+308(10308),2.22507e-308(10-308)
#include<limits.h>
INT_MIN:最小值
INT_MAX:最大值
数据量与复杂度
复杂度 | 数据量 |
---|---|
O(n!) | 10 |
O(2n) | 20 |
O(n3) | 500 |
O(n2) | 2500 |
O(nlogn) | 106 |
O(n) | 107 |
O(n1/2) | 1014 |
O(logn) | 1020 |
读入字符串
char ch[20];
cin>>ch; //只能读入一行不带空格、tab、换行的字符串
cin.getline(ch, 20); //最长可以读入19个字符串,最后一个是'\0',允许带空格
string str;
getline(cin, str); //随便读入
//getchar与putchar
getchar用于读入单个字符,putchar用于输出单个字符
//gets与puts
gets(char *str)与puts(char *str),分别表示读入和输出一行字符串
注意在使用c++的输入cin
与getline
时,如果是先使用cin
再使用getline
,中间需要用一个cin.ignore()
读走cin的回车,否则会直接跳过本次getline的读入
位运算
7个位运算(&,|,^,~,>>,<<,>>>)
按位与&:两个全为1,结果为1,否则为0
a, b两个数按位与的话,结果一定小于等于a和b num &= num - 1; // 最低的 1 变成 0 6 & 5 => 4 0110 & 0101 => 0100
按位或|:两位有一个为1,结果为1,否则为0
num |= num + 1; // 最低的 0 变成 1 6 | 7 => 7 0110 | 0111 => 0111
按位异或^:相同为0,不同为1
按位取反~:0->1,1->0
算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位
算术左移<<:符号位不变,低位补0
“>>>”:逻辑右移也叫无符号右移,运算规则是:低位溢出,高位补0
函数传参数组长度问题
函数传递一个数组时传入的是指针,在函数内不能得到数组的长度,需要手动传递长度
typedef
用于给数据类型取别名
#include <stdio.h>
typedef long long LL; //给long long 取别名为LL,这样使用此数据类型时就可直接使用别名
int main() {
LL a = 123456789;
printf("%lld", a);
return 0;
}
符号常量与const常量
符号常量又称宏定义,是替换的意思,就是将用到标识符的对应位置替换成常量3.14,
const是赋值,将值赋给常量
//符号常量
#define 标识符 常量值
#define PI 3.14
//const常量
const 数据类型 常量名 = 常量值
const double PI = 3.14;
注意define后面没有分号;
,const后面有分号
推荐使用const,因为宏定义还能够表示一个片段,有时会出现错误
#include<stdio.h>
#define cal(x) (x * 2 + 1)
int main() {
printf("%d\n", cal(1 + 2));
return 0;
}
//输出:6
或许会认为输出的会是7,但是要知道宏定义表示的是替换的意思,直接将1+2
代入到了表达式中,为1+2*2+1
,所以结果为6
浮点数的比较
如果要判断两个浮点数相等,需要用到eps = 1e-8,进行如下操作
const double eps = 1e-8;
fabs((a) - (b)) < eps //这样才能判断两浮点数相等,否则可能出错
同理我们可以通过eps这个极小的数来判断两个数的大小关系
Π
#include<stdio.h>
#include<math.h>
int main() {
double PI = acos(-1.0);
printf("%f\n", PI);
}
//输出:3.141593
进制转换
进制符号前缀表示
二进制:0b或0B(是数字0,不是字母O)
八进制:0
十六进制:0x
整数:
十进制转k进制:除k取余法,将结果取倒数
k进制转十进制:从最右边开始,每位数乘以k的位数-1次方,最后将每一个结果相加
二进制转八进制:从低位开始,每3个二进制一组的结果拼接,不足3位往高位补0
二进制转十六进制:从低位开始,每4个二进制一组的结果拼接,不足4位往高位补0
八进制转二进制:从低位开始,将每个数转为3位的二进制
十六进制转二进制:从低位开始,将每个数转为4位的二进制
小数:
十进制小数转k进制:将小数乘k,将结果的整数保存起来。重复上述操作,直到小数部分为0。将整数部分按顺序组合就是小数的二进制表示。简称:乘k取整,顺序排列
注意:小数的进制转换可能会出现无限循环的情况
二进制转十进制:将小数每个数乘以2—位数,
二进制转八进制:将小数部分每3位一组做二进制表示,不足3位往低位补0,将结果拼接
二进制转十六进制:将小数部分每4位一组做二进制表示,不足4位往低位补0,将结果拼接
注意:
8进制(%o)与10进制(%d)与16进制(%x)的直接相互转换,可以直接通过c语言自带的sacnf与printf的格式限定符完成
二进制减法
当遇到0 - 1
的情况时,需要从前借一位,如10 - 01 = 0(10)
- 01 = 1,这里的0(10)中的10其实就是十进制的2
原码、反码、补码
1、二进制的最高位是符号位:0表示正数,1表示负数(0->0,1->-)
2、正数的原码,反码,补码都一样
3、负数的反码 = 它的原码符号位不变,其他位取反(0->1,1->0)
4、负数的补码 = 它的反码+1;负数的反码 = 负数的补码-1
5、0的反码、补码都是0
6、在计算机运算时,都是以补码的方式来运算的
7、当我们在看运算结果时,要看它的原码
输入输出
基本格式
%g
能够精简格式,并去掉末尾多余的0
sscanf和sprintf
sscanf(从左至右)
#include<stdio.h>
int main() {
int n;
char str[10] = "123";
sscanf(str, "%d", &n);
printf("%d\n", n);
return 0;
}
//输出:123
sscanf(str, "%d", &n)就是将数组str中的内容以%d的形式写入n中
sprintf(从右至左)
#include<stdio.h>
int main() {
int n = 223;
char str[10];
sprintf(str, "%d", n);
printf("%s\n", str);
return 0;
}
//输出:223
#include<stdio.h>
int main() {
int n = 223;
char str[10];
sprintf(str, "%d", n);
for(int i = 0; i < 10; i++) {
printf("%d ", str[i] - '0');
}
return 0;
}
//输出:2 2 3 -48 -48 -48 -48 -48 -47 -48
//可知sprintf是一位一位存进字符数组的,并且在数组中是字符形式
sprintf(str, "%d", n)就是将n的值以%d的形式传给数组str
lambda表达式
格式:
[外部变量访问方式说明符] (参数) mutable noexcept/throw() -> 返回值类型
{
函数体;
};
// (mutable noexcept/throw() -> 返回值类型)都可省略
auto display = [](int a,int b) -> void{cout << a << " " << b;}
auto display = [](int a,int b) {cout << a << " " << b;}
外部变量格式 | 功能 |
---|---|
[] | 空方括号表示当前 lambda 匿名函数中不导入任何外部变量。 |
[=] | 只有一个 = 等号,表示以值传递的方式导入所有外部变量; |
[&] | 只有一个 & 符号,表示以引用传递的方式导入所有外部变量; |
.与->的区别
.
主要用于类对象,->
用与指针引用其成员
class A {
int a;
}
A p;
A *q;
p.a; // 对象
q->a; // 指针
for(auto &i:s)和for(auto i:s)的区别
前者是引用类型,可以对s进行修改,后者不能修改s,形如void swap(int a, int b) 与 void swap(int &a, int &b)