1. 程式人生 > 其它 >C/C++程式碼規範

C/C++程式碼規範

C/C++程式碼規範

程式碼格式在一些語言裡不是必需的,比如C語言中,你可以在語句之間加任意個;,可以加很多空格;可以一個語句分兩行寫,也可以把所有程式碼都放在一行。有些語言就對程式碼格式非常敏感,比如Python,同一層級的語句之間一定要有相同的縮排。

程式碼規範是在程式碼格式上更進一步的要求,為的是使程式碼更容易閱讀、出現錯誤更容易查錯。

為了程式碼的整潔、漂亮,程式碼的風格需要統一,也就是說,同一篇程式碼、同一個專案的程式碼風格需要保持一致性。一個人的風格可能是固定的,而一個專案的風格通常需要事先制定。

不同人可能持不同的程式碼風格,但是也有一些規範是大家共同遵守的。可以多閱讀已經寫好的、規範的程式碼,來熟悉一些基本的、大家共同遵守的規範。

下面將介紹一下C語言的程式碼規範大概該注意哪些地方。

縮排

縮排是非常常見的事情,它被用來顯示出程式碼的層級。一般可以用Tab或者空格來形成縮排。

要輸入一個Tab,只要按下鍵盤上的Tab鍵就好了。

使用Tab做縮排,只需要一個Tab就夠了;而使用空格做縮排,一般會使用2或4個空格為一個縮排。

根據不同的編輯器設定或個人習慣,一個Tab可能會被顯示成2 / 4 / 8個空格等等。因此,切忌將Tab將空格(Space)和縮排(Tab)混用,這樣有可能導致程式碼顯示出來的層次變得混亂,難以閱讀。

int foo(int num) {
    // 一級縮排
    if (num % 2 == 0) {
        // 二級縮排
return num + 1; } else return num; }

大括號

一般有兩種方式,一種是左大括號“{”放在行末,另一種是{單獨佔一行。一般第一種更為常見。甚至,會有把else關鍵字放在if語句大括號的同行。

int foo(int num) {
    if (num % 2 == 0) {
        return num + 1;
    } 
    else return num;
}

大括號換行的寫法:

int foo(int num)
{
    if (num % 2 == 0)
    {
        num *= 2;
num += 1; } return num; }

當然,格式都不是絕對的,可以根據情況靈活調整,只要方便閱讀就好。比如如果幾條語句比較簡單、邏輯關聯強,也可以放在一行。

<template class T>
std::vector<T> stack_reverse(std::stack<T> _stack) {
    std::vector<T> result;
    while (!_stack.empty()) { result.pusk_back(_stack.top()); _stack.pop(); }
    return result;
}

空格

比如ifelseforwhile關鍵字後留空格,可以突出關鍵字。而相對應的,函式名後的括號要緊跟

void print_vector_int(const std::vector<int> & a) {
    for (auto i : a) std::cout << i << ' ';
    std::cout << std::endl;
}

左右括號()一般緊緊包裹其中的內容,而,;則緊緊跟著其左側的字元,其右側要留一個空格。

std::vector<int> a = {1, 2, 3, 4, 5};

雙目運算子(如+-===+=<%等)的左右都要留空格。

int num1 = 10 / 2;
int num2 = 20 % 3;
int val = num1 + num2;

單目運算子(如!++--*&等)緊跟它的運算元,前後不留空格。

std::vector<int> a = {
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
};
auto i = a.begin();
while (i != a.end()) {
    std::cout << *i << ' ';
    ++i;
}

方括號[]、成員運算子.->也緊跟其運算元,即前後不留空格。

std::vector<int> a = {1, 2, 3, 4, 5};
a[0] = a[1] + a[2];
a.erase(a.begin());

int val = 10;
auto b = new std::vector<int>();
b->push_back(val);
b->erase(b->begin());

符號命名

養成良好且規範的變數 / 函式命名方式和習慣。

參考閱讀:

符號的命名主要有下劃線法、駝峰法等,比如find_first_of()namedWindow()等。

巨集名列舉名(其實列舉就可以視作一種巨集定義)一般採用全大寫+下劃線,比如BGR2GRAYMAX_LENGTHBLUE等。

一般來說,函式、區域性變數名、全域性變數名、巨集名等,可以採用不同的命名法以區分彼此。

變數名也應具有一定的意義,比如tmptemp一般表示臨時變數,ijk等一般用作迭代,cnt一般用來計數。

struct MyStruct {
    int val_a;
    int val_b;
    char class_type;
    enum Type {TYPE_A, TYPE_B};
    
    bool isValid() { return val_a > 10 && val_b > 20; }
}

註釋

寫程式碼的時候記得新增一些註釋。良好的註釋可以方便自己和別人閱讀和修改程式碼。

不必要事無鉅細,在關鍵部分給出提示即可。

通常,對於一個函式應該寫明其具有的功能、函式各個引數的意義;對於變數要有對其作用的介紹。這樣性質的註釋一般寫在函式或變數的宣告處附近。而對於函式的定義部分也最好有相應的解釋,可以告訴讀者某行或某段程式碼實現了什麼事情、或者為什麼這樣寫。

很多編輯器、IDE可以識別到這些註釋,並在滑鼠懸停在它們的呼叫上時顯示出函式的原型和註釋,很是方便。

函式、變數名本身也應該體現一定的意義。如果得當,那麼程式碼則具有自述性(self-explaining),而不必要額外再寫註釋了。

不建議用中文拼音為符號命名,更不要用中文縮寫,因為中文的緣故,同音詞很多,相同拼音首字母的詞語更多,別人很難聯想到具體是什麼詞語。既然是用26個英文字母程式設計,那麼也建議使用英語給變數起名。

起變數名在一定程度上也需要一定的英語考究,比如一些詞雖然意思相近,但其中的一個會比其他的更合適。

下面是“選猴王”(也就是“約瑟夫問題”)的參考程式碼:

// return the postion number of the monkey king
int get_monkey_king(int n, int m) {
    std::queue<int> monkeys_queue;
    for (int i = 1; i <= n; ++i) monkeys_queue.push(i);
    cnt = 0;
    while (monkeys_queue.size() > 1) {
        ++cnt;
        auto monkey = monkeys_queue.front();
        monkeys_queue.pop();
        if (cnt == m) cnt = 0; 
        else monkeys_queue.push(monkey);
    }
    std::cout << monkeys_queue.front() << std::endl;
}

int main() {
    std::cin >> n >> m;
    std::cout << get_monkey_king(n, m);
}