c++学习
vector:可(扩展)变数据类型
输入输出
cin:c in 输入 cout:c out 输出
流操作符
<<
输出流操作符
>>
输入流操作符
转义符的使用
\n 换行 等同于 std::endl(end line) \t tab键 \转义符
头文件
include 引入
<iostream>
input | output :io 输入输出 stream:流(类比“水流”,字符流|字节流|文件流”)
变量
变量
只是一个名称,它代表 计算机内存的特定位置,供用户 存储 、检索 和 使用 数据。
数据类型
- int :整数(整型)
- double :浮点数 | float(实型)
- char :字符
- string :字符串
- bool :布尔值(真/假值)
变量的声明
在一个变量可以使用之前,我们需要事先声明(创建)变量。要声明一个变量,我们需要确定两个内容:
- 变量的类型
- 变量的名称
int score = 0;
//等效于
int score;
score =0
算术运算符
+
加法-
减法*
乘法/
除法%
求余(获得整数除法后的余数)
头文件
.h(head)c语言的头文件以.h
结尾
iostream c++的头文件
C++中的输出:cout
在C++
中,输出操作使用对象cout
,需要包含头文件cout
的主要特点和用法:
cout
是一个对象,不是关键字或函数。- 可以输出常量和变量,根据需要连续输出。
- 相对于
printf
,cout
能够自动识别变量的类型,无需指定格式符。 - 输出控制使用特定的控制符,如
endl
和\n
。
C语言中的输出:printf
在C语言中,输出操作使用函数printf
,需要包含头文件printf
的主要特点和用法:
printf
是一个函数。- 需要指定格式符来输出变量的类型,如
%c
、%d
、%s
等。 - 可以根据需要连续输出,但需要为每个变量指定相应的格式符。
向量与循环结构
向量
创建向量格式:
std::vector<type>name;
//列如:
std::vector<int>grades(3);
它只能存储同类型的元素
所需的头文件:
#include <vector>
向量初始化
方法1:创建时直接初始化
std::vector<double>location = {121.674849,31.14839};
大括号之间的两个double数据,就是向量locaton的初始值(经度、纬度)
方法2:
std::vector<double>location;
location = {121.674849,31.14839};
方法3: 先声明,后对成员内容赋值
std::vector<douvle>location;
location[0] = 121.674849;
location[1] = 31.14839;
添加与删除向量中的元素
.push_back() 压人一个元素
如果需要在向量的末尾(也就是最后一个元素之后)添加一个新元素 可以使用.push_back()
.pop_back() 弹出一个元素
如果我们想把向量的最后一个元素 移除,我们要使用的方法就是.pop_back()
英文字母
char类型 是一种存储字符的变量。
计算:M在字母表中是第几位。
#include <iostream>
using namespace std;
int main()
{
int a ;
a = 'M'-'A'+ 1;
cout<<a<<endl;
}
计算:第18位是什么字母
#include <iostream>
using namespace std;
int main()
{
int a ;
a = 'M'-'A'+ 1;
cout<<a<<endl;
char b;
b = 'A' + (18- - 1);
cout<<b<<endl;
}
字符 要用
''
单引号进行括起来。
数字反转
方法1
#include <iostream>
using namespace std;
int main() {
double p;
int a, b, c, d, q;
cin >> p;
q = int(p * 10);
a = q / 1000;
b = q / 100 % 10;
c = q / 10 % 10;
d = q % 10;
cout << d << "." << c << b << a << endl;
return 0;
方法2
#include <iostream>
using namespace std;
int main() {
char a, b ,c ,dot , d;
cin>>a>>b>>c>>dot>>d;
cout<<d<<dot<<c<<b<<a;
}
scanf | printf 占位符
用于 格式化输入输出 数据的方法之一。
可以指定不同格式,如保留多少位浮点数、输出的数据占多宽的空间,等等。
这些占位符常用于 C 语言风格的输入输出方式,即scanf/printf
。
这些占位符,都以百分号%
为开头。
其它格式化输出
方法3:使用scanf与printf实现数字反转(p5705)。
#include <cstdio>
int main() {
char a,b,c,d;
scanf("%c%c%c.%c",&a,&b,&c,&d);
printf("%c.%c%c%c",d,c,b,a);
}
再分肥宅水
这道题需要使用浮点数进行运算,输出时指定了精度。 可以使用占位符 %lf 输入, %.3f 输出。
#include<cstdio>
using namespace std;
int main() {
double t;
int n;
scanf("%lf%d", &t, &n);
printf("%.3f\n%d", t / n, n * 2);
return 0;
}
顺序结构程序设计案例
交换变量
交换变量 例 2.9 定义两个变量 a 和 b 并输入两个数字存储进它们。 交换这两个变量并输出。
a=b;b=a;
行不行呢?
假设给你一杯可乐,一杯雪碧,要如何把这两个杯子中的饮料进行交换呢?
t = a;a = b;b = t;
一组相关的短语句也可以写在一行内
算法竞赛的基本格式
一般来讲,对于输入的内容,每个数字之间以空格或者回车隔开。 如图,是洛谷题目 P1425 的输入样例。
请仔细阅读输入格式和输出格式,了解如何输入输出。
分支结构
apples
x为1输出apple。x > 1 输出 apples
方法1:
#include <iostream>
using namespace std;
int main(){
int x ;
cin >> x;
if(x== 1){
cout << "Today,I ate 1 apple " << endl;}
else{
cout << "Today,I ate " << x << " apples ";
}
}
方法2:
include <iostream>
using namespace std;
int main(){
int x ;
cin >> x;
cout << "Today,I ate " << x << " apple";
if(x > 1){
cout << "s";
}
}
小洛机器人
#include <iostream>
using namespace std;
int main(){
char ch;
cin >> ch;
switch (ch) {
case 'G':
cout << "Hello, my master!" << endl;
// cout << "I'm Xiaoluo." << endl;
// break;
case 'N':
cout << "I'm Xiaoluo." << endl;
break;
case 'S':
cout << "Teinei teinei teinei~"<< endl;
break;
case 'B':
case 'Q':
cout << "Bye bye!" << endl;
break;
default:
cout << "Sorry..." << endl;
}
关系表达式与逻辑表达式
运算优先级
浮点数精度误差
浮点数可能会产生精度误差 所以一般不用== 来判断两个浮点数是否相等 正确的方式:比较这两个数的差值是否小于一定程度 假设fabs(a-b)<1e-6
成立,就可以认为浮点数a 和b 相等。注意要用<cmath> 头文件
double a, b;
......
if (a == b) // 这么写是错误的!会造成浮点数误差!
if (fabs(a - b) < 1e-6) // 正确的写法,注意 <cmath>
数的性质 (p5710)
例3.2(洛谷P5710)
一些数字可能拥有以下的性质:
- 性质1:是偶数;
- 性质2:大于4 且不大于12。
小A 喜欢这两个性质同时成立的数字;Uim喜欢这至少符合其中 一种性质的数字;八尾勇喜欢刚好有符合其中一个性质的数字; 正妹喜欢不符合这两个性质的数字。
现在输入一个数字x(0≤x≤100),要求输出这4 个人是否喜欢这 个数字,如果喜欢则输出1,否则输出0,用空格分隔。
闰年判断
例3.3(洛谷P5711)
输入一个年份(大于1582 的整数),判断这一年是否为闰年,如 果是输出1,否则输出0。
- 被4 整除(p1)是闰年,除非
- 被100 整除(p2)不是闰年,除非
- 被400 整除(p3)又是闰年
#include <iostream>
using namespace std;
int main(){
int n ;
cin >> n;
bool p1,p2,p3;
p1 = (n % 4) == 0;
p2 = (n % 100 ) == 0; // 成立是平年 不成立是闰年
p3 = (n % 400 ) == 0;
if(p3 || (p1 && !p2) ){
cout << "闰年" << endl;
}
复习1:
顺序结构与条件结构:
小鱼的游游泳时间(p1425)
成绩
使用 分数计算,避免触及 浮点运算:
printf("%d", a * 2/10 + b * 3/10 + c * 5 /10);
解法 1: 注意“A,B,C 都是 10 的整数倍”。 每一小项经过加权,即使有乘上一个小数,但是结果一定是整数。 可以把 0.2 变成 2/10, 使程序不接触浮点数,不必考虑浮点误差。
*2 / 10 ,整个运算中都中整型运算, /运算,自动舍去小数部分。
解法2:
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
printf("%d", int(a * 0.2 + b * 0.3 + c * 0.5 + 0.5)); return 0;
直接加权计算。
int(……) 是指不是整数的内容 强制转换 为 int 类型,舍掉小数位数 只保留整数 。double(……) 可以强制转换为 double 。
为什么最后加上了一个 0.5?是因为浮点误差(例如 89.9999)。
小玉买文具
总结
double
: 用于存放小数的变量类型。char
: 用于存放字符的变量类型。 ASCII将每个字母和数字对应。cin>>
a: 用于读入输入的信息给表示变量 a 。 一道题目如果按照题意不好解决,不妨想想能不能换一种数据处 理的方式,比如把数字当成字符
。
嵌套条件
if …… else if …… else ……
短路判断
计算表达式时,如果只计算部分内容就可以确保一个表达式的结 果,那么剩余部分计算机就不会继续运算下去了。 例如:
a||(b&&!c)
,当a 为真,表达式肯定也是真,不用继续算a&&(b||c||d||e||f)
,当a 为假,表达式肯定为假x>0&&sqrt(x)-round(sqrt(x))<1e-6
,当x是负数时,后面的就不 会继续运算,也不会造成RE。
体重BMI
double m, h, BMI;
cin >> m >> h;
BMI = m / h / h;
if (BMI < 18.5)
cout << "Underweight";
else if (BMI < 24)
cout << "Normal";
else {
cout << BMI << endl;
cout << "Overweight" << endl;
}
for循环
找最小值
- 头文件algorithm的max(),min(),和abs()
- max() min()参数为两个,可以是整型或浮点型,返回最大值和最小值
- 适用于个数不多的比较时
- abs()返回绝对值,整数
- math的fabs(),进行浮点数的取绝对值功能
解法1:使用minnum
#include <algorithm>
int n;
cin << n;
//int tmp = 2147483647;
int tmp, minnum =2100000000;
for(int i = 1; i <= n ; i++){
cin << tmp;
minnum = min(minnum , tmp)
}
cout << minnum;
解法2:使用if
int n;
cin << n;
//int tmp = 2147483647;
int tmp, minnum =2100000000;
for(int i = 1; i <= n ; i++){
cin << tmp;
// 比较 最新输入的值是不是比当前最小值还小
if(tmp < minnum){
minnum = tmp;
}
}
cout << minnum;
while循环
一尺之棰
注意,从第二天开始,所以定义days 默认为1;
include using namespace std;
int main() { int a; int days = 1;
// a = 1 cin >> a;
while (a > 1) {
days++;
a = a / 2;
cout << “days: “ << days << “ a: “ << a << endl; }
cout << days; }
多重循环
循环语句也能互相嵌套。如果需要循环的“大操作”中有好几个重复 的小操作,就可以进行循环嵌套。 如果超过一个语句,或者需要调整层级,则必须要大括号,建议 全部加上括号。
注意内层循环变量名不能和外层循环变量名冲突。
for (;;) {
for (;;) {
for (;;) {
// 内层循环体
}
}
for (;;)
while (...) {
// 内层循环体
}
}
数字直角三角形
我们可以把这个任务分成两个层级
- 大任务:输出每一行。需要一个外层循环,其循环体就是输出 一行的内容。循环变量从 1 到 n (也可以 0 到 n-1)。
- 小任务:输出一行中的每一个数字。需要一个内层循环,用于 输出一行中的每一个数字。共需要打出 n 行,所当处理第 i 行时, 需要输出 n-i+1 个数字。
定义变量 cnt 来记录输出到那个数字
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
int cnt = 0,n;
scanf("%d",&n);
for ( int i = 0;i <= n ; i++){
for ( int j = 1; j <= n - i ; j++){
++cnt;
printf("%02d",cnt);
}
cout << endl;
}
}
求阶乘之和
long long n ; 有效值为 9 * 10^18 ;
例 4.7 (洛谷 P1009,有改动)
计算 S = 1! + 2! + 3! + ⋯ + n! (n ≤ 20) 的值,其中 i! 是指 i 的阶乘,即 i! = 1 × 2 × ⋯ × i 。
分析: 按计算器可发现, 20 的阶乘大约 2.4 × 1018,所以可以使用 long long 类型存下。
long long 是一种整数类型,可以放下 9 × 1018的数字,但是比 int 又大又慢。
,
逗号表达式
将两个不同的表达式写在了一起,变成了一条语句,变成了逗号表达式。 有时可以使语句变得精炼。
//正确写法 1 使用大括号包括多个语句
if (t1 + t2 > maxtime) {
maxtime = t1 + t2; maxday = 1;
}
//正确写法2使用逗号表达式链接多个语句成为一个语句
if (t1 + t2 > maxtime)
maxtime = t1 + t2, maxday = 1;
//错误写法,第二个语句不在if管辖范围内
if (t1 + t2 > maxtime)
maxtime = t1 + t2; maxday = 1;
通常用于类似 “变量交换”
三位数排序(p5715)
方法一: 排列组合进行穷举(列举)所有的可能。
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if (a <= b && b <= c) printf("%d %d %d\n", a, b, c);
else if (a <= c && c <= b) printf("%d %d %d\n", a, c, b);
else if (b <= a && a <= c) printf("%d %d %d\n", b, a, c);
else if (b <= c && c <= a) printf("%d %d %d\n", b, c, a);
else if (c <= a && a <= b) printf("%d %d %d\n", c, a, b);
else /*if (c <= b && b <= a)*/ printf("%d %d %d\n", c, b, a);
方法二: 求出某个最大值,再对别两个值进行判断
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if (a >= b && a >= c)
if (b >= c)
printf("%d %d %d\n", c, b, a);
else
printf("%d %d %d\n", b, c, a); // 这个else搭配哪个if呢?
else if (b >= a && b >= c)
if (a >= c)
printf("%d %d %d\n", c, a, b);
else
printf("%d %d %d\n", a, c, b);
else // if (c >= a && c >= b) 本句可加可不加
if (a >= b)
printf("%d %d %d\n", b, a, c);
else
printf("%d %d %d\n", a, b, c);
int a = 8, b =6, tmp;
// 交换 a,b
tmp = a, a = b, b = tmp;
方法三: 三次交换
int a, b, c, p;
scanf("%d%d%d", &a, &b, &c);
if (a > b)
p = a, a = b, b = p;
if (a > c)
p = a, a = c, c = p;
if (b > c)
p = b, b = c, c = p;
printf("%d %d %d", a, b, c);
?
问号表达式
问号表达式与叫“三目表达式”
问号表达式的形式是 S1?S2:S3
如果S1条件成立,那么这个表达式的值是S2,否则是S3。 例如: 意思是b= (a==1) ? 2 : 3
也就是当a==1 成立时,(a==1) ? 2 : 3
的值是2,即b 赋2;否 则(a==1) ? 2 : 3 的值是3,b 赋值3. b=a==1?2:3
cout << status == 1 ? "已阅读" : "未读";
icode大师赛中第18题:
for i in range(8):
obj = Dev if i < 4 else Spaceship
obj . step(8-i)
obj . turnRight()
7,26总结
if 语句、if-else 语句
- 如果给定的表达式为真,那么执行指定语句
- 否则(else)执行另外的语句
switch-case 分支语句
- 判断某个表达式的值在几个常量的值
- 每个分支要加break 退出,default 其余情况
条件语句嵌套
- 可以多个else 多个分支,或者分支中还有分支
- 注意复杂的分支语句,以及大括号的用法
缩进、逗号表达式、注释、问号表达式
- 让编程更容易的一些窍门
关系表达式
- 真(1)假(0)
- 大于小于等于不等于,注意优先级
逻辑表达式
- 与(&&):同时为真则为真
- 或(||):至少有一个为真则为真
- 异或(^):刚好有一个为真则为真
- 非(!):颠倒黑白
浮点数精度误差、短路判断
数组
定义:
int a[5]; // 定义变量a,长度为5
// 定义了变量名为a,长度为5
a[0] = 1;
a[1] = 2;
……
a[4] = 5;
//下标越界
a[5] = 0;
//获取数组内容
cout << a[1] << endl;
cout << a[2] << endl;
cout << a;// 输出数组a的指针(内存地址)
cout << *a;
scanf("%d",&b)
一维数组
数组元素查找
例子
给出 n 个(不超过 100 个)正整数,请输出 x 第一次出现的位置。
数组元素查找
例子 给出 n 个(不超过 100 个)正整数,请输出 x 第一次出现的位置。
#include <iostream>
using namespace std;
int main() {
int n ;
cin >> n;
int a[101] ;
// int a[100] = {12, 23, 44, 8, 36, 3, 1};
for(int i = 1;i <= n;i++){
cin >> a[i];
}
int x;
cin >> x;
for (int i = 1; i <= n; i++) {
if (a[i] == x) {
cout << i ;
break;
}
}
}
小鱼比可爱 (p1428)
题意理解与转换:
有n个同学,不超过100个站成一排,大家都向前,每个同学身高为整数。 请计算,每位同学前面有几个同学比自己矮.
#include <iostream>
using namespace std;
int main(){
int a[101],n;
cin >> n;
// 存储小鱼的可爱值
for(int i = 0; i < n; i++){
cin >> a[i];
}
for(int i = 0; i < n ; i++){
int cnt = 0;
for(int j = i -1; j > 0; j--){
if(a[j] < a [i]){
cnt ++;
}
}
cout << cnt << " ";
}
// for(int i = 0; i < n ; i++){
// // 开始计数
// int cnt = 0;
// for(int j = 0 ; j < i -1; j ++){
// if(a[j] < a[i]){
// cnt ++;
// }
// }
// cout << cnt << " ";
// }
}
数组的定义与操作
#include <iostream>
using namespace std;
int main() {
int a[5];
// a[0] = 1;
// a[1] = 2;
// a[2] = 3;
// a[3] = 4;
// a[4] = 5;
// 在c语言中,& 符表示 :取地址; * 符表示:取值
cout << "数组a的值??: " << *a << endl;
cout << "数组a的地址: " << a << endl;
// cout a 表示输出数组a所在内存地址,其值为数组第一项的值
// cout *a 表示输出当前地址(数组a的地址)所存储的值。
cout << "数组a0的地址:" << &a[0] << endl;
cout << "数组a1的地址:" << &a[1] << endl;
cout << "数组a2的地址:" << &a[2] << endl;
// 声明时初始化
int b = 0;
int c[5] = {1, 2, 3, 4, 5};
cout << "数组c的内容:" << c[0] << c[1] << c[2] << c[3] << c[4] << endl;
for(int i =0;i < 5 ; i++){
cout << c[i];
}
cout << endl << "---------" << endl;
// 只初始一部分内容
int d[9] = {1,2,3,4,5};
for(int i = 0 ; i < 9 ; i++){
cout << d[i] ;
}
cout << endl << "---------" << endl;
char s[7] = {'a','b','c','d','e','f'};
cout << s << endl;
}
小鱼的数字游戏
自己维护计数器N,统计cin录入个数。
#include <iostream>
using namespace std;
int main(){
int a[110] ;
int tmp,n =0;
do{
cin >> tmp;
a[n++] = tmp;
}while(tmp != 0);
for(int i = n-1; i >= 1;i--){
cout << a[i] << " ";
}
}
方法二:
#include <iostream>
using namespace std;
int main(){
int a[110] ;
int tmp,n =0;
do{
cin >> tmp;
a[n++] = tmp;
}while(tmp != 0);
while(n--){
cout << a[n] << " ";
}
}
冰雹猜想
#include <iostream>
using namespace std;
int main() {
int n, a[200];
int i = 1;
cin >> n;
a[0] = n;
while (n != 1) {
if (n % 2 == 0) {
n = n / 2;
} else {
n = 3 * n + 1;
}
a[i++] = n;
// cout << n << " ";
}
while (i--) {
cout << a[i] << " ";
}
}
数组长度:
可以使用函数sizeof()
来得到数组对应的长度。
使用memset()
来进行数组统一初始化,这比用for循环要更简洁。
#include <cstring>
int a[10000] = {0};// 推荐,初始化时初始化
memset(a,0,sizeof(a));
for(int i = 0; i < sizeof(a); i++){
a[i] = 0;
}
数组如果不初始化就可能存有其他数值,因此我们在使用前必须 初始化,可以使用 for 循环依次赋初值,也可以在定义时直接初 始化。