欲善其事,先利其器——VSCode之代码格式化(K&R,Allman花括号换行之争,参数换行,宏定义连续对齐,C/C++ Extension Pack,clang-format)

重案组之虎达文西 2024-10-20 15:05:01 阅读 63

编写符合行业规范的代码是一项重要的专业技能!(省流版:clang-format配置在最后面),作为小小的过来人,本人初学编程时完全不拘一格,每一份工程都有不同的风格,在遇到问题请教大佬时常常折磨大佬的眼睛,emmm在此向各位被我折磨过的大佬致歉和感谢。

目录

一、缩进风格

K&R style

Allman style

哪种风格更好?

二、参数换行

三、宏定义连续对齐

四、C/C++ Extension Pack自定义格式化代码

五、配置clang-format文件

六、其他资料参考


一、缩进风格

在编程界,左花括号存在不同风格的争论,即:K&R 风格(Kernighan & Ritchie Style)和 Allman 风格之争。常被称为“花括号换行之争”,至今也没有编程界的秦始皇统一编写风格。

K&R style

K&R 风格是以 C 语言的创始人 Brian Kernighan 和 Dennis Ritchie 命名的,并在《The C Programming Language》这本经典书籍中首次引入。这种风格广泛应用于 C、C++、Java、JavaScript 和其他 C 系语言中。

<code>if (condition) {

// 代码块

} else {

// 代码块

}

Allman style

Allman 风格的名字来源于 Eric Allman,他是 Unix sendmail 程序的主要开发者。这种风格有时也称为 “BSD 风格” 或 “ANSI 风格”。

if (condition)

{

// 代码块

}

else

{

// 代码块

}

哪种风格更好?

没有绝对的好坏之分,两种风格各有优缺点,最终取决于个人偏好或团队的代码规范。项目组内的一致性更为重要,选择一种大家都能接受的风格,并统一应用到整个项目中。

K&R 和 Allman 风格的争论,归根结底是开发者在美观、可读性和效率之间的权衡,这场“花括号换行之争”大概率永远不会有一个统一的答案。

二、参数换行

int function(unsigned int very_very_long_parameter1, unsigned int very_very_long_parameter2,unsigned int very_very_long_parameter3, unsigned int very_very_long_parameter4,unsigned int very_very_long_parameter5, unsigned int very_very_long_parameter6) {

// 代码逻辑

}

当参数过长时,可以通过换行来改善代码的可读性。通常,参数会在逗号处进行换行,并且下一行的参数与函数的起始括号对齐。

示例:

int function(unsigned int very_very_long_parameter1, unsigned int very_very_long_parameter2,

unsigned int very_very_long_parameter3, unsigned int very_very_long_parameter4,

unsigned int very_very_long_parameter5, unsigned int very_very_long_parameter6) {

// 代码逻辑

}

int function(

unsigned int very_very_long_parameter1,

unsigned int very_very_long_parameter2,

unsigned int very_very_long_parameter3,

unsigned int very_very_long_parameter4,

unsigned int very_very_long_parameter5,

unsigned int very_very_long_parameter6

) {

// 代码逻辑

}

三、宏定义连续对齐

在 C/C++ 中编写宏定义时,尤其是宏定义特别多的时候,就需要保持统一的格式和对齐方式以增强可读性。

不对齐:

#define MAX_SIZE 100

#define MIN_SIZE 50

#define DEFAULT_SIZE 75

#define BUFFER_OVERFLOW_ERROR -1

#define INVALID_INDEX_ERROR -2

垂直方向连续对齐:

#define MAX_SIZE 100

#define MIN_SIZE 50

#define DEFAULT_SIZE 75

#define BUFFER_OVERFLOW_ERROR -1

#define INVALID_INDEX_ERROR -2

对齐后阅读效率大大滴提高。

四、C/C++ Extension Pack自定义格式化之设置

VSCode 的 C/C++ 插件 内置了 clang-format。安装 C/C++ 插件(Microsoft) 后,无需额外安装 clang-format,插件会自动使用内置的 clang-format 来进行代码格式化。

不需要额外安装clang-format

打开C/C++ Extension Pack设置,定位到formatting设置

Format On Paste:粘贴代码自动格式化

Format On Save:保存时格式化

Format On Save Mode:这个设置在启用Format On Save功能时,VS Code 会格式化整个文件或只格式化修改过的部分。

file(默认选项):

选择此选项保存文件时,VS Code 会格式化整个文件。即使你只修改了部分内容,保存时所有内容都会被格式化。

modifications:

这个选项意味着只有修改过的代码(即你最近编辑过的部分)会在保存时被格式化。未修改的部分保持原样。

modificationsIfAvailable:

如果编辑器能识别到修改部分,则仅格式化修改的部分。如果无法识别,就格式化整个文件。

这些选项只会在启用了Format On Save前提下生效。

最后一个Format on type是键入格式化,比如键入;就会格式化。

五、配置clang-format文件

在设置好C/C++ Extension Pack之后,最后一步就是配置clang-format文件了,打开settings.json文件可以看到如果不配置clang-format文件,clang-format会使用默认的风格格式化代码。

