0. 前言
最近很多uu们过来问鼠鼠一些 c语言/python 的问题,遂决定开一个答疑帖,方便大家学习交流。但是呢既然开了帖,也就不只讲有疑问的地方,顺便把常见的一些问题都给大家过一遍。又考虑到很多uu跟鼠鼠一样是电脑小白,也顺带分享一些电子产品、生活小知识。
鼠鼠水平有限,内容仅供参考,有错误遗漏之处欢迎斧正。
注意:下文中大部分操作均为免费,有额外开销之处会予以标明。
鼠鼠这博客皮肤渲染代码高亮不太对劲,大家复制到自己的编译器看吧。
1. c/c++ 入门
鼠鼠学习的课程是c语言,指定的编译器环境是 Embarcadero Dev-Cpp,下文以此为例展示。大家可以根据自己老师的要求调整。
(注:OI竞赛中习惯了 devc++ 的同学可以对标 dev,我个人觉得操作没有区别)
(注:学习 python 的uu们可以移步其他博客查看攻略,我用的是 pycharm)
1.1 下载
em devc++下载
em devc++下载指南
以上,可以从 sourceforge 或 github 上下载 Embarcadero Dev-Cpp。如果使用 devcpp (图标为蓝色的那个),可以使用腾讯下载。
1.2 简单配置
刚下载好是这样的。
-
按住Ctrl键后鼠标滚轮可以控制右侧编辑区字体大小
-
鼠标指针移到左侧项目管理区和右侧编辑区的中缝处,按住左键往左拖,可以隐藏左侧项目管理区。
-
上方菜单选择 “工具” \(\rightarrow\) “编辑器选项”
- 基本、显示、语法三项可以改变主题
- (字体推荐默认的 Consolas)
- (鼠鼠用的是 obsidian 主题: 基本-高亮显示当前行选择黑色,语法-预设选择 obsidian)
- 代码:在”缺省源”中输入的代码会自动在所有新建文件中生成,就不用每份代码都打一遍头文件了。
- 代码补全: Code Completion 会自动帮你匹配库函数、结构体对象等等,但是会写代码时突然卡手,建议关掉;完成符号会自动匹配括号和引号,看个人习惯使用,鼠鼠的只匹配大括号。
- 自动保存:一定要打开!!!最好间隔调个1分钟。
-
上方菜单选择 “工具” \(\rightarrow\) “编译选项”
-
“设定编译器配置”最好是什么什么 64-bit Release
-
开启”编译时加入以下命令”并输入以下代码:
-
-Wall -Wextra
-
具体为什么后面说。
-
搞定了长这样。
1.3 新手常见错误
前人总结
下表速查:(CE 就是不能编译,warning 能编译但会警告,WA 就是答案错误,RE 就是运行时出错)
错误 | 结果 | 解决方案 |
---|---|---|
int mian() | CE | 缺省源写对 |
retuen 0; | CE | 缺省源写对 |
return 0;忘了写 | OI中WA | 缺省源写上 |
分号,括号漏了 | CE | 看高亮确定配对关系,补上漏的 |
使用中文分号/逗号 | CE(有时本地会通过,交题CE) | 写代码时一定注意输入法,英文,符号为半角!!! |
赋值运算符和 == 不分 |
warning、WA | 一定小心!!记牢c++的=是赋值 |
运算符优先级错误 | warning、WA | 不确定就多打括号,人为规定优先级 |
数组没开够 | WA/RE | 多开5个肯定就没事了 |
int溢出 | WA | 开long long |
未初始化局部变量 | warning、WA | 养成初始化习惯 |
我们可以看到,上述错误中 CE、warning 的可以当场改过来,减少了考试暴毙的可能性。那么 warning 是怎么来的呢?诶,正是编译选项中这两个代码的功劳:
-Wall -Wextra
所以一定要编译选项加上这两句,写代码时把 warning 当作 error 来对待!
1.4 调试与对拍
1.4.1 中间输出调试
其实名字我忘了,乱编了一个
老师会教大家断点调试,但是这样做非常难受,看的人眼花。有没有好一点的调试方法呢?
(转载)中间输出调试
鼠鼠以 B3925 [GESP202312 三级] 小猫分鱼 为例讲解。
看到这个题,鼠鼠对第一组样例进行分析:(两只猫,每轮丢掉一条鱼)
-
在只有一只猫时最少这只猫分1条,另一只分相等数量1条,外加丢掉1条,共3条。
-
在第二只猫时最少这只猫分3条(因为要留下3条进行1),另一只分相等数量3条,外加丢掉1条,共7条。
答案为7,符合样例1。
综上,鼠鼠分析出此题应该倒推:
每只猫的逻辑都是分 \(n\) 堆,取一堆,扔 \(x\) 个。记第 \(i\) 只猫扔完后还有 \(s_i\) 只鱼,则有:
\[s_i = \dfrac{n-1}{n}(s_{i-1} – x) \]
每只猫都有的吃,\(s_n = 1\) 最小,此时 \(s_0\) 就是答案(海滩上最少的鱼数)了。
反推公式可得
\[s_{i-1} = \dfrac{n}{n-1}s_i + x \]
鼠鼠开心地写出了如下代码:
#include<stdio.h>
#define ll long long
#define db double
#define mod 998244353
#define N 1005
int n,x,s[N];
int main(){
scanf("%d%d",&n,&x);
s[n]=1;
int i;
for(i=n;i>=1;i--)s[i-1]=s[i]*n/(n-1)+x;
printf("%d\n",s[0]);
return 0;
}
结果一看:
样例1通过了,可是样例2输出了7,明显不对。为什么呢?
这时就要用到中间输出调试来查错了。
鼠鼠先在输入 \(n\) 和 \(x\) 后立即输出它们,以检查输入的正确性:
int main(){
scanf("%d%d",&n,&x);
printf("orz: %d %d\n",n,x);
s[n]=1;
int i;
for(i=n;i>=1;i--)s[i-1]=s[i]*n/(n-1)+x;
printf("%d\n",s[0]);
return 0;
}
运行代码,可以发现输出多了一行:
orz: 3 1
证明输入没有问题。
Tip: 在调试输出时加入特殊信息,如 orz 等,可以帮助快速确定哪行输出是调试输出。
接下来就要检查代码逻辑了。我们在每次算出 \(s_i\) 之后输出 \(s_i\) 看看对不对。代码如下:
int main(){
scanf("%d%d",&n,&x);
printf("orz: %d %d\n",n,x);
s[n]=1;
int i;
for(i=n;i>=1;i--){
s[i-1]=s[i]*n/(n-1)+x;
printf("sto %d:%d\n",i-1,s[i-1]);
}
printf("%d\n",s[0]);
return 0;
}
调试的输出如下:
sto 2:2
sto 1:4
sto 0:7
这意味着\(s_2=2,s_1=4,s_0=7\)。这对不对呢?我们手动验算一下:
\[s_3=1,s_2=\dfrac32s_3 + 1 =\dfrac52 \]
这时就发现错误了:我们贪心地让 \(s_3=1\),却忽略了这样会使后面的 \(s_i\) 出现小数,这是不符合常理的。
但是我们发现 \(s_3\) 越小 \(s_0\) 显然越小,于是枚举 \(s_n\) 使得每次算出的 \(s_i\) 都是整数即可。更改代码如下:
int main(){
scanf("%d%d",&n,&x);
if(n==1)return printf("1\n"),0;
// printf("orz: %d %d\n",n,x);
int i;
for(s[n]=1;;s[n]++){
for(i=n;i>=1;i--){
if(s[i]%(n-1))break;
s[i-1]=s[i]*n/(n-1)+x;
// printf("sto %d:%d\n",i-1,s[i-1]);
}
if(i==0)return printf("%d\n",s[0]),0;
}
}
其中因为要对 \(n-1\) 取模,特判了 \(n=1\) 的情况。
记得对调试输出注释后提交,准备开香槟咯!!!
愉快地提交代码,我们得到了90分的好成绩。
1.4.2 对拍
为啥错掉了?明明样例都过了啊?
这时我们就要用到一个叫对拍的技巧查错了:
(转载)C++ 对拍详解
1.5 常见网站分享
这里与2和3中的有重叠,先于此汇总,2和3中相同的会放个 reference。
汇总
没有回复内容