算法设计与分析 第一章作业

软工2101罗钰颖 2022-09-07 23:44:00

Google代码规范

命名约定

通用命名规则

函数命名, 变量命名, 文件命名要有描述性; 少用缩写.

说明

尽可能使用描述性的命名, 别心疼空间, 毕竟相比之下让代码易于新读者理解更重要. 不要用只有项目开发者能理解的缩写, 也不要通过砍掉几个字母来缩写单词.

int price_count_reader;    // 无缩写
int num_errors;            // "num" 是一个常见的写法
int num_dns_connections;   // 人人都知道 "DNS" 是什么
​
int n;                     // 毫无意义.
int nerr;                  // 含糊不清的缩写.
int n_comp_conns;          // 含糊不清的缩写.
int wgc_connections;       // 只有贵团队知道是什么意思.
int pc_reader;             // "pc" 有太多可能的解释了.
int cstmr_id;              // 删减了若干字母.

文件命名

总述

文件名要全部小写, 可以包含下划线 (_) 或连字符 (-), 依照项目的约定. 如果没有约定, 那么 “_” 更好.

说明

可接受的文件命名示例:

  • my_useful_class.cc

  • my-useful-class.cc

  • myusefulclass.cc

  • myusefulclass_test.cc // _unittest_regtest 已弃用.

C++ 文件要以 .cc 结尾, 头文件以 .h 结尾. 专门插入文本的文件则以 .inc 结尾

内联函数必须放在 .h 文件中. 如果内联函数比较短, 就直接放在 .h 中.

类型命名

总述

类型名称的每个单词首字母均大写, 不包含下划线: MyExcitingClass, MyExcitingEnum.

说明

所有类型命名 —— 类, 结构体, 类型定义 (typedef), 枚举, 类型模板参数 —— 均使用相同约定, 即以大写字母开始, 每个单词首字母均大写, 不包含下划线. 例如:

// 类和结构体
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
​
// 类型定义
typedef hash_map<UrlTableProperties *, string> PropertiesMap;
​
// using 别名
using PropertiesMap = hash_map<UrlTableProperties *, string>;
​
// 枚举
enum UrlTableErrors { ...

变量命名

总述

变量 (包括函数参数) 和数据成员名一律小写, 单词之间用下划线连接. 类的成员变量以下划线结尾, 但结构体的就不用, 如: a_local_variable, a_struct_data_member, a_class_data_member_.

说明

普通变量命名

举例:

string table_name;  // 好 - 用下划线.
string tablename;   // 好 - 全小写.
​
string tableName;  // 差 - 混合大小写
​

类数据成员

不管是静态的还是非静态的, 类数据成员都可以和普通变量一样, 但要接下划线.

class TableInfo {
  ...
 private:
  string table_name_;  // 好 - 后加下划线.
  string tablename_;   // 好.
  static Pool<TableInfo>* pool_;  // 好.
};
​

结构体变量

不管是静态的还是非静态的, 结构体数据成员都可以和普通变量一样, 不用像类那样接下划线:

struct UrlTableProperties {
  string name;
  int num_entries;
  static Pool<UrlTableProperties>* pool;
};

常量命名

总述

声明为 constexprconst 的变量, 或在程序运行期间其值始终保持不变的, 命名时以 “k” 开头, 大小写混合. 例如:

const int kDaysInAWeek = 7;

函数命名

总述

常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配: MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable().

说明

一般来说, 函数名的每个单词首字母大写 (即 “驼峰变量名” 或 “帕斯卡变量名”), 没有下划线. 对于首字母缩写的单词, 更倾向于将它们视作一个单词进行首字母大写 (例如, 写作 StartRpc() 而非 StartRPC()).

注释

注释风格

总述

使用 ///* */, 统一就好.

文件注释

总述

在每一个文件开头加入版权公告.

文件注释描述了该文件的内容. 如果一个文件只声明, 或实现, 或测试了一个对象, 并且这个对象已经在它的声明处进行了详细的注释, 那么就没必要再加上文件注释. 除此之外的其他文件都需要文件注释.

说明

法律公告和作者信息

每个文件都应该包含许可证引用. 为项目选择合适的许可证版本.(比如, Apache 2.0, BSD, LGPL, GPL)

如果你对原始作者的文件做了重大修改, 请考虑删除原作者信息.

文件内容

如果一个 .h 文件声明了多个概念, 则文件注释应当对文件的内容做一个大致的说明, 同时说明各概念之间的联系. 一个一到两行的文件注释就足够了, 对于每个概念的详细文档应当放在各个概念中, 而不是文件注释中.

不要在 .h.cc 之间复制注释, 这样的注释偏离了注释的实际意义.

类注释

总述

每个类的定义都要附带一份注释, 描述类的功能和用法, 除非它的功能相当明显.

函数注释

总述

函数声明处的注释描述函数功能; 定义处的注释描述函数实现.

说明

函数声明

基本上每个函数声明处前都应当加上注释, 描述函数的功能和用途. 只有在函数的功能简单而明显时才能省略这些注释(例如, 简单的取值和设值函数). 注释使用叙述式 (“Opens the file”) 而非指令式 (“Open the file”); 注释只是为了描述函数, 而不是命令函数做什么. 通常, 注释不会描述函数如何工作. 那是函数定义部分的事情.

函数声明处注释的内容:

