• スワコゥのパーフェクトコード教室 ~ Style of suwakow's for OI Codes


    “みんなー! スワコゥのコード教室はじまるよー!”

    “大家!(color{grey}{ ext{suwakow}})的码风教室开始了哟!”

    “あたいみたいな天才目指して、がんばっていってね!”

    “你们要以我这样的天才为目标,好好努力哟!”

    注:本文所述均为(color{grey}{ ext{suwakow}})算法竞赛时常用的代码风格,可能会随着时间推移略有改变。


    Part 1 预先准备

    • 头文件

    通常使用 #include <bits/stdc++.h>,注意尖括号前有一个空格。

    在部分环境下,如本地调试时,可能会使用 #include "testlib.h"。任何包含引号的头文件应置于尖括号的头文件后。

    在部分本地与提交编译环境不同的比赛场合,可能会不使用 #include <bits/stdc++.h>,而是使用传统的头文件列表形式。在不违反上一条规则的前提下,应按照头文件长度从短到长排序。

    • #define 的使用

    预先写在代码模板中的:

    #define R register
    #define ll long long
    #define mp make_pair
    #define pii pair<int, int>
    

    在某些需要 unsigned 类型或 long double 类型的场合,也会使用:

    #define ld long double
    #define uint unsigned int
    

    #define 语句均按照长度从短到长排序。

    通常 #define 写在头文件之后,不空行。但在某些数据结构中可能会为了方便而进行局部 #define,此时应在数据结构的末尾进行 #undef

    • 一般情况下使用 using namespace std; ,写在 #define 之后,不空行。
    • 对于代码中可能用到的常量,使用 const Type Name = Value; 的形式,写在 using namespace std; 之后,不空行。对于用在数组下标中的常量名,使用单个大写字母,如 const int N = 210000;

    Part 2 声明

    • 全局变量的声明均写在 Part 1 之后,空一行。除非变量个数过多导致某行过长不便浏览,一种类型的变量声明写在一行内。不同类型的变量之间一般不空行。
    • 对于“打表”的部分变量,可以采用如下的方式:
    int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
    int tab[5][5] = {
        {0, 1, 2, 3, 4},
        {5, 6, 7, 8, 9},
        {10, 11, 12, 13, 14},
        {15, 16, 17, 18, 19},
        {20, 21, 22, 23, 24}
    };
    string preTimes[21] = {
    	"", "", "di", "tri", "tetra", "penta", "hexa", "hepta", "octa", "nona", "deca", "undeca",
    	"dodeca", "trideca", "tetradeca", "pentadeca", "hexadeca", "heptadeca", "octadeca", "nonadeca"
    };
    
    • 变量的命名

    一般的变量使用不超过 (3) 个小写英语字母命名。

    对于有实际意义的变量,一般采用其实际意义对应的英语单词中首 (3) 个字母或其中 (3) 个辅音,具体的选取不硬性要求。对于 (3) 个字母表意不清或易混淆的,可以适当增加字母个数,不过不宜超过 (5) 个。

    对于无实际意义的变量,一般直接使用单个小写英语字母作为数组名。如,对于“读入的序列 (a) ”,一般直接使用 a[]作为变量名 。

    对于多个单词复合的变量名,一般使用驼峰命名法,如,数据结构中的加法标记和乘法标记共存时,一般记为 addTagmulTag;分别对 (a, b) 两个值记录最大值时,一般记为 maxAmaxB

    变量的声明一般与后面的内容之间空一行。

    • 结构体和 namespace

    结构体主要按其用途分为两类——对新类型的定义和对某种结构的封装。

    对于第一种,用一个例子来说明其格式:

    const int N = 110000;
    
    int n;
    struct point {
        int x, y;
        point(int x = 0, int y = 0) : x(x), y(y) {}
        inline bool operator < (const point &a) const {
            return x < a.x;
        }
        inline int cross(const node &a) {
    		return x * a.y - y * a.x;
        }
    } poi[N];
    

    即,声明结构体名的大括号内,所有内容向前缩进一次,变量名、函数名之间不空行。

    此类结构体一般较短,作用较为简单,不会作为某种封装好的,能独立完成某个任务的整体结构出现。注意如果重载此类结构体的运算符,需在结构体内重载。

    对于此类结构体的声明,可以视作声明一个变量,与其他变量的声明之间不空行,与其他函数的声明之间空行。

    另一种结构体与自定义 namespace 的格式较为相似,同样用例子说明:

    struct segmentTree {
    //
    static const int K = N << 2;
        
    int lt[K], rt[K];
    node data[K];
        
    void build(int k) {
        // ...
    }
    //
    } segA, segB;
    
    namespace brute_frac_n {
    //
    void dfs(int step) {
        // ...
    }
        
    int main() {
        dfs(0);
        return 0;
    }
    //
    }
    

    即,大括号内首尾各空一行,可以用注释符号标记。大括号内的内容顶格写,变量名、函数名之间空一行,与不封装的部分格式类似。

    • 函数、结构体和命名空间的命名

    一般也使用驼峰命名法,对于单词数较多(多于三个)或包含数字的名称,也可以使用下划线。

    函数名需尽可能地阐述它执行的任务。对于一些阐述起来较复杂的函数,至少需要能够通过其名称明显地区分不同函数。如果是对于某种算法的封装,也可以使用算法名。例如, void dijkstra(); void maxFlow();对于非递归的函数,一般前加 inline

    第一类结构体与变量的命名类似,第二类结构体如果是多个单词复合,一般使用驼峰命名法,否则全部使用大写字母,如 struct DSU

    自定义命名空间在算法竞赛中应用较少,主要用于区分不同的部分分。

    这三类内容出现时,相邻两个结构之间均需空一行。


    Part 3 空格、缩进与换行

    • 空格的使用

    适当的空格往往会使代码结构更清晰,增强可读性。

    任意关键字后均需空格,如 while (...) sizeof (f) 等。

    任意双、三目运算符前后均需空格,而单目运算符后不可加空格。如, check(mid) ? l = mid + 1 : r = mid; inline bool operator < (const node &x) const {}等。

    除非位于行末,任意 ,; 后均需空格。

    强制类型转换时,类型的括号后需空格,如 return (ll) x * y % mod;

    • 缩进一律采用四空格形式。
    • 任意大括号的左半部分与上文紧邻的内容在同一行,以一个空格分隔。
    • for , while, if 等结构,若其后相邻的语句不超过一句,则不加大括号,视语句整体长短决定放在同一行还是新开一行。但是如果存在以上结构的嵌套,则为了防止嵌套中的混淆,一般使用大括号。
    • 一行内 ( for 语句内的除外)不允许出现两个或以上的分号。如果有语义上的连贯,可以用逗号代替分号。

    Part 4 其他

    • 循环变量声明时一般用 register

    • 除非从 (0) 开始可以使代码更简洁(状态压缩等),数组下标一般从 (1) 开始。

    • 任何函数(无论其类型是否为 void)均需要在结尾有显式的 return 语句。

    • 任何函数(无论其有多短)均需要将其内部语句单独一行写,不可压在一行。

    • 涉及到位运算时,为了防止不必要的混淆,一般加括号。

  • 相关阅读:
    linux下的内存映射函数mmap详解及示例代码
    Android平台上使用属性系统(property system)
    Android筆記
    Android Prelink
    DataGridView BindingSource BindNavigator
    可排序的ListView
    开源2D绘图组件ZedGraph
    BackgroundWorker示例
    级联datagridview 利用datarelation和bindingsource
    继承DataGridView
  • 原文地址:https://www.cnblogs.com/suwakow/p/11775797.html
Copyright © 2020-2023  润新知