C++代码格式化

文章介绍了如何在Ubuntu18.04上安装clang-format12版本,以利用其强大的代码格式化功能。通过二进制包安装并提供了一个bash脚本来批量格式化多个C++源文件。同时,文章提到了clang-format的风格选项,包括GNU风格,并展示了自定义配置文件的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言


C++代码格式化的工具有很多,比如astyle,clang-format。这里推荐使用clang-format,因为clang-format比astyle更强大,更灵活。但是clang-format也有很多缺点:不能在控制语句之间自动添加一个空白行,不能自动添加花括号等等。clang-format安装方式也有很多,比如源码编译安装,二进制包直接安装,这里选择使用二进制包直接安装。
 

安装


ubuntu18.04软件仓库中默认已经集成了clang-format工具,但是版本比较低,低版本的clang-format支持的功能比较少,这里安装12版本,12版本以及12版本以上支持GNU风格。(官方安装文档:https://apt.llvm.org/

获取安装脚本

wget https://apt.llvm.org/llvm.sh

修改脚本权限

chmod 777 llvm.sh

执行脚本安装

./llvm.sh 版本号

./llvm.sh 12

 

使用


官方提供了clang-format详细使用文档:https://releases.llvm.org/12.0.0/tools/clang/docs/index.html

单文件格式化

方式1:clang-format --style={style_name} -i <需要格式化的文件>

clang-format --style=gnu -i Server.cc

12版本支持的style name有:LLVM、Google、Chromium、Mozilla、WebKit、Microsoft、GNU
 

方式2:clang-format --style=file -i <需要格式化的文件>

clang-format --style=file -i Server.cc

这种方式,需要在使用clang-format命令的同级目录下创建一个.clang-format配置文件,配置文件内容参考官方使用文档。此处参考GNU格式化风格,做了一些调整。

---
Language:        Cpp
# BasedOnStyle:  GNU
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands:   Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
  - __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
  AfterCaseLabel:  true
  AfterClass:      true
  AfterControlStatement: Always
  AfterEnum:       true
  AfterFunction:   true
  AfterNamespace:  true
  AfterObjCDeclaration: true
  AfterStruct:     true
  AfterUnion:      true
  AfterExternBlock: true
  BeforeCatch:     true
  BeforeElse:      true
  BeforeLambdaBody: false
  BeforeWhile:     false
  IndentBraces:    false
  SplitEmptyFunction: true
  SplitEmptyRecord: true
  SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit:     0
CommentPragmas:  '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat:   false
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
ForEachMacros:
  - foreach
  - Q_FOREACH
  - BOOST_FOREACH
StatementAttributeLikeMacros:
  - Q_EMIT
IncludeBlocks:   Preserve
IncludeCategories:
  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
    Priority:        2
    SortPriority:    0
    CaseSensitive:   false
  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
    Priority:        3
    SortPriority:    0
    CaseSensitive:   false
  - Regex:           '.*'
    Priority:        1
    SortPriority:    0
    CaseSensitive:   false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequires:  false
IndentWidth:     2
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Right
ReflowComments:  true
SortIncludes:    true
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Always
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles:  false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard:        Latest
StatementMacros:
  - Q_UNUSED
  - QT_REQUIRE_VERSION
TabWidth:        2
UseCRLF:         false
UseTab:          Never
WhitespaceSensitiveMacros:
  - STRINGIZE
  - PP_STRINGIZE
  - BOOST_PP_STRINGIZE
  - NS_SWIFT_NAME
  - CF_SWIFT_NAME
...

需要注意以下几点:
1)clang-format 只能格式化单个文件,如果需要一次性格式化多个文件,需要编写脚本。
2)-i 是将格式化的内容直接覆盖原文件。
3)–style可以指定直接使用哪种代码风格,如gnu风格;也可以自己根据手动配置。

多文件格式化脚本

#!/bin/bash
CodePath=/root/ceph-14.2.22/src
LogPath=/root/clang.log
SubfixArray=("cc","cpp","c","h","hpp")

function CodeFormat()
{
  for entry in `ls $1`
  do

    LogTime=$(date "+%Y.%m.%d %H:%M:%S")
    FilePath=$1/$entry

    if [ -f $FilePath ]
    then
      if [[ ${SubfixArray[@]} =~ ${FilePath##*.} ]]
      then
        echo "$LogTime $FilePath: file, do format..." | tee -a $LogPath
        clang-format --style=file -i $FilePath
      fi
    elif [ -d $FilePath ]
    then
      echo "$LogTime $FilePath: dir, do nothing..." | tee -a $LogPath
      CodeFormat $FilePath
    else
      echo "$LogTime $FilePath: unknow, do nothing..." | tee -a $LogPath
    fi

  done
}

function main()
{
  if [ -f $LogPath ]
  then
    cat /dev/null > $LogPath
  else
    touch $LogPath
  fi

  CodeFormat $CodePath
}

main

注:这里不建议使用find命令搜索文件,在大型项目中,find命令搜索太慢了
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值