在vscode官方文档中也提到了这一点

自定义格式化风格可点击查看→Clang-Format官方文档

也可以直接参考我的配置

<code>BasedOnStyle: LLVM

# 强制花括号遵循 Allman 风格

BreakBeforeBraces: Allman

# 对齐连续的宏定义

AlignConsecutiveMacros: AcrossEmptyLinesAndComments

# 控制行宽,避免行太长

ColumnLimit: 120

# 控制空格和标点符号风格

SpaceBeforeParens: ControlStatements # 控制语句的括号前有空格

SpaceBeforeAssignmentOperators: true # 赋值操作符前插入空格

# 缩进设置

IndentWidth: 4 # 使用4个空格缩进

# 控制每行最大空行数(避免空行过多)

MaxEmptyLinesToKeep: 1

# 启用注释对齐,注释前保留一个空格

AlignTrailingComments: true

SpacesBeforeTrailingComments: 1

# 对齐转义的换行符到左侧

AlignEscapedNewlinesLeft: true

# 允许将参数换行,但保持多个参数在同一行(打包参数)

AllowAllParametersOfDeclarationOnNextLine: true

BinPackParameters: true # 启用参数打包,减少换行次数

把BreakBeforeBraces: Allman删掉,则默认是K&R风格。

把ColumnLimit: 120删掉,则默认是80,如果有开左右页面编写的需求或者笔记本之类的小屏幕可以改小避免行太长(下图演示为80)。

其他项就不赘述了。

使用方法:在工程目录下新建一个.clang-format文件,记事本打开粘贴进去保存即可。

演示效果

格式化前:

#define ADD(a,b) a+b

#define MULTIPLY(x, y) x*y

#define CHECK(a,b) if(a>b){ printf("a is greater\n");} else {printf("b is greater\n"); }

#define SQUARE(z) z*z

#define MAX(x,y) ( ( x > y ) ? x :y )

#define MIN( x , y ) ((x)<(y)?(x):(y))

#define ABS( value ) ( ( value<0) ? -value :value)

#define DO_THING(p, q) if(p){while(q > 0){q--;}}

#define SET_FLAG(flag, mask) flag |= mask

#define CLEAR_FLAG(flag, mask) flag&=~mask

#define TOGGLE_FLAG(flag, mask) flag ^=mask

#define COMPLEX_MACRO(a, b, c, d, e) if(a > b && (c==d || e!=0)) { printf("complex logic\n");}

void ComplexFunctionWithManyParams(int param1,int param2,int param3,int param4,

int param5,int param6,int param7,int param8,int param9,int param10,char*str1,char*str2){if(param1>0){

if(param2<param3){for(int i=0;i<param4;++i){while(param5>param6){param7=(param8*param9)/(param10==0?1:param10);

if(param7<param1){strcat(str1,str2);if(strcmp(str1,str2)==0){printf("Strings are equal\n");}

}}else{param6--;}}}}else{if(param9==param10){printf("param9 is equal to param10\n");}else{

printf("param9 is not equal to param10\n");if(param8>param7){for(int j=0;j<param5;++j){param1-=param2;}}}}}}}

格式化后:

#define ADD(a, b) a + b

#define MULTIPLY(x, y) x *y

#define SQUARE(z) z *z

#define MAX(x, y) ((x > y) ? x : y)

#define MIN(x, y) ((x) < (y) ? (x) : (y))

#define ABS(value) ((value < 0) ? -value : value)

#define SET_FLAG(flag, mask) flag |= mask

#define CLEAR_FLAG(flag, mask) flag &= ~mask

#define TOGGLE_FLAG(flag, mask) flag ^= mask

#define COMPLEX_MACRO(a, b, c, d, e) \

if (a > b && (c == d || e != 0)) \

{ \

printf("complex logic\n"); \

}

#define DO_THING(p, q) \

if (p) \

{ \

while (q > 0) \

{ \

q--; \

} \

}

#define CHECK(a, b) \

if (a > b) \

{ \

printf("a is greater\n"); \

} \

else \

{ \

printf("b is greater\n"); \

}

void ComplexFunctionWithManyParams(int param1, int param2, int param3,

int param4, int param5, int param6,

int param7, int param8, int param9,

int param10, char *str1, char *str2)

{

if (param1 > 0)

{

if (param2 < param3)

{

for (int i = 0; i < param4; ++i)

{

while (param5 > param6)

{

param7 = (param8 * param9) / (param10 == 0 ? 1 : param10);

if (param7 < param1)

{

strcat(str1, str2);

if (strcmp(str1, str2) == 0)

{

printf("Strings are equal\n");

}

}

}

else

{

param6--;

}

}

}

}

else

{

if (param9 == param10)

{

printf("param9 is equal to param10\n");

}

else

{

printf("param9 is not equal to param10\n");

if (param8 > param7)

{

for (int j = 0; j < param5; ++j)

{

param1 -= param2;

}

}

}

}

}

六、其他资料参考

还有很多需要注意的编写规范,一篇文章肯定是连皮毛都讲不完的。

推荐阅读《c语言规范》、《华为c编程规范》和《c专家编程》



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。