怎样使用NOI Linux编程

2021年10月2日 | 分类: 【环境】

【使用】

先进入虚拟机(即:NOILINUX系统)才能使用以下条件

先点开终端按Ctrl+Alt+t 就出现终端窗口

先输入ls

找到文本目录,比如存放到Desktop(桌面)……

再输入cd Decktop 就能直接到桌面里找文件

在输入 vim a.cpp 就能进入a.cpp内

按Esc键及Shift+冒号 及wq 就能回到终端

再输入g++ -Wall a.cpp -o a (注:W为大写)就能生成a.out文件

最后输入 /.a 即可就能输入数据测评。

参考:https://www.cnblogs.com/ww3113306/p/9795485.html

linux环境下的基础操作
命令行操作
1,使用Ctrl + Alt + T召唤出终端。
2,基础指令:
1,cd
使用方法:cd + 文件目录
效果:使终端所在的目录切换到指定文件目录,但是每次cd只能不断深入某个文件夹,如果要退出这个文件夹则直接使用cd,后面不加任何东西
如果文件名太长懒得打的话,可以打一半然后按Tab键,如果这时你给出的部分文件名已经可以使电脑确定出唯一的一个文件的话,那么将会自动补全这个文件名,否则会给你列出可能的文件名。
2,l
列出当前目录下的文件和文件夹,一般和cd配合使用。
3,./ 程序名
用来运行一个程序
4,> 和 <
有时候你并没有在程序中打文件输入和输出,然后你需要使用文件输入输出,但是又懒得打文件输入输入+重新编译。
这个时候使用这个指令就很方便。
./work < in.in > out.out表示运行work文件,从in.in中读入,输出到out.out中。

编辑器
1,gedit的使用
gedit是我常用的编辑器,基础功能都有,界面比较简洁,因为noi linux下默认打开.cpp文件的软件是emacs,所以如果要使用gedit的话,建议先新建一个.cpp文件,然后右键选择打开.cpp的软件,选文本编辑器(gedit),然后就会默认使用gedit打开.cpp文件了。
一般来说,打开gedit后第一反应应该是进行一些基础的设置。
这里推荐的设置是:

选择编辑,打开首选项:
1,勾选显示行号.
2,勾选右边对齐线显示的位置.(这个一般用于提示自己每行的代码不要过长,会使得代码美观一点)
3,勾选突出显示当前行.(方便定位当前光标所在的位置)
4,勾选突出显示匹配的括号.
5,勾选启用自动缩进.
6,勾选在保存前创建备份文件(每次都选了,但是从来没用到过,以防万一吧)。
7,配色方案我喜欢用暗色的,感觉光线柔和一点,这个根据个人喜好选择即可.

设置完后关闭首选项。点击F9,然后切换到文件浏览器模式(我用的ubuntu16.04,叫法可能不同,但差别不会很大)。这个模式有什么好处呢?
1,你可以直接右键在当前目录下进行新建文件等一系列关于文件的操作(但是好像不能复制粘贴文件),而不需要再打开文件夹进行一系列操作。
2,你可以直接右键在当前目录下调出命令行,从而避免繁琐的cd操作,尤其是在有中文目录的情况下这个会很实用。
3,可以快速切换到当前目录,还可以快速打开当前目录下的文件夹。

1,如果要快速上下翻动可以关闭数字锁定,然后利用小键盘快速翻动,1,7分别对应翻到底部和翻到顶部。2, 8则是小幅度的翻动,3和9是较大幅度的翻动。
2,gedit自带替换的功能(Ctrl + H),这个功能一般用于你之前使用了某个变量名,而你现在又想使用这个变量名,这时你可以用这个功能快速替换之前的同名变量,避免名字冲突。
3,gedit的搜索功能(Ctrl + F),搜索了之后会高亮匹配项。为了防止误选建议勾选区分大小写和匹配整个单词。
4,快速跳转到某一行(Ctrl + I).
以上快捷键根据版本不同,可能略有区别,如果不能使用就在上面的搜索选项中查看对应快捷键即可。
5,你也可以在终端中使用gedit + 文件名来快速创建一个文件,并在gedit中打开。

