爆码风

· · 个人记录

爆码风

\rm Update
  1. 添加了命名风格,whiledo-while 语句,for_each 语句,二维动态数组的构造和析构,结构体的访问级别顺序 (Updated on Saturday, Aug. 6th, 2022)。

前情提要:

  1. include, define, using, typedef 等:

    /* By @Joker_1212 */
    #include <bits/stdc++.h>
    #define ull unsigned long long
    #define ll long long
    // more #define
    using namespace std;
    // typedef
  2. 单句表达式:

    1. 一个语句至少一行。

    2. 运算符前后加空格:

      t = a & (b | c);
      t = a + b * c / d - e % f;
    3. 如果几个操作紧密相关会使用逗号表达式。逗号前不加空格,后加空格。如:

      t = a % b, a = b, b = t;
      cin.tie(nullptr), cout.tie(nullptr);
  3. 变量定义:

    1. 简单变量(intvector 等)

      尽量缩小变量的作用域。

    2. 数组

      1. 如果数组大小随着数据的变化的趋势较明显且维度不高(目前两维及以下),会用动态数组:

        // 构造一维动态数组
        int *arr = new int[n];
        ...
        // 一维动态数组析构
        delete[] arr;
        
        // 构造二维动态数组
        int **arr = new int *[n];
        for (int i = 0; i < n; ++i)
         arr[i] = new int [n];
        // 二维动态数组析构
        for (int i = 0; i < n; ++i)
         delete[] arr[i];
        delete[] arr;
      2. 若趋势不明显(比如一个桶),会用全局数组:

        int a[50005];
    3. 指针,引用:

      *& 紧贴变量名。

    4. 命名风格:

      1. 变量和函数:小写字母加下划线

      2. 常量:大写字母加下划线

      3. 类和结构体:驼峰命名法

  4. 语句块:

    1. 由于最初学的是 Python,受到它的风格影响较大,所有语句块大括号能省则省,且语句块内所有语句严格 4 个空格缩进。(标签不会增加缩进,宏定义直接顶格)

    2. 分支语句:

      1. 若逻辑简单,则使用三目运算符:

        puts(n & 1 ? "NO" : "YES");
      2. 涉及大量枚举的分支,使用 switch-case 子句,所有 case(包括 default) 与 switch 处于同一缩进水平:

        switch(a)
        {
        case 'A':
         ...
         [break;] 这行视情况而加
        case 'B':
         ...
         [break;]
        ...
        default: // default 视情况而加
         ...
         break;
        }
      3. 其他情况使用 if-(else if)-else 子句

    3. while 循环:

      一般使用 while,较少 do-while

      while 语句格式:

       while (/* condition */)
       {
           /* code */
       }

      do-while 语句格式

       do
       {
           /* code */
       } while (/* condition */);
    4. for 循环:

      总则:分号前无空格后有空格,若有部分缺少,则两个分号之间无空格:

      for (int i = 0;; ++i)
      1. 一般情况:

        for (int i = a; i < b; ++i)
      2. 用到 vector 和 C 风格数组等容器的遍历:

        for (auto i = a.begin(); i != a.end();  ++i)
        for (unsigned i = 0; i < a.size(); ++i)
        
        // range_based for loop,for_each 循环
        for (auto i : a) // 只访问
        for (auto &i : a) // 可以修改元素
      3. 需要在循环外用到循环变量:

        int ind;
        for (ind = 0; condition; ++i)
    5. 函数:

      除递归函数外都加 inline,如果参数不是基本数据类型习惯引用传值,默认值的等号前后无空格。泛型与函数声明分两行。

       inline bool cmp(int a, int b)
      
       int dfs(int cnt, int rst=0)
      
       template <typename T>
       inline int find(T val, vector<T> &arr)
    6. 结构体:

      如下:

       struct Point
       {
           // typedef,如果有必要
      
           int x, y;
      
       // 需要时添加
       // public:
       // protected:
       // private:
           // 需要时添加
           Point (int x, int y)
           {
               this->x = x;
               this->y = y;
           }
           ~Point();
      
           // 需要时添加,所有的运算符重载都与其格式类似(不一定有 friend 友元声明)
           friend istream &operator>>(istream &in, Point &p)
           {
               in >> p.x >> p.y;
               return in;
           }
      
           // 需要时添加,所有成员函数与其类似
           bool is_origin()
           {
               return this->x == 0 && this->y == 0;
           }
       }
  5. 其他:

    1. main 函数:

      int main()
      {
      #ifdef LOCAL
        freopen("./in.in", "rb", stdin);
        freopen("./out.out", "wb", stdout);
      #endif
        ios_base::sync_with_stdio(false);
        cin.tie(nullptr), cout.tie(nullptr);
        ...
        return 0;
      }
    2. IO 方式的选择:

      1. Input/输入

        优先 cin,其次 getchar()

      2. Output/输出

        如果逐个字符输出,用 putchar()

        如果对格式的控制比较繁杂,用 printf()

        其他情况用 cout

        输出一定以 \n 结尾。

      3. goto 语句,只在跳出多重循环时使用

由于时间仓促,只写了一小部分,如果有其他的风格我会慢慢加上。也欢迎在评论区提出你认为好的代码风格。