2

CVRS C++ Coding Style Guidelines

 2 years ago
source link: http://blog.tangzhixiong.com/post-0060-coding-style.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

CVRS C++ Coding Style Guidelines

CVRS C++ Coding Style Guidelines

老师让我写一个编程规范,让大家参考。当时写在 http://zybuluo.com,现在搬运过来。

CVRS 实验室上的版本(旧):http://cvrs.whu.edu.cn/docs/CVRS-CodingStyleGuide.html

零、绪论

  1. 注释分为两种,第一种是给自己看或者其他看代码的人看,用 // comment 或者 /* comment */,第二种是会被放到文档中,用 //! comment 或者 /*! comment */(也就是多加一个 ! 的事)。
  2. 代码宽度不能超过 80 个字符。(注释也不能)
  3. 代码编辑完后,要把 trailing space 去掉(Notepad++ 中 Edit--Blank Operations--Trim Trailing Space

一、C++ 语言部分

1)文件:

C 语言中,单词全小写,单词之间用 _ 连接,e.g. feature_detector.h, feature_detector.c

C++ 中,单词首字母用大写表示,单词之间不空格,e.g. FeatureDetector.hFeatureDetector.cpp

2)类:

  1. 定义声明:对于类的作用和内容进行简单的说明,用 //! remarks
  2. 命名规则:e.g. ComputingTemperature。(不同于 MFC,如 MFC 中 CZoomDlg,在类前加 C。而小组统一直接表示为 ZoomDlg。)

3)结构体:

C++ 中结构体不需要 typedef 便可直接当成类型使用,也就是说,下面两种是一样的

// method 1
struct ElecStateStruct {
    char *elec_name;
    char *elec_state;
};

// method 2
typedef struct ElecStateStruct {
    char *elec_name;
    char *elec_state;
} ElecStateStruct;

但推荐使用第二种

命名规则和类的一样。

4)函数和变量:

函数:

  1. 定义声明:在头文件(.h 文件)的类中,一般先写 private 型,再写 public 型。并先定义变量后定义函数。内容写于 .cpp 文件,并对其说明。
  2. 命名规则:currentTemperature( ... )filtering( ... )
  3. 注释:与 C 一致,须在函数前进行说明。说明函数功能、参数含义及返回值等,e.g.
//! Function is used for feature point extraction,
//! giving ... type variables,
//! returns 1 means success, 0 means failure
int extractionPoint( ... )
{
    ...
}

变量:

  1. 定义声明:与 C 一致。
  2. 命名规则:全局(e.g. _currentTemperature),局部(e.g. currentTemperature),函数内部的变量可以尽可能短。
  3. Qt 中信号和槽也可用 C 语言风格。比如:
signals:
    void angle_resolution( double res );
    void angleResolution( double res );

public slots:
    void on_angle_resolution( double res );
    void onAngleResolution( double res );

5)宏:

全大写,不以 _ 开头(避免重定义覆盖标准库或其他地方的宏),e.g. CURRENT_TEMPERATURE

三、程序排版规则

  1. 美观(不要吝惜你的空格和空行)
  2. 自身的一致性
  3. 大家的一致性(规范)
  1. 用等宽字体
  2. 不使用 tab 键,用 4 个空格代替(因为不同 IDE、编辑器、网页,对 tab 的显示宽度不一致。)
  3. 缩进(indent)用 4 个空格(Visual Studio 需要设置)

C Example:

#include <stdio.h>                                         // <-- 注意这里 <stdio.h> 前的空格
#include <math.h>
                                                           // <-- 【#include】s 后空行
#define PI (3.1415)                                        // <-- 最好都加上括号

typedef struct PointCoordinate
{
    int x ;
    int y;
} Point;

//! setting coordinate                                     // <-- 函数说明
Point set_point( int a, int b );                           // <-- 函数声明,参数列表这里有空格
//! get the area of the circle
double get_area( int radius );