程序编译
最基础的编译命令:g++ 1.cpp
编译出来的文件叫做a.out
使用./a.out可以运行这个程序。
当然还有一些额外的常用指令,使用的时候直接加在后面即可。
1,-o
可以让你命名编译出来的文件,比如g++ 1.cpp -o work可以使得编译出来的文件叫做work
2,-Wall -Wextra
这两个指令的作用差不多,可以给你一些额外的警告和提示,用于避免一些NC错误。
比如当你在if的判断条件中把x == y写成了x = y时它就会警告你。但这两个指令带来的警告不会使编译失败。
3,-O2
顾名思义,开启O2选项,O2是一种更高级别的优化,平时默认是O1,如果在没有开O2的情况下,大多数STL会跑得很慢(sort之类的除外)。
4,-g
开启gdb
以下是一个示例:(编译1.cpp为work,并运行此程序 同时开启O2优化)

g++ 1.cpp -g -Wall -Wextra -o work -O2
./work

5,文件调用。
这个应该都会吧,一般都是使用freopen来实现文件调用。

int main()
{
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
    pre();
    build();
    work();
    fclose(stdin);
    fclose(stdout);
    return 0;
}

程序调试
gdb的使用
gdb是一个功能很强大的调试软件,一般来讲是用于动态调试,跟devc++的单步跟踪差不多,但功能更多,更稳定。因为使用gdb时往往需要一步步的查看程序运行的情况,所以可能调试起来会比较慢,但可以通过一些小技巧来加快调试速度,这个可以自己体会&总结。
首先是一些基础操作;
还有一些不常见操作;

对拍
有时候你打出了一道题的正解,但你可能并不放心你的正解是否是正确的,这时一个很常见的验证方法是对拍。
首先你需要以下程序:
1,正解(或者是一些针对部分数据的高级暴力也是可以的)
2,暴力
3,造数据的程序
4,对拍程序
正解和暴力怎么写就看你自己了,这里简单讲一下如何造数据和写对拍

造数据程序:


#include<bits/stdc++.h>
using namespace std;
#define R register int
int main()
{
    freopen("in.in", "w", stdout);
    srand(time(0));
    int n = rand() % 1000 + 1, m = rand() % 1000 + 1;
    n = 1000, m = 1000;
    printf("%d %d\n", n, m);
    for(R i = 1; i <= n; i ++) printf("%d ", rand() % 50000 + 1);
    printf("\n");
    for(R i = 1; i <= m; i ++)
    printf("%d\n", rand() % n + 1);
    fclose(stdout);
    return 0;
}

这是一份造数据的程序,首先一般会写一个文件输出,表示造出的数据放入要某个文件里。
srand();是给rand()指令重新指定一个种子,否则你将会每次都造出一样的数据,因为rand实际上是通过一个式子不断的计算得到随机值(不是真随机),所以如果种子一样,那么随机出来的东西也将是一样的。
然后中间的就根据题目的输入格式自己写了。
一般在开始会在题目给点范围内随机一个数据大小,但是有时候为了特殊目的(想测极限数据,要用小的错误数据调试等),可能会在下面强制指定一个数据大小。如上面程序中的n = 1000, m = 1000;

对拍程序:

#include<bits/stdc++.h>
using namespace std;
#define R register int

int main()
{
    for(R i = 1; i <= 1000; i ++)
    {
        system("./make");
        system("./work > out.out");
        system("./work1 > out1.out");
        if(system("diff -bB out.out out1.out"))
        {
            printf("error in %d\n", i);
            return 0;
        }
        else
        {
            printf("passed... %d\n", i);
            system("sleep 1");
        }
    }
    return 0;
}

对拍一般都是一样的,所以不会的话背下代码即可,当然理解一下就更好记了。
system();中的指令会起到跟你在终端中输入这串指令一样的效果。
diff -bB out.out out1.out是在忽略行末空格和换行的情况下对比两个文件,如果不同的话会给你返回一个非0的值,因此如果不同的话就输出错误并终止程序,这样的话你就可以保留使你错误的那个数据点。
否则的话输出passed… 当前数据点。提示你过了这个点。
因为一般都是写的srand(time(0));所以如果时间是一样的话,种子也会是一样的,随机出来的东西也会是一样的,所以这个时候多次对同一组数据进行测试就没有意义了。所以一般会使用sleep命令来延迟一秒的时间以满足每次测试的时候种子都不同。

快速编译程序:

这个可能比较冷门,有时候会比较方便。

#include<bits/stdc++.h>
using namespace std;
string name, tmp, s;
int main()
{
    cin >> tmp >> name;
    s = "g++ " + tmp + ".cpp -g -Wall -Wextra -o " + name;
    system(s.c_str());
    return 0;
}

运行这个程序,然后输入你要编译的文件名+你要编译为的程序名,就可以快速将这个文件编译为指定程序名。从而避免每次都要打一长串编译命令