#10160. 2026/9/6/C++基础笔记
2026/9/6/C++基础笔记
C++ 基础做题与易错点复习笔记
复习提纲
- 看懂一道编程题:输入、处理、输出。
- 分清变量:数量、当前数据、循环编号、答案。
- 写好循环:读入位置、循环次数、初始值、输出位置。
- 写好判断:等号、范围、分支和括号。
- 检查答案:格式、样例、边界和错误原因。
一、怎样才算做对一道题?
一道题的基本过程是:读入数据 → 按要求处理 → 输出答案。
程序能运行,不代表答案正确;样例通过,也不代表整道题正确。
一般的编程题评测会使用多组测试数据,检查程序能否在规定限制内给出符合要求的答案。有些比赛有部分分,但通常根据测试点或子任务是否通过给分,不是阅读代码给“过程分”。
写代码前先回答:
- 题目给了什么数据?
- 要根据这些数据做什么?
- 最后要输出什么,有几个结果?
**提交前核对题目和代码是否对应。**判断奇偶的程序,不能提交到比较十位和个位的题目;求最大值的程序,也不能提交到时间计算题目。
二、输入格式决定读什么,不能自己猜
情况一:输入 n,输出 1 到 n
输入只有一个数。后面的数字由循环产生,不需要再输入。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cout<<i<<endl;//依次输出,每行一个数
}
return 0;
}
输入:
3
输出:
1
2
3
情况二:输入 n,再输入 n 个数
每次循环都要读取一个新数据。
int n,a;
cin>>n;//先读取数量
for(int i=1;i<=n;i++){
cin>>a;//每次读一个,共读n个
//在这里处理刚读到的a
}
下面这样会多读取一个数:
cin>>n>>a;//这里已经读取了第一个数据
for(int i=1;i<=n;i++){
cin>>a;//这里又尝试读取n个数据
}
需要处理多少个数,就按输入格式读取多少个:不多读、不漏读。
对于这里的整数输入,cin>>a 会跳过数字前的空格和换行。不要把“输入有两行”理解成“只能写两次 cin”,关键是读入的数据数量和顺序。
三、先分清变量的含义
| 变量 | 在循环输入题中的含义 |
|---|---|
| n | 一共有多少个数 |
| i | 当前处理第几个数 |
| a | 当前读到的数 |
| s 或 cnt | 已找到多少个符合条件的数 |
| sum | 已经算出的总和 |
例如输入:
3
8 2 90
| 循环次数 | i | a |
|---|---|---|
| 第一次 | 1 | 8 |
| 第二次 | 2 | |
| 第三次 | 3 | 90 |
判断“当前的数是否大于等于 5”,要写 if(a>=5),不是 if(i>=5)。
不要在循环中写 cin>>n 读取当前数据,这样会把“总数量”改掉,循环次数也可能随之改变。
变量使用前,必须有值
int x;
cout<<x;//错误:x还没有输入或赋值
在函数里写 int x;,不代表它自动等于零。
新增变量前先想:它表示什么?它的值从哪里来?
四、循环中的三个关键位置
1. 每个数据都要输入:cin 放在循环里面
统计直角数量:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a,s=0;//最开始找到的直角数量为0
cin>>n;
for(int i=1;i<=n;i++){
cin>>a;//每次读一个新的角度
if(a==90){
s++;//找到一个直角,数量增加1
}
}
cout<<s;//全部检查完,只输出一次总数
return 0;
}
如果只在循环前读一次角度,循环中没有 cin>>a,就会反复检查同一个角。
2. 最终结果只输出一次:cout 放在循环后面
求 1 到 n 的和:
int n,sum=0;
cin>>n;
for(int i=1;i<=n;i++){
sum+=i;//依次加1、2、3……n
}
cout<<sum;//答案保存在sum中,不是n中
当 n 为 3 时:
| 执行后 | sum |
|---|---|
| 初始 | 0 |
| 加上1 | 1 |
| 加上2 | 3 |
| 加上3 | 6 |
如果每次写 sum+=n,就变成反复加同一个 n;如果最后写 cout<<n,则输出的是输入数据,不是计算结果。
如果把输出放进循环,会打印中间结果。是否需要这样做,要看题目的输出要求。
3. return 0 放在所有任务完成之后
return 0; 会结束程序。放在循环里面,可能刚执行一次就结束,后面的数据还没处理。
另外,写在 for(int i=...) 中的 i,只在这个循环范围内使用,不要在循环结束后用它输出答案。
五、初始值、起点、终点、步长
求和、计数从 0 开始,连乘从 1 开始
int sum=0;//还没加任何数
int s=0;//还没找到符合条件的数
int ans=1;//连乘不能从0开始
求 1×2×…×n,在结果不超出 int 范围的题目中:
int ans=1;
for(int i=1;i<=n;i++){
ans*=i;
}
cout<<ans;
如果 ans 从 0 开始,每一步都是零乘一个数,结果永远是零。
每次增加多少,要写清楚
从 a 开始,每次增加 3,不超过 b:
for(int i=a;i<=b;i+=3){
cout<<i<<" ";
}
例如 a=2、b=9,i 依次是 2、5、8;再增加 3 得到 11,已经超过 9,循环结束。
不是随便找一个变量写 cout<<c+3;,而是让循环中的数按要求变化。
六、条件判断:把中文条件翻译完整
= 是赋值,== 是判断相等
a=5;//把a的值改成5
if(a==5){//判断a是不是5
cout<<"YES";
}
比较十位和个位是否相等时,要写 if(a==b),不能写 if(a=b)。
并且用 &&,或者用 ||
| 题目中的条件 | 代码 |
|---|---|
| 不少于10、至少10 | a>=10 |
| 超过10 | a>10 |
| 不超过10 | a<=10 |
| 90到100之间,含两端 | a>=90&&a<=100 |
| 小于0或者大于100 | a<0||a>100 |
| 能被4整除 | a%4==0 |
s>=90&&s<=100 的左右两边都是完整的判断,不能省成 s>=90&&<=100,也不要写成数学里的连写形式。
“能被4整除”不能只写 a%4。我们要判断的是“余数等于0”。
只选择一个结果:使用 if / else if / else
分数在 0 到 100 之间,90分及以上为A,75分及以上为B,60分及以上为C,其余为D:
if(s>=90){
cout<<"A";
}else if(s>=75){
cout<<"B";
}else if(s>=60){
cout<<"C";
}else{
cout<<"D";
}
走到第二个判断时,已经知道 s 小于90,因此只需要继续判断是否达到75。
每个数据都要比较:不能跳过后面的 if
找四个数的最大值:
int a,b,c,d;
cin>>a>>b>>c>>d;
int ma=a;//先把第一个数作为当前最大值
if(b>ma) ma=b;
if(c>ma) ma=c;
if(d>ma) ma=d;
cout<<ma;
这里三个判断都要执行。不能全连成 else if,否则前面成立后,后面的数就不会比较。
是否使用 else,要看后面的事情还需不需要继续做,不是固定套写法。
七、括号与缩进也能帮助减少错误
商品价格至少10元就减2元,否则原价输出:
if(a>=10){
cout<<a-2<<" ";
}else{
cout<<a<<" ";
}
else 要放在 if 对应的右大括号之后,不要放进 if 的大括号里面。
完整的循环处理:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a;
if(a>=10){
cout<<a-2<<" ";
}else{
cout<<a<<" ";
}
}
return 0;
}
每进入一层大括号,就缩进一级。缺少右大括号、使用了未定义的变量,都可能导致编译错误。遇到编译错误,先检查第一条报错附近,不要盲目修改全部代码。
八、计算与输出的常见细节
1. 先统一单位,再计算
h小时m分钟,一共是:
int all=h*60+m;//全部换成分钟
如果再过t分钟,并且题目保证当天结束:
int all=h*60+m+t;
cout<<all/60<<" "<<all%60;//小时和分钟
每一步都要知道变量的单位。不要用还没有赋值的 x 参与计算。
2. / 求商,% 求余数
n支笔,每盒装k支,装满的盒数是 n/k,剩余支数是 n%k。
cout<<n/k<<" "<<n%k;
3. 整数除法会丢掉小数部分
double avg=(a+b+c)/3.0;//使用3.0,让除法保留小数
printf("%.1f",avg);//按题意保留1位小数
即使左边是 double,右边写 (a+b+c)/3,仍会先进行整数除法,之后不能自动找回小数。
4. 算对还要输出对
| 输出要求 | 写法 |
|---|---|
| 两个数之间用空格分隔 | cout<<a<<" "<<b; |
| 两个数分别占一行 | cout<<a<<endl<<b<<endl; |
| 输出指定单词 | cout<<"YES"; |
如果 a=6、b=5,cout<<a<<b; 会输出 65,而不是两个分开的数。
题目要求 ONES,就不能写成 OENS;要求整数,就按整数格式输出,不要随意加上小数。
不同评测对空白和数值误差的处理可能不同。最稳妥的方法是:**按照题目规定输出,不依赖评测放宽要求。**不要额外打印“请输入”“答案是”等文字。
九、样例检查之后,还要自己测试
样例有两个作用:帮助理解题意,帮助初步检查代码。
样例不一致时先查原因;样例一致时再补测其他情况。
| 题目 | 可以补充的测试 |
|---|---|
| 输出1到n | n=1,检查有没有漏掉1 |
| 商品优惠 | 9、10、11,检查10是否优惠 |
| 统计直角 | 没有直角、全部直角、只有最后一个是直角 |
| 求和 | n=3,应得到6,不是3或9 |
| 连乘 | n=1得到1,n=3得到6 |
| 最大值 | 最大值放在首位、末位,几个数全为负数 |
| 分数等级 | 59、60、74、75、89、90、100 |
输出错了,拿一组很小的数据,逐行看变量变化:
- cin 实际读到了哪个数?
- 进入循环时,i、当前数据、答案分别是多少?
- if 条件到底成立不成立?
- 执行后变量变成了多少?
- 最后 cout 输出的是哪个变量?
**不要用“随便换一个符号试试”代替检查原因。**修改后重新运行原来出错的数据,再检查样例。
十、提交前一分钟检查
- 我提交的代码,解决的是当前这道题吗?
- 输入数量和顺序有没有多读、漏读、读反?
- n、i、当前数据和答案有没有混淆?
- 变量用之前有值吗?求和、计数、连乘的初值正确吗?
- 循环起点、终点、步长,以及 cin、cout 的位置正确吗?
- 等号、并且、或者、分界线是否正确?
- 所有数据都处理完了吗?有没有提前 return?
- 输出变量、空格、换行、单词和小数位数符合要求吗?
读清题目,写清每个变量的作用,用小数据一步一步检查,比反复猜着修改更有效。