  • 函数的输入输出.

  • 对类成员函数而言: 函数调用期间对象是否需要保持引用参数, 是否会释放这些参数.

  • 函数是否分配了必须由调用者释放的空间.

  • 参数是否可以为空指针.

  • 是否存在函数使用上的性能隐患.

  • 如果函数是可重入的, 其同步前提是什么?

举例如下:

// Returns an iterator for this table.  It is the client's
// responsibility to delete the iterator when it is done with it,
// and it must not use the iterator once the GargantuanTable object
// on which the iterator was created has been deleted.
//
// The iterator is initially positioned at the beginning of the table.
//
// This method is equivalent to:
//    Iterator* iter = table->NewIterator();
//    iter->Seek("");
//    return iter;
// If you are going to immediately seek to another place in the
// returned iterator, it will be faster to use NewIterator()
// and avoid the extra seek.
Iterator* GetIterator() const;
​

但也要避免罗罗嗦嗦, 或者对显而易见的内容进行说明.

变量注释

总述

通常变量名本身足以很好说明变量用途. 某些情况下, 也需要额外的注释说明.

说明

类数据成员

每个类数据成员 (也叫实例变量或成员变量) 都应该用注释说明用途. 如果有非变量的参数(例如特殊值, 数据成员之间的关系, 生命周期等)不能够用类型与变量名明确表达, 则应当加上注释. 然而, 如果变量类型与变量名已经足以描述一个变量, 那么就不再需要加上注释.

特别地, 如果变量可以接受 NULL-1 等警戒值, 须加以说明. 比如:

private:
 // Used to bounds-check table accesses. -1 means
 // that we don't yet know how many entries the table has.
 int num_total_entries_;
​

全局变量

和数据成员一样, 所有全局变量也要注释说明含义及用途, 以及作为全局变量的原因. 比如:

// The total number of tests cases that we run through in this regression test.
const int kNumTestCases = 6;

实现注释

总述

对于代码中巧妙的, 晦涩的, 有趣的, 重要的地方加以注释.

说明

代码前注释

巧妙或复杂的代码段前要加注释.

行注释

比较隐晦的地方要在行尾加入注释. 在行尾空两格进行注释.

不允许的行为

不要描述显而易见的现象, 永远不要 用自然语言翻译代码作为注释, 除非即使对深入理解 C++ 的读者来说代码的行为都是不明显的. 要假设读代码的人 C++ 水平比你高, 即便他/她可能不知道你的用意:

你所提供的注释应当解释代码 为什么 要这么做和代码的目的, 或者最好是让代码自文档化.

TODO 注释

总述

对那些临时的, 短期的解决方案, 或已经够好但仍不完美的代码使用 TODO 注释.

TODO 注释要使用全大写的字符串 TODO, 在随后的圆括号里写上你的名字, 邮件地址, bug ID, 或其它身份标识和与这一 TODO 相关的 issue. 主要目的是让添加注释的人 (也是可以请求提供更多细节的人) 可根据规范的 TODO 格式进行查找. 添加 TODO 注释并不意味着你要自己来修正, 因此当你加上带有姓名的 TODO 时, 一般都是写上自己的名字.

// TODO(kl@gmail.com): Use a "*" here for concatenation operator.
// TODO(Zeke) change this to use relations.
// TODO(bug 12345): remove the "Last visitors" feature
​

如果加 TODO 是为了在 “将来某一天做某事”, 可以附上一个非常明确的时间 “Fix by November 2005”), 或者一个明确的事项 (“Remove this code when all clients can handle XML responses.”).

格式

行长度

总述

每一行代码字符数不超过 80.

非 ASCII 字符

总述

尽量不使用非 ASCII 字符, 使用时必须使用 UTF-8 编码.

空格还是制表位

总述

只使用空格, 每次缩进 2 个空格.

函数声明与定义

总述

返回类型和函数名在同一行, 参数也尽量放在同一行, 如果放不下就对形参分行, 分行方式与 函数调用 一致.

说明

函数看上去像这样:

ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {
  DoSomething();
  ...
}
​

如果同一行文本太多, 放不下所有参数:

ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,
                                             Type par_name3) {
  DoSomething();
  ...
}
​

甚至连第一个参数都放不下:

ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
    Type par_name1,  // 4 space indent
    Type par_name2,
    Type par_name3) {
  DoSomething();  // 2 space indent
  ...
}
​