void main()
{
    // define the coordinate of the center, the radius and the area of a circle
    Point point_circle;                                    // <-- 变量定义规则:小写,之间加下划线
    int radius_circle;
    double area_circle;

    // input the information of a circle                   // <-- 函数部分步骤意义说明规则
    printf( "please input point.x & point.y: \n" );        // <-- 函数调用,参数列表这里有空格
    scanf( "%d%d", &point_circle.x, &point_circle.y );
    printf( "please input the radius of the circle:\t" );
    scanf( "%d", &radius_circle );

    area_circle = PI * radius_circle * radius_circle;
    printf( "the area of a circle is: %lf\n", area_circle );
}

Point setPoint( int a, int b )                             // <-- 函数定义,参数列表这里有空格
{
    Ponit pt;
    pt.x = a;
    pt.y = b;
    return pt;
}

double getArea( int radius )
{
    double S;
    S = PI * radius * radius;
    return S;
}

加空格只是出于易读性的考虑,所以我们用 scanf( "%d", &radius_circle ); 而不是 scanf("%d", &radius_circle);。但如果行过长,就可以省略这些空格,比如:

while ( 1 == scanf("%d", &num) ) {       // 这里没空格
    printf( "%d\n", num );               // 这里有空格
}

C++ Example:

#include <iostream>

#define PI (3.1415)
#define MAX (300)

//! basic class,2dim_point                                // <-- 对类的说明
class  Point
{
private:                                                   // <-- 先 private
    int x;                                                 // <-- 不能是 _x
    int y;
public:
    int getX( ) { return x; }                              // <-- 极其简单的函数,可以放在一行
    int getY( ) { return y; }

    //! setting coordinate                                 // <-- 函数说明(这个函数,就不该放在一行)
    void setPoint( int a, int b )
    {
        x = a;
        y = b;
    }

    //! calc distance from this point to another
    double distanceTo( Point &pt );                        // <-- 长的函数都放在 cpp 文件
};

//! derived class circle
class Circle : public Point
{
    private:
        //! radius of a circle                             // <-- 变量说明格式
        int radius;
    public:
        //! set the size of the radius
        int setRadious( int r ) { radius = r; }
        void getRadious( ) { return radius; }
        //! get the area of the circle
        double getArea( ) { return PI * radius * radius; }
};

void main( )
{
    // define a circle
    Circle circle1;

    // set up circle center & radius                       // <-- 对程序中的部分步骤说明
    circle1.setPoint(200, 250);
    circle1.setRadius(100);

    // output the X coordinate of the center of the circle1
    cout << "x = " << circle1.getX() << endl;
    // output the X coordinate of the center of the circle1
    cout << "the Area of Circle1 is " << circle1.getArea() << endl;
}

正确和错误举例

/*
 * 加足够的空格
**/

for(int i;i<count;i++)                                     // WRONG
for ( int i; i < count; i++ )                              // CORRECT
for ( int i; i < count; ++i )                              // EVEN BETTER

int max(int a,int b)                                       // WRONG
int max( int a, int b )                                    // CORRECT

max(23,45);                                                // WRONG
max(23, 45);                                               // WRONG
max( 23, 45 );                                             // CORRECT
max( 21, max(max(3,8), 34) );                              // CORRECT,体会一下这些空格的有无

show();                                                    // CORRECT
show( );                                                   // CORRECT

/*
 * 大括号的位置
**/

for ( int i; i < count; ++i )                              // CORRECT,注意这里的空格
{
    ...
}

for ( int i; i < count; ++i ) {                            // CORRECT
    ...
}

// 同理,正确的 while,if,do while 应为
while ( CONDITION ) {
    ...
}

while ( CONDITION )
{
    ...
}

if ( CONDITION ) {
    ...
}

if ( CONDITION )
{
    ...
}

if ( CONDITION_1 ) {
    ...
} else if ( CONDITION_2 ) {
    ...
} else {
    ...
}

do {
    ...
} while ( CONDITION );


