用 C++ 样式注释替换 C 样式注释
Posted
技术标签:
【中文标题】用 C++ 样式注释替换 C 样式注释【英文标题】:Replace C style comments by C++ style comments 【发布时间】:2010-10-07 05:17:18 【问题描述】:如何自动将所有 C 样式 cmets (/* comment */
) 替换为 C++ 样式 cmets (// comment
)?
这必须在多个文件中自动完成。任何解决方案都可以,只要可行。
【问题讨论】:
我很好奇你为什么要这样做? C++ 编译器可以很好地编译 C 风格的 cmets,那么有什么意义呢?您可能不想再添加任何 c 样式的 cmets,但不理会旧的 cmets 应该不会造成任何损失。 为什么会有人说这个问题令人反感? 这个问题是浪费时间。不是从解析的角度来看,而是它试图完成的毫无意义的任务。 -1 坦维尔。或许这是上天的旨意。如果管理层告诉你挖一个洞然后再填一遍,有时你不得不这样做,尽管毫无意义。 您需要这样做的原因可能有很多。也许你有某种预处理器或其他工具。也许您只是有一个需要遵循的编码约定。询问如何重构文本没有任何意义:我们以精心结构化的文本为生。 【参考方案1】:这个工具可以完成这项工作: https://github.com/cenit/jburkardt/tree/master/recomment
RECOMMENT 是一个 C++ 程序 将 C 风格的 cmets 转换为 C++ 风格 厘米。
它还处理其他人提到的所有非平凡案例:
此代码包含建议和 编码于 2005 年 4 月 28 日由 JDS Uniphase 的 Steven Martin, 佛罗里达州墨尔本。这些建议 允许程序忽略 字符串的内部内容,(其中 否则似乎开始或结束 cmets), 处理代码行 带有尾随 cmets,并处理 带有尾随代码的 cmets。
【讨论】:
很遗憾,RECOMMENT 不能很好地处理缩进和格式化,而且它根本不支持 Doxygen cmets。这就是我创建c-comments-to-cpp的原因。【参考方案2】:这不是一个小问题。
int * /* foo
/* this is not the beginning of a comment.
int * */ var = NULL;
你想用什么来代替它?任何真正的替换有时都需要分割线。
int * // foo
// this is not the beginning of a comment.
// int *
var = NULL;
【讨论】:
这不是原始问题的答案。【参考方案3】:你打算如何处理这样的情况:
void CreateExportableDataTable(/*[out, retval]*/ IDispatch **ppVal)
//blah
注意括号内的注释...这是在生成的代码中记录事物的常用方法,或者在类的实现中提及默认参数值等。我通常不喜欢使用 cmets ,但它们很常见,需要考虑。我不认为你可以不经过深思熟虑就将它们转换为 C++ 风格的 cmets。
【讨论】:
有一个相当简单(但不受欢迎的解决方案)。如果您替换的每条评论不以 0 或空白字符和换行符结尾,则插入换行符。所以换句话说,“IDispatch **ppVal)”将在一个新行上。 别误会,我同意你的观点,转换是个坏主意 这不是答案。【参考方案4】:我支持在您的问题中发表评论的人。为什么这样做?放手吧。
它浪费时间,向版本控制添加无用的提交,有搞砸的风险
编辑: 从 OP 的 cmets 添加详细信息
首选 C++ 风格的注释的根本原因是您可以注释掉其中可能包含 cmets 的代码块。如果该注释是 C 风格的,则代码的这种块注释不是直截了当的。 – 未知(雅虎)
这可能是一件公平/好的事情,但我有两个关于这方面的问题:
据我所知,没有人会主张更改所有现有代码 - 这是对新代码的偏好。 (海事组织) 如果您觉得需要“注释掉代码”(另一种不确定的做法),那么您可以根据需要进行 - 而不是在此之前看来你还想用c风格的cmets来屏蔽一段代码?还是要使用 // 来屏蔽很多行?
另一种选择是针对这种情况的预处理器#ifdef。我对此感到畏缩,但这与注释掉行/块一样糟糕。两者都不应该留在生产代码中。
【讨论】:
首选 C++ 风格注释的根本原因是您可以注释掉可能包含 cmets 的代码块。如果该注释是 C 风格的,则代码的这种块注释不是直截了当的。 很公平。两点: 1. 我知道没有人会主张更改所有现有代码 - 那是对新代码的偏好。 (IMO) 2. 如果您觉得需要“注释掉代码”(另一种不确定的做法),那么您可以根据需要进行 - 而不是之前。 在我的编辑器中,注释掉可能包含 cmets 的代码块很简单,只需要两次击键。取消注释同样简单。当你可以使用一个像样的编辑器时,为什么要经历这么多麻烦? -1 因为这确实回答了操作的问题,并且主要只是说这个想法很愚蠢。这就是 cmets 的用途。【参考方案5】:这是一个 Python 脚本,可以(大部分)完成这项工作。它处理大多数边缘情况,但它不处理字符串中的注释字符,尽管这应该很容易修复。
#!/usr/bin/python
import sys
out = ''
in_comment = False
file = open(sys.argv[1], 'r+')
for line in file:
if in_comment:
end = line.find('*/')
if end != -1:
out += '//' + line[:end] + '\n'
out += ' ' * (end + 2) + line[end+2:]
in_comment = False
else:
out += '//' + line
else:
start = line.find('/*')
cpp_start = line.find('//')
if start != -1 and (cpp_start == -1 or cpp_start > start):
out += line[:start] + '//' + line[start+2:]
in_comment = True
else:
out += line
file.seek(0)
file.write(out)
【讨论】:
【参考方案6】:我最近将我们存储库中所有文件的所有 C 样式 cmets 转换为 C++ 样式。由于找不到可以自动执行此操作的工具,我自己编写了一个:c-comments-to-cpp
这不是万无一失的,但比我尝试过的任何其他方法(包括推荐)都要好。除此之外,它还支持转换 Doxygen 样式的 cmets,例如:
/**
* @brief My foo struct.
*/
struct foo
int bar; /*!< This is a member.
It also has a meaning. */
;
转换为:
/// @brief My foo struct.
struct foo
int bar; ///< This is a member.
///< It also has a meaning.
;
【讨论】:
【参考方案7】:您为什么不编写一个 C 应用程序来解析它自己的源文件?您可以通过相对简单的 Regex 查询找到 /* cmets */ 部分。然后你可以用换行符+“//”替换换行符。
无论如何,只是一个想法。祝你好运。
【讨论】:
你到底为什么要在 C 中做这个?有很多语言比 C 更适合正则表达式搜索替换。另外,它为什么要解析“它自己的”源文件? 好吧,我可以说在 C 中做这件事只是因为大概 OP 已经知道 C。话虽如此,我想说避免在 C 中做它的相对痛苦将非常值得努力学习为这项任务提供更好的语言。我个人建议使用 Python,但有很多选择。 正则表达式是不够的,需要一个真正的解析器。 当然,如果您能够获得符合 ANSI 的 C++ 编译器的源代码,那么您就有了解析器。 :) 同意 Darron - 你不能使用正则表达式,例如 printf("////**** 这最好不要更改,它是一个字符串文字!\n");需要一个真正的 C 解析器。【参考方案8】:如果您编写应用程序/脚本来处理 C 源文件,请注意以下几点:
字符串中的注释字符 行中间的注释字符(您可能不想拆分代码行)您最好尝试找到一个了解如何将代码实际解析为代码的应用程序。
【讨论】:
【参考方案9】:您可能想尝试以下一些建议:
a)编写您自己的代码(C/Python/任何您喜欢的语言)来替换 cmets。类似于正则表达式所说的内容或这种天真的解决方案 '可能' 工作: [Darron 发帖,除非像 one rmeador 这样的案例]
对于文件中的行: 如果行 [0] == "\*": buf = '//' + 行中除 '\*' 之外的所有字符 标志 = 真 如果标志 = 真: 如果行以 '*/' 结尾: 剥离 '*/' 标志 = 假 添加 '//' + 行到 bufb) 找到一个工具来做这件事。 (我会查找一些并发布,如果我找到它们。)
c)几乎所有现代 IDE(如果您正在使用的话)或文本编辑器都具有自动注释功能。然后,您可以手动打开每个文件,选择注释行,决定如何处理这种情况并使用加速器(例如 Ctrl + M)注释 C++ 样式。然后,您可以再次使用您的判断来简单地“查找和替换”所有“/*”和“*/”。我已将 Gedit 配置为使用“代码注释”插件来执行此操作。我不记得我在 Vim 中的操作方式。我相信这个很容易找到。
【讨论】:
【参考方案10】:如果只有“几个文件”,真的有必要编写程序吗?在文本编辑器中打开它在实践中可能会更快,除非有大量的 cmets。 emacs 有一个 comment-region
命令(不出所料)对一个区域进行 cmets,所以这只是放弃有问题的 '/*' 和 '*/' 的情况。
【讨论】:
+1。许多文本编辑器也会“在文件中查找和替换”。对于其他海报提到的所有极端情况,您无论如何都需要快速目视检查。【参考方案11】:我知道,这是一个非常老的问题,但我只是使用“纯 emacs”实现了这一点。简而言之,解决方案如下:
运行M-x query-replace-regexp
。出现提示时,输入
/\*\(\(.\|^J\)*?\)*\*/
作为要搜索的正则表达式。 ^J
是一个换行符,您可以通过按 ^Q
(在大多数键盘中为 Ctrl+Q)输入,然后按 enter 键。然后输入
//\,(replace-regexp-in-string "[\n]\\([ ]*?\\) \\([^ ]\\)" "\n\\1// \\2" \1))
作为替换表达式。
本质上,这个想法是您使用两个嵌套的正则表达式搜索。主要的只是找到 C 风格的 cmets(*?
急切的重复对此非常方便)。然后,使用 elisp 表达式执行第二次替换仅在评论文本内。在这种情况下,我正在寻找后跟空格的换行符,并将最后三个空格字符替换为 //
,这对于保留注释格式非常有用(不过,只有在所有 cmets 都缩进时才有效)。
对辅助正则表达式的更改将使这种方法在其他情况下也有效,例如
//\,(replace-regexp-in-string "[\n]" " " \1))
只会将原始注释的全部内容放入单个 C++ 样式的注释中。
【讨论】:
【参考方案12】:来自 php 团队约定...如果提出问题,则必须存在一些推理。知道就回答吧。
永远不要使用 C++ 风格的 cmets(即 // 注释)。始终使用 C 风格 cmets 代替。 PHP 是用 C 语言编写的,旨在编译 在任何符合 ANSI-C 的编译器下。尽管许多编译器 在 C 代码中接受 C++ 风格的 cmets,你必须确保你的 代码也可以与其他编译器一起编译。 此规则的唯一例外是特定于 Win32 的代码, 因为 Win32 端口是 MS-Visual C++ 特定的,而这个编译器 已知在 C 代码中接受 C++ 样式的 cmets。
【讨论】:
以上是关于用 C++ 样式注释替换 C 样式注释的主要内容,如果未能解决你的问题,请参考以下文章