注意以下几点:

  • 使用好的参数名.

  • 只有在参数未被使用或者其用途非常明显时, 才能省略参数名.

  • 如果返回类型和函数名在一行放不下, 分行.

  • 如果返回类型与函数声明或定义分行了, 不要缩进.

  • 左圆括号总是和函数名在同一行.

  • 函数名和左圆括号间永远没有空格.

  • 圆括号与参数间没有空格.

  • 左大括号总在最后一个参数同一行的末尾处, 不另起新行.

  • 右大括号总是单独位于函数最后一行, 或者与左大括号同一行.

  • 右圆括号和左大括号间总是有一个空格.

  • 所有形参应尽可能对齐.

  • 缺省缩进为 2 个空格.

  • 换行后的参数保持 4 个空格的缩进

函数调用

总述

要么一行写完函数调用, 要么在圆括号里对参数分行, 要么参数另起一行且缩进四格. 如果没有其它顾虑的话, 尽可能精简行数, 比如把多个参数适当地放在同一行里.

条件语句

总述

倾向于不在圆括号内使用空格. 关键字 ifelse 另起一行.

循环和开关选择语句

总述

switch 语句可以使用大括号分段, 以表明 cases 之间不是连在一起的. 在单语句循环里, 括号可用可不用. 空循环体应使用 {}continue.

指针和引用表达式

总述

句点或箭头前后不要有空格. 指针/地址操作符 (*, &) 之后不能有空格.

布尔表达式

总述

如果一个布尔表达式超过标准行宽, 断行方式要统一一下.

函数返回值

总述

不要在 return 表达式里加上非必须的圆括号.

变量及数组初始化

总述

=, (){} 均可.

预处理指令

总述

预处理指令不要缩进, 从行首开始.

 

参考:Google 开源项目风格指南——中文版https://zh-google-styleguide.readthedocs.io/en/latest/

 

《数学之美》读后感

    爱因斯坦说:从希腊哲学到现代物理学的整个科学史中,不断有人力图把表面上极为复杂的自然现象归为几个简单的基本概念和关系,这就是整个自然哲学的基本原理。

    如果说教育有最失败的地方,那就是学生从上课第一天起到考试结束,都不知道他学的东西能做什么,有什么实际的用途,很多时候都是后知后觉,这便是填鸭式教育和题海战术的弊端。

    吴军在《数学之美》一书中用很多通俗易懂、贴近生活的例子向我们讲述了很多数学原理的应用场景。所用的数学模型是那么简单,效果又是如此显著。数学之“美”便在于“大道至简”。书里每一个模型和数学原理,在美到无与伦比的同时,又都不约而同得秉承着一条美学原则,那就是——简单

    作者从文字与语言入手,并没有涉及到数学原理或数学模型的内容,阐述了信息、文字和数学的产生,随后向我们解释了文字和语言背后的数学。

    我们每个人都从小就开始学数学,多数人说起数学,恐怕都会觉得太难、太深奥。而且很多时候,似乎我们的工作也不需要那么多复杂的数学知识。

    不过有些事实我们无法回避,这个世界属于科学范畴的各种知识,它的底层逻辑,几乎都离不开数学。我们现代生活的方方面面,无论是现实的物质世界,还是虚拟的网络社会,都建立在一个用数学知识为基础的复杂结构里。

    《数学之美》这本书最大的价值,是告诉我们,数学是以什么方式定义了我们的世界,数学思维的魅力究竟在哪里。你可以不懂那么多复杂的公式,但如果你理解了数学背后的思维方式,有了感知和理解这个世界的能力,就会进入一个新境界。

    首先我们要了解数学到底有什么用。比如让计算机处理自然语言时,人们一开始想让计算机学会人类的语法,但后来发现,要写出来的语法不仅数量特别多,而且实际的识别率特别低。后来科学家们在数学统计学工具的帮助下,让计算机计算出句子的出现概率,通过概率的大小来判断正确与否,从而解决了这个难题。在让计算机进行新闻分类时,科学家们也是另辟蹊径,利用新闻中的特征词来构建向量,再使用余弦定理完成了对新闻的分类。数学让我们抓住做事的规律也就是“道”。

    那数学为什么这么有用,归根到底是因为数学能帮助我们发现仅凭经验无法发现的规律,找到仅凭经验无法总结出来的办法。比如我们是在数学的帮助下,才发现了行星围绕恒星运转的真正规律。而我们每天使用的全拼输入法,也都是靠着数学的帮助,才让输入效率不断提高。

    最后,为什么说数学之美就是简单美。当使用数学的方法,“术”可能比较复杂,但是“道”却总是简单的。不管是计算机背后隐含的简单的布尔代数原理,还是使用数学来解决各种问题时体现出的简单思想,都向我们展示出数学之美就是简单美。

...全文
57 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

434

社区成员

发帖
与我相关
我的任务
社区描述
广东外语外贸大学信息科学与技术学院
算法 高校
社区管理员
  • brisksea
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