/*
 * 永远都加 {},哪怕只有一行代码,适用于 if、for、while 和函数声明+定义
**/
if ( FATAL_ERROR )                                         // WRONG
    return EXIT_FAILURE;

if ( FATAL_ERROR ) {                                       // CORRECT
    return EXIT_FAILURE;
}

int getX( ) return x;                                      // WRONG
int getX( ) { return x; }                                  // CORRECT


/*
 * 函数声明和调用的参数规范
**/

void func();                                               // WRONG
void func2(int i, int j);

void func( );                                              // CORRECT
void func2( int i, int j );

其他一些说明

注释的放置

流程上的东西,夹在代码内,如:

// set up circle center
circle.setPoint( 200, 250 );
// set up circle radius
circle.setRadius( 100 );

补充说明性质的东西,放在行尾,如:

fprintf( fp,
         "| %*i "              // index
         "| %*s "              // timestamp
         "| %*s%d%*s "         // log level
         "| %*s%s%*s "         // type (aligned to center)
         "| %-*s "             // action
         "| %*s |\n",          // messag
         ... );

对齐

通常不需要对齐,比如:

int x0;
double dx;

不必写成:

int    x0;
double dx;

但如果很多东西,有一种莫名的联系,对齐则是上上之选,比如:

/*
 * 对齐实例 1
**/
ust.time              = parse8BytesToDouble(ba, c, f); c += 8;
// q target
ust.q_target[0]       = parse8BytesToDouble(ba, c, f); c += 8;
ust.q_target[1]       = parse8BytesToDouble(ba, c, f); c += 8;
ust.q_target[2]       = parse8BytesToDouble(ba, c, f); c += 8;
ust.q_target[3]       = parse8BytesToDouble(ba, c, f); c += 8;
ust.q_target[4]       = parse8BytesToDouble(ba, c, f); c += 8;
ust.q_target[5]       = parse8BytesToDouble(ba, c, f); c += 8;

/*
 * 对齐示例 2
**/
enum URFunctionCodes { /* 0-128d */
    // mb_req_pdu
    READ_COILS                   = 0x01,  // read output bits
    READ_DISCRETE_INPUTS         = 0x02,  // read input bits
    READ_HOLDING_REGISTERS       = 0x03,  // read output registers
    READ_INPUT_REGISTERS         = 0x04,  // read input registers
};

/*
 * 对齐示例 3
**/
mcuAddr.insert(  ROLL_PITCH_YAW,        0x000B  );
mcuAddr.insert(  accX_accY_accZ,        0x000E  );
mcuAddr.insert(  GyroscopeX,            0x0011  );

包括行末的 // 注释也最好对齐。外,强烈建议 Qt 的信号和槽也对齐,不要使用

connect(mcu, SIGNAL(mcuTimestamp(quint32)), this, SLOT(onMCUTimestamp(quint32)));

而是使用:

connect( mcu, SIGNAL(mcuTimestamp(quint32)),
         this, SLOT(onMCUTimestamp(quint32)) );

参数列表也要对齐:

// method 1
return QString().sprintf( "%02d:%02d:%02d.%03d"         // e.g. 01:23:45.678
                        , dt.time().hour()
                        , dt.time().minute()
                        , dt.time().second()
                        , dt.time().msec() );
// method 2
return QString().sprintf( "%02d:%02d:%02d.%03d",        // e.g. 01:23:45.678
                          dt.time().hour(),
                          dt.time().minute(),
                          dt.time().second(),
                          dt.time().msec() );
// but not this one
return QString().sprintf( "%02d:%02d:%02d.%03d",        // e.g. 01:23:45.678
                          dt.time().hour(), dt.time().minute(),
                          dt.time().second(), t.time().msec() );
// and, of course, not this one
return QString().sprintf( "%02d:%02d:%02d.%03d", dt.time().hour(),
    dt.time().minute(), dt.time().second(), t.time().msec() );

TANG ZhiXiong, 2018. Generated by Pandoc on Travis CI. Fork Me on GitHub.

Related Issues not found

Please contact @district10 to initialize the comment


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK