如何转换if以切换
How can I convert if to switch?
有没有办法将C++if
s转换为switch
es?嵌套或非嵌套if
s:
if ( a == 1 ) { b = 1; } /*else*/
if ( a == 2 ) { b = 7; } /*else*/
if ( a == 3 ) { b = 3; }
当然,它应该检测转换是否有效。
这不是一个微观优化,它是为了清晰的目的。
通常,您应该能够使用能够处理C++的程序转换工具来实现这一点。
具体来说,我们的DMS软件重组工具包可以做到这一点,使用源代码到源代码的重写。我认为这些已经接近完成任务:
default domain Cpp;
rule fold_if_to_switch_initial(s: stmt_sequence, e: expression,
k1: integer_literal, k2: integer_literal,
a1: block, a2: block):
stmt_sequence->stmt_sequence
= "s
if (e==k1) a1
if (e==k2) a2 "
-> "s
switch (e) {
case k1: a1
break;
case k2: a2
break;
}" if no_side_effects(e) / no_impact_on(a1,e);
rule fold_if_to_switch_expand(s: stmt_sequence, e: expression, c: casebody,
k: integer_literal, a:action)
stmt_sequence->stmt_sequence
= "s
switch (e) { c }
if (e==k) a "
-> "s
switch (e) {
c
case k: a
break;
}" if no_side_effects(e) / no_impact_on(c,e);
必须处理if控制语句而不是块的情况,通过以下方式实现:
rule blockize_if_statements:(e: expression, s: statement):
statement->statement
= "if (e) s" -> "if (e) { s } ";
DMS通过使用完整的语言解析器来工作(是的,它确实有一个带有预处理器的完整C++解析器选项)以处理源代码和重写规则。它不会被空白或注释所欺骗,因为它是在解析树上操作的。"…"中的文本是C++文本("默认域Cpp"声明就是这么说的)带有模式变量\x;"…"之外的文本是DMS的规则元语法,而不是C++。模式匹配树并将模式变量绑定到子树;规则右侧使用模式变量绑定进行实例化。在应用变换之后,它从修改后的树中重新生成(修改后的)源代码。
OP坚持认为,"当然,它应该检测转换是否有效。"。这是规则末尾条件的要点,例如,"if no_side_effect…"。。。noimpact’,用于检查对表达式的求值是否会更改某些内容,以及操作是否会影响表达式的值。
实现这些语义检查是困难的,因为必须考虑C++;令人难以置信的复杂语义。执行此操作的工具必须至少与编译器一样了解(例如,名称、类型、声明的属性、读取和写入),然后必须能够对结果进行推理。DMS目前只能实现其中的一些(我们现在正在为C++11进行全面的控制和数据流分析)。由于语义复杂,我也不希望其他重构工具能很好地完成这一部分;我认为这种情况不太可能改善,因为它需要对C++进行推理。
在OP的情况下(当使用DMS这样的工具时,这种情况经常发生),可以断言事实上这些语义谓词没有被违反(然后你可以用"true"替换它们,从而避免实现它们),或者你只关心特殊情况(例如,操作是对表达式中on以外的变量的赋值),在这一点上,检查变得简单得多,或者你可以通过缩小可接受的语法来模拟检查:
rule fold_if_to_switch_expand(s: stmt_sequence, v: identifier, c: casebody,
k: integer_literal, v2: identifier, k2: integer_literal)
stmt_sequence->stmt_sequence
= "s
switch (v) { c }
if (v==k) v2=k2; "
-> "s
switch (v) {
c
case k: v2=k2;
break;
}" if no_side_effects(c);
话虽如此,如果OP只有几百个已知的地方需要改进,他可能会咬紧牙关,使用他的编辑器更快地完成。如果他不知道地点,和/或有更多的例子,DMS会更快地完成工作,而且可能会减少很多错误。
(我们使用DMS对IBM Enterprise COBOL进行了本质上相同的重构,没有深层语义检查)。
理论上,还有其他具有正确机器类型(模式匹配、重写)的程序转换工具可以做到这一点。据我所知,他们都没有对处理C++进行任何有效的尝试。
我会使用文本编辑器。
步骤1:将MARK放在代码块之前,并可能带有前导标签第2步:将END放在代码块的末尾,并可能带有前导标签步骤3:在某种vi中加载您的文件。运行这样的程序:
/^^T*MARK/
:.,/^^T*ENDMARK/ s/^(^T*)if/1IIFF/g
:%s/IIFF *([^)]*) *{ *([^}]*)};? *$/TEST{1}TSET {2} break;/
:%s/TEST{([^=}]*)==([^}]*)}TSET/COND{1}case 2:/g
?^^T*MARK?
/COND{/
:. s/COND{([^}]*)}/switch(1) {^M^T/
:%s/COND{([^}]*)}/^T/g
:%s/^(^T*)ENDMARK/1} //switch/g
:%s/^^TMARK//g
其中^T是制表符,^M是返回字符(根据您使用的vi/vim版本,您可能无法直接键入)
代码是从我的头顶上写下来的,没有经过测试。但我以前也做过这样的事。此外,包含TEST{whatever}TSET
和COND{whatever}
、MARK
、ENDMARK
和IIFF
类型构造的文件将被严重损坏。
这并不检查有效性,它只是将完全符合您格式的内容转换为switch语句。
有限的有效性检查可以通过一些花哨的ass(对于vi)来完成,以确保等式表达式的左手边对于所有行都是相同的。它也不处理其他问题,但很容易纠正。
然后,在签入之前,您可以使用一个好的比较工具对修改后的代码进行可视化扫描。
- 将按位if条件转换为普通if条件
- 使用if-else将数字转换为单词
- 转换器练习:跳过 if 语句和 if 语句
- 不能在 if 语句 - c++ 中使用 void func 直接将字符串转换为大写
- 如何定义此"if block"中其他无效输入的值,以便在c ++中将字符串转换为对象?
- 如何在预处理器 (#if) 中强制转换静态 const 以避免溢出
- 防止在执行时将两个类中的两个对象转换为 bool:if(a!=b)
- 将if-else转换为循环
- 如何将 If else 语句转换为 switch 语句
- 如何转换if以切换
- "if (var)"使用数字转换而不是布尔值
- 尝试将一堆C++代码转换为Java-if语句
- 在 C++ 中将 if, else if, else 语句转换为 switch 语句
- 我将如何在不使用 if 语句、字符数组、apstring 或 atoi 的情况下将带有两位数字的字符串转换为 int
- 在if中对转换发出gcc警告
- 如何将一系列if/else-if/else-if/关系链转换为线性循环代码
- 用if语句将c++ switch转换为Sql
- C++需要帮助if!=转换为随机数
- 如何将语句if(isalpha(c))从c++转换为MIPS ?
- C/C++ 中的 'if' 语句是否将操作数转换为整数?