变量类型:
bool
: true/false 大小为1Byte
char
:单引号引起的字符,大小为1Byte
int
:范围-231~231-1的整数,大小为4Byte
float
精度6-7位有效数字的整数,大小为4Byte
double
精度14-15位有效数字的浮点数,大小位8Byte
long long
:范围-263~263-1的整数,大小为8Byte
long double
精度18-19位有效数字的浮点数,大小为16Byte
变量定义:
int a,b = 2, c = 2;
float d = 1.5, e = 1, f = 1.2345e2;
bool g = true, h = false;
char i = 'a',j = 'j';
long long l = 12345678987654321LL;
long double m = 123.45;
cin
,cout
输入输出语句:
cin >> a >> b; //输入语句
cout << a+b <<' ' << a*b << endl; //输出语句
scanf
,printf
输入输出语句
#include
#include
using namespace std;
int main()
{
int a,b;
scanf("%d%d",&a,&b); //输入语句
printf("a*b=%d\na*b=%d",a+b,a*b); //输出语句
printf("a*b=%.2f")
return 0;
}
cin
和scanf
的区别:
cin可以跳过空格,scanf会读入空格,cin执行效率低,scanf执行效率高
类型转换:
运算过程中,精度低的会转化为精度高的
tips:
1.做算法用浮点数时,建议用double,精度高
2.保留有效几位小数,用printf
3.整数,浮点数混在一起乘除,注意整数之间的除法会不会变成整除
using namespace std的作用:
常用头文件:iostream
cstring
algorithm
printf格式化输出:
#include
using namespace std;
int main()
{
int a = 1;
int b = 12;
int c = 123;
printf("%5d\n",a); //字长为5,右对齐,补齐加空格
printf("%-5d\n",b); //字长为5,左对齐,补齐加空格
printf("%05d\n",c); //字长为5,补齐加0字符
return 0;
}
#include
using namespace std;
int main()
{
int score;
cin >> score;
if(score>60) cout << "及格" << endl;
else cout << "不及格" << endl;
return 0;
}
if else 条件下只有一条语句,可以不加括号,否则要加
(1) 大于 >
(2) 小于 <
(3) 大于等于 >=
(4) 小于等于 <=
(5) 等于 ==
(6) 不等于 !=
#include
using namespace std;
int main()
{
int grade;
cin >> grade;
if(grade>=85) cout<<'A'<<endl;
else if(grade>=75) cout<<'B'<<endl;
else if(grade>=60) cout<<'C'<<endl;
else cout<<'D'<<endl;
return 0;
}
与: &&
或 :||
非: !
转移字符:
\n
换行 \'
单引号字符 \"
双引号字符 %%
字符串中显示%
AcWing668 游戏时间2
给出两个时间点,计算出间隔的时间数
思路:
将两个时间换算成距离0点0分的分钟数在计算,若结束时间大于开始时间,则间隔的分钟数=结束时间对应的分钟数-开始时间对应的分钟数
若结束时间小于开始时间,说明经过了一天,则间隔的分钟数=结束时间对应的分钟数+1440(一天的分钟数
)-开始时间对应的分钟数
题解代码:
#include
#include
using namespace std;
int main()
{
int a,b,c,d;
cin >> a >> b >> c >> d;
int x = a*60+b; //开始时间对应的分钟数
int y = c*60+d; //结束时间对应的分钟数
if(y>x) printf("O JOGO DUROU %d HORA(S) E %d MINUTO(S)",(y-x)/60,(y-x)%60);
else printf("O JOGO DUROU %d HORA(S) E %d MINUTO(S)",(y+1440-x)/60,(y+1440-x)%60);
return 0;
}
把控制循环次数的变量从循环体中剥离,基本结构如下:
for (init-statement : condition: expression)
{
statement
}
init-statement可以是声明语句、表达式、空语句,一般用来初始化循环变量;
condition 是条件表达式,和while中的条件表达式作用一样;可以为空,空语句表示true
expression 一般负责修改循环变量,可以为空
#include
#include
using namespace std;
int main()
{
for(int i=1;i<=10;i++)
{
cout << i << endl; //输出1-10
}
return 0;
}
循环版的if语句。If语句是判断一次,如果条件成立,则执行后面的语句;while是每次判断,如果成立,则执行循环体中的语句,否则停止。
#include
#include
using namespace std;
int main()
{
int i = 1;
while(i<=10)
{
cout << i << endl; //输出1-10
i++;
}
return 0;
}
do while语句与while语句非常相似。唯一的区别是,do while语句限制性循环体后检查条件。不管条件的值如何,我们都要至少执行一次循环。
#include
#include
using namespace std;
int main()
{
int i = 0;
do
{
i++;
}while(i<0);
cout << i << endl;
int j = 0;
while(j<0)
{
j++;
}
cout << j << endl; //两个都不满足条件,但是do while先执行了一次
//所以i=1,j=0
return 0;
}
break
:可以提前从循环中退出,不再执行循环体内的语句
continue
:跳到下次循环的开头,不执行循环体内该次循环这条语句后的语句
打印n阶方阵
#include
#include
using namespace std;
int main()
{
int n;
cin >> n;
for(int i=0,k=1;i<n;i++)
{
for(int j=0;j<n;j++,k++)
{
cout << k << " " ;
}
cout << endl;
}
return 0;
}
曼哈顿距离:把两个点坐标的 x 坐标相减取绝对值,y 坐标相减取绝对值,再加和
c = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ c=|x1-x2|+|y1-y2| c=∣x1−x2∣+∣y1−y2∣
思路:观察n阶菱形中点的坐标,发现每个点到中心点的曼哈顿距离都小于 ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor ⌊2n⌋
#include
#include
#include
using namespace std;
int main()
{
int n;
cin >> n;
int cx = n/2,cy = n/2;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if((abs(i-cx)+abs(j-cy))<=n/2) cout << "*";
else cout << " ";
}
cout << endl;
}
return 0;
}
int a[3] = [0,1,2]; //定义一个长度为3的数组
int b[3] = {0,1,1}; //定义一个长度为3的数组
int c[5] = {0,1,2}; //等价与{0,1,2,0,0}空缺的元素默认用0补全
char d[] = {'a','b','c'};
函数内部定义的数组都是随机赋值的,且数组存储与栈内存中,大小有限制,约为1M
而函数外部定义的数组都初始化为0,且存储在堆内存中,大小可以很大(受内存限制),因此定义较大的数组一般放在函数外面
#include
using namespace std;
int main()
{
int n,m;
cin >> n >> m;
int a[n];
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
Leecode 189 旋转数组
暴力解法:
旋转一次前,记录下数组的最后一个元素为temp,之后把所有的元素都往后移一个单位,再在空出的第一个位置填上temp
代码如下:
#include
using namespace std;
int main()
{
int n,m;
cin >> n >> m;
int a[n];
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++)
{
int temp=a[n-1];
for(int j=n-1;j>0;j--) a[j]=a[j-1];
a[0] = temp;
}
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
优化解法:
以数组【1,2,3,4,5】,旋转2次为例
操作 | 数组 |
---|---|
初始状态 | 【1,2,3,4,5】 |
目标状态 | 【1,2,3,4,5】 |
①将整个数组翻转 | 【5,4,3,2,1】 |
②将对应的前半部分数组翻转 | 【4,5,3,2,1】 |
③将后半部分数组翻转 | 【4,5,1,2,3】 |
代码如下:
#include
#include
using namespace std;
int main()
{
int n,k;
cin >> n >> k;
int a[n];
for(int i=0;i<n;i++) cin>>a[i];
reverse(a,a+n);
reverse(a,a+k);
reverse(a+k,a+n);
for(int i=0;i<n;i++) cout << a[i] << " ";
return 0;
}
#include
using namespace std;
int main()
{
int a[3][4]={{0,1,2,3}, //定义一个三行四列的数组
{4,5,6,7},
{8,9,10,11}};
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
}
需要先调用cstring
头文件
memset
: memset是以字节为单位,初始化内存块。
初始化数组时,格式如下
memset(数组名, 0, sizeof 数组名); // 初始化为全零数组
memcpy
:内存拷贝函数,从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中,格式如下:
memcpy(拷贝目的数组, 拷贝原数组, sizeof 原数组);
#include
#include
using namespace std;
int main()
{
int a[10],b[10];
for(int i=0;i<10;i++) a[i]=i; //a=[0,1,2,3,4,5,6,7,8,9]
memcpy(b,a,sizeof a); //复制a数组到b数组
memset(a,0,sizeof a); //初始化a数组
for(int i=0;i<10;i++) cout << b[i] << " ";
cout << endl;
for(int i=0;i<10;i++) cout << a[i] << " ";
return 0;
}
练习题:
Acwing 754 平方矩阵II
Acwing 756 蛇形矩阵
每个常用字符都对应一个-128~127的数字,二者之间可以相互转化
#include
using namespace std;
int main()
{
for(int i=1;i<128;i++) printf("%d: %c\n",i,(char)i);
return 0;
}
常用ASCII值:’A’-‘Z’ 是65~90,’a’-‘z’是97-122,’0’-‘9’是48-57。
字符可以参与运算,运算时会将其当做整数:
#include
using namespace std;
int main()
{
char a1[] = {'c','+','+'}; //列表初始化,没有结尾\0空字符
char a2[] = {'c','+','+','\0'}; //列表初始化,有结尾\0空字符
char a3[] = "c++"; //自动添加\0空字符
cout << sizeof a3 << endl; //a3长度为4,后面自动补上\0
return 0;
}
cin输入 cout输出
:
char a[100],b[100];
cin >> a; //cin读入
scanf("%s",b); //scanf读入,注意:不要加取地址符
cin >> a+1; //从下标1开始存
输出:cout
printf
,puts
:
#include
using namespace std;
int main()
{
char a1[] = "ABCDEFG"; //定义字符串
cout << a1 << endl; //cout 输出
printf("%s\n",a1); //printf("%s")输出
puts(a1);
cout << a1+1 << endl;
printf("%s\n",a1+1); //a1+1表示从B开始输出
return 0;
}
cin scanf 都是遇到空格,回车就停止了
fgets()
:可读入到字符数组中,fgets(字符数组名,读取长度,stdin)
注意:fgets()会把回车读进来
char a[100],b[100];
fgets(a,100,stdin);
getline()
:读到string里,getline(cin,读入的string变量名)
string s;
getline(cin,s);
strlen()
strcmp()
strcpy()
#include
#include
using namespace std;
int main()
{
char a[100],b[100];
cin >> a;
strcpy(b, a); //将字符串b复制给从a开始的字符数组。
cout << strlen (a) << endl; //strlen (a) 返回a的字符串长度
cout << strcmp(a,"abc") << endl; //strcmp(s1,s2) string compare 比较两个字符串的大小,
//a < b 返回-1,a == b 返回0,a > b返回1。这里的比较方式是字典序!
cout << b << endl; //复制的b
return 0;
}
#include
#include
#include
using namespace std;
int main()
{
char a[100];
cin >> a;
for(int i=0,len = strlen(a);i<len;i++) cout << a[i] << endl;
return 0;
}
#include
using namespace std;
int main()
{
string s1; //默认初始化为一个空字符串
string s2 = "ABCD"; //s2设为值为ABCD的字符串
string s3 = s2; //将s2复制给s3
string s4(10,'c'); //s4为10个c
return 0;
}
string能用cin
读入,不能用scanf
读入
string可以用cout
,printf
输出
#include
#include
using namespace std;
int main()
{
string s1 = "abc",s2 = "abcd";
cout << s1.empty() << endl; //返回string是否为空
cout << s1.size() << endl; //返回string的长度
cout << s1>s2 << endl; //string 的比较 支持 > < >= <= == !=等所有比较操作,按字典序进行比较。
string s3 = s1+s2;
cout << s3 << endl; //两个string对象相加
//s3的值为abcabcd
return 0;
}
注意:
字面值和string对象相加:
做加法运算时,字面值和字符都会被转化成string对象,因此直接相加就是将这些字面值串联起来:
string s1 = “hello”, s2 = “world”; // 在s1和s2中都没有标点符号
string s3 = s1 + “, “ + s2 + ‘\n’;
当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string:
string s4 = s1 + ", "; // 正确:把一个string对象和有一个字面值相加
string s5 = "hello" +", "; // 错误:两个运算对象都不是string
string s6 = s1 + ", " + "world"; // 正确,每个加法运算都有一个运算符是string
string s7 = "hello"+ ", " + s2; // 错误:不能把字面值直接相加,运算是从左到右进行的
substr()
取出字串的函数:
s.substr(p, len)
返回一个string,包含s中从p开始的len个字符的拷贝(pos的默认值是0,n的默认值是s.size() - len,即不加参数会默认拷贝整个s)
另外,若len的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾
可以将string对象当成字符数组来处理
#include
#include
using namespace std;
int main()
{
string s1 = "Hello World";
for(int i =0;i<s1.size();i++) cout << s1[i] << endl; //for遍历string
for(char c: s1) cout << c << endl; //for(遍历的赋值变量:string 对象名)
//等价于for(int i =0;i
for(char &c:s1) c='0'; //加上&,可以对源string进行修改操作
cout << s1 << endl;
return 0;
}
stringstream
把字符串初始化为一个类似于cin的方式,从中读出需要的信息
#include
#include
using namespace std;
int main()
{
string s;
getline(cin,s);
int a,b;
double c;
string str;
stringstream ssin(s); //把str转化为stringstream类型
ssin >> a >> b >> str >> c ;
cout << a << endl << b << endl << str << endl << c << endl;
return 0;
}
练习题:
Acwing 770 单词替换
Acwing 771 字符串中最长的连续出现的字符
Acwing 777 字符串的乘方
Acwing 778 字符串最大跨距
Acwing 779 最长公共字符串后缀