老师让我写一个编程规范,让大家参考。当时写在 http://zybuluo.com,现在搬运过来。
CVRS 实验室上的版本(旧):http://cvrs.whu.edu.cn/docs/CVRS-CodingStyleGuide.html
// comment
或者 /* comment */
,第二种是会被放到文档中,用 //! comment
或者 /*! comment */
(也就是多加一个 !
的事)。Edit--Blank Operations--Trim Trailing Space
)C 语言中,单词全小写,单词之间用 _
连接,e.g. feature_detector.h
, feature_detector.c
;
C++ 中,单词首字母用大写表示,单词之间不空格,e.g. FeatureDetector.h
,FeatureDetector.cpp
//! remarks
。ComputingTemperature
。(不同于 MFC,如 MFC 中 CZoomDlg
,在类前加 C
。而小组统一直接表示为 ZoomDlg
。)C++ 中结构体不需要 typedef
便可直接当成类型使用,也就是说,下面两种是一样的
// method 1
struct ElecStateStruct {
char *elec_name;
char *elec_state;
};
// method 2
typedef struct ElecStateStruct {
char *elec_name;
char *elec_state;
} ElecStateStruct;
但推荐使用第二种。
命名规则和类的一样。
函数:
.h
文件)的类中,一般先写 private 型,再写 public 型。并先定义变量后定义函数。内容写于 .cpp
文件,并对其说明。currentTemperature( ... )
,filtering( ... )
//! Function is used for feature point extraction,
//! giving ... type variables,
//! returns 1 means success, 0 means failure
int extractionPoint( ... )
{
...
}
变量:
_currentTemperature
),局部(e.g. currentTemperature
),函数内部的变量可以尽可能短。signals:
void angle_resolution( double res );
void angleResolution( double res );
public slots:
void on_angle_resolution( double res );
void onAngleResolution( double res );
全大写,不以 _
开头(避免重定义覆盖标准库或其他地方的宏),e.g. CURRENT_TEMPERATURE
。
原则 0:
- 美观(不要吝惜你的空格和空行)
- 自身的一致性
- 大家的一致性(规范)
原则 1:
- 用等宽字体
- 不使用
tab
键,用 4 个空格代替(因为不同 IDE、编辑器、网页,对 tab 的显示宽度不一致。)- 缩进(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() );