NOI Linux 使用技巧

前情提要:由于我是机房中为数不多的几个用过 NOI Linux 的人,zhub 让我写了本文以向大家分享 NOI Linux 使用技巧。

疑似是有点太详细了,我写的大部分东西 zhub 都讲了

首先声明一下,我不是 Linux 专家,对一些东西了解不多,只是分享一些 实用主义 的技巧,请大佬轻喷

强烈建议场上把在 Windows 中写的程序在 NOI Linux 编译一遍,防止挂分

以下代码在 Linux 中不能过编

  • #include<bits\stdc++.h> : 应写成 #include<bits/stdc++.h>
  • #include<windows.h> : Windows 下特有的头文件,请使用 #include<cstdlib> 调用 system()
  • 这玩意在 Dev-C++ 中甚至过编,我去年 CSP 被坑过
    1
    2
    3
    4
    inline fun(int arg, ...)
    {
    // do something...
    }
  • system("pause") 不会 4202 年还有人在用这个吧
  • 还有一堆特定于 Windows 和 GCC 4.9.x 的非标准库

NOI Linux 的使用技巧

Linux 下的注意事项

  • 路径使用 / (斜杠) 而不是 \ (反斜杠)
  • . (点) 开头的文件会隐藏
  • 大小写敏感 e.g. abc.tXtabc.txt 是不同的文件
  • 终端中不能使用 Ctrl + CCtrl + V 来复制粘贴,请使用 Ctrl + Shift + CCtrl + Shift + V (注意 Ctrl + C 是退出程序)
  • 可执行文件没有 .exe 后缀名
  • 运行程序需 ./【程序名】
  • Python 命令是 python3

如何编写代码

如果使用 Code::Blocks,小齿轮按钮是编译,绿色小箭头是运行

  • IDE: Code::Blocks,强烈推荐,自带强大代码补全和调试(能调 STL)功能,比 Dev-C++ 好用 114514 倍
    • 注意事项:
      • 建议建 Project (File -> New -> Project -> Console application) 以使用完整功能
      • 默认终端是 XTerm,比较反人类(反正我至今没搞懂怎么复制粘贴),在 Settings -> Environment 中将 Terminal to launch… 一项改为 gnome-terminal…
      • 建议在 Debugger -> GDB/CDB Debugger: Default 中取消勾选 Disable startup scripts(默认勾选),以调试 STL
  • Editor:
    • Geany: 编程体验类似 Dev-C++,有语法高亮和简单代码补全
    • gedit(中文名:文本编辑器):有语法高亮,无代码补全
    • VSCode: 没有插件,使用体验一般,功能同上
    • Sublime Text 3: 有简单代码补全(感觉不怎么好用)
    • Vim: 强大的命令行文本编辑器(不推荐新手使用)
    • Emacs: 同上,有 GUI,我不会用
    • nano: (终端命令 nano) 易于上手的命令行文本编辑器
    • JOE(Joe’s Own Editor): 命令行文本编辑器,不知道怎么用

如何编译和运行代码

  • 在代码目录下右键「在终端打开」
  • g++ ./【程序文件名】.cpp -o 【程序文件名】 -std=c++14 -O2 -g 编译代码
  • ./【程序文件名】 运行
  • time -p ./【程序文件名】 可以查看程序运行时间(注意本机运行速度往往慢于 €€£ 少爷机,特别是在有虚拟机性能损耗的情况)

其他可能用上的命令

  • Linux 的特定目录:
    • . 当前目录
    • .. 当前目录的父目录
    • ~ 主目录(a.k.a. 主文件夹),你创建的所有文件都应该放在这个目录及其子目录下
    • / 根目录,除非你知道你在干什么,否则不要动这个目录下的文件
  • touch 【文件名】 新建文件
  • mkdir 【目录名】 新建目录
  • cd 【目录】 切换当前目录
  • ls 【目录名】 列出目录下文件,如果不给定目录名,则默认是当前目录,ls -A 列出所有文件,包含隐藏文件(注意:主目录下会有很多无关的隐藏文件)
  • rm 【文件名】 删除文件,rm -r 【目录名】 删除目录
  • cp 【原路径/文件】 【目录路径/文件】 复制文件
  • mv 【原路径/文件名】 【新路径/文件名】 移动/改名文件
  • diff 【文件A】 【文件B】 比较文件 A 和文件 B 的差异
  • ps -e 列出所有进程(和 PID)
  • kill 【PID】 结束进程(PID 使用上面的命令查看)
  • killall 【进程名】 结束进程
  • 管道:【程序A】 | 【程序B】 将程序 A 的输出作为程序 B 的输入运行 A 和 B
  • 文件输入输出重定向:
    • 【程序】 > 【输出文件名】 将输出写至文件
    • 【程序】 < 【输入文件】 将文件作为输入运行程序
    • 可以一块使用,如:./prob < prob.in > prob.out

其他可能用上的东西

对拍脚本

对拍代码模板(prob 是代码文件名和输入输出文件名,gen.cpp 是数据生成器,bf.cpp 是暴力程序)

使用方法:bash ./chk.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# chk.sh
read n
g++ ./prob.cpp -o prob -O2
g++ ./bf.cpp -o bf -O2
g++ ./gen.cpp -o gen -O2
while (( $n>0 ))
do
./gen > prob.in
# 文件输入输出 ./gen
if (( $?>0 )) then
echo "Data Generate Fail"
sleep 1s
continue
fi
./prob < prob.in > prob.out
# 以上是无文件输入输出的方法
# 如果有文件输入输出则改成 ./prob
if (( $?>0 )) then
echo "Runtime Error"
break
fi
./bf < prob.in > bf.out
# 文件输入输出 ./bf
if (( $?>0 )) then
echo "BF Runtime Error"
continue
fi
if diff prob.out bf.out; then
echo "OK"
rm prob.in prob.out bf.out
else
echo "WA"
break
fi
done
rm prob bf gen

简单版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# chk.sh
g++ prob.cpp -o prob -O2
g++ bf.cpp -o bf -O2
g++ gen.cpp -o gen -O2
n=1
while ((n <= 1000))
do
./gen > prob.in
./prob < prob.in > prob.out
./bf < prob.in > bf.out
# 全部无文件输入输出,有文件输入输出则应删除所有输入输出重定向
if diff prob.out bf.out;
then
echo $n
let "n=n+1"
continue
else
echo "WA"
break
fi
done

GDB 的基本使用

这块我也不熟,我知道的就这些了

P.S. 使用 Code::Blocks 可以愉快地调试

GDB 是大部分 Linux 发行版中自带的 Debugger

  • gdb 【程序名】 进入 Debug 界面,注意编译时必须带上 -g 参数
  • l 【行数】 列出给定行附近代码,如果不给定行数则
  • b 【行数或函数名】 设置断点
  • r 运行至断点,注意不要忘记输入
  • n 下一行
  • p 【变量名】 打印变量
  • disp 【变量名】 设置变量在断点处始终显示