- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
这个问题的灵感来自 How to transform a flow chart into an implementation?它询问从代码中通过算法消除 goto
语句的方法。 answer this 中描述了一般问题科学论文。
我已经根据 Knuth 的计算机编程艺术中的算法 X 的高级草图实现了一些代码,描述了具有受限前缀的字典排列的生成(参见 draft 的第 16 页)。
这是对应的flow chart上述算法。
这可能是一个非常聪明且非常高效的算法,但是代码的结构似乎很难遵循。我最终使用了很好的旧 goto
风格的实现:
//Algorithm X;
1:
initialize();
2:
enter_level(k);
3:
set(a[k],q);
if(test() == ok) {
if (k == n) {
visit();
goto 6;
}
goto 4;
}
goto 5;
4:
increase(k);
goto 2;
5:
increasev2(a[k]);
if (q != 0) {
goto 3;
}
6:
decrease(k);
if (k==0) {
goto 7;
}
set(p,u_k);
goto 5;
7:
return;
问题是:如何重构此代码以消除所有 goto
调用?
一个(伪造的)答案是建议“查找引用的科学论文,并逐行跟进” - 事实上,这当然是有可能的。但这个问题是关于有经验的程序员一旦瞥了一眼这个 spaghetti code 就会立即看到什么。 .
我对如何重构感兴趣,而不仅仅是代码。
注意:
goto
跳转,实际实现算法 X 很简单。实现黑盒函数 initialize()
等只需要一些额外的指令,但这些与代码的结构无关。函数调用期间发生了什么并不重要,因为现在的重点是程序的流程。最佳答案
无需太多努力(而且风险不大),您可以快速减少 goto 和标签的数量。
1) 删除未在任何地方引用的标签(这将是标签 1:)
2) 查找只有通过 goto 才能输入的代码块,这些代码块在少数地方被调用。这些通常可以简单地分解出来。 4:可以通过将代码移动到它被调用的地方来处理,并且安全地完成,因为它唯一的导出是一个 goto。这也允许我们删除它上面的 goto 5,因为该代码将简单地跳转到 5:。 7:可以通过修改if语句来处理。此时我们有
initialize();
2:
enter_level(k);
3:
set(a[k],q);
if(test() == ok) {
if (k == n) {
visit();
goto 6;
}
increase(k);
goto 2;
}
5:
increasev2(a[k]);
if (q != 0) {
goto 3;
}
6:
decrease(k);
if (k!=0) {
set(p,u_k);
goto 5;
}
return;
我倾向于在这里停下来。但如果继续,就会变成识别循环并用循环结构替换 goto 的问题。但是,由于代码的结构方式,进行这些更改的风险似乎要大得多。此外,您可能会以 breaks 和 continues 结束,这无论如何都是一种 gotos。我最终得到的是这个(如果没有一些非常严格的测试,我不会保证它的正确性):
initialize();
enter_level(k);
while (true) {
set(a[k],q);
if(test() == ok) {
if (k == n) {
visit();
} else {
increase(k);
enter_level(k);
continue;
}
} else {
increasev2(a[k]);
if (q != 0) {
continue;
}
}
while (true) {
decrease(k);
if (k!=0) {
set(p,u_k);
increasev2(a[k]);
if (q != 0) {
break;
}
} else {
return;
}
}
}
我做了 3:一个循环,和 6:一个内循环。我通过复制 5: 代码代替 goto 并用 break 替换 goto 3 摆脱了 goto 5。这使得制作更干净的循环变得更容易一些。 goto 6 通过使用 else 来修复。 goto 3 变为继续。
在此之后(如果您还有精力),您可以尝试将循环从 while(true) with continues 更改为 whiles with actual conditions。
最好先开发测试,然后进行一两处更改并进行测试。进行另一个更改,然后再次测试。如果您不这样做,很容易在早期犯下结构性错误,然后使后续步骤无效并迫使您重新开始。
关于c++ - 解开 Knuth 的结 : how to restructure spaghetti code?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37079307/
我经常看到“意大利面条”,我只想清楚地解释什么是 意大利面条代码,什么不是。只是因为我不想这样做。 PHP 引用资料会有所帮助,因为这是我选择的语言。 最佳答案 区别在于意大利面条代码是由其他开发人员
我如何确定或判断一组类是否是“意大利面条代码”? 当我在 Visual Studio 中的“体系结构”菜单下生成依赖关系图时,我是否应该将我的代码视为意大利面条,并看到有很多弯曲的箭头指向各处? 我总
任何清理“header spaghetti”的推荐做法编译时间慢 (Linux/Unix)? 在 GCC 中是否有任何等同于“#pragma once”的东西? (发现关于此的相互矛盾的消息) 谢谢。
我正在尝试根据随时间推移由数值组成的数据创建意大利面条图。这是一个大数据,所以不能在这里粘贴,但是在尝试时 matplot(x,y,type="l",lty=1,col="#00000020") 这是
我有一个 Spaghetti Stack(一种 N 叉树数据结构,其中子节点具有指向父节点的指针)- 从数据库接收。 从数据库接收到的“堆栈”只是一个包含所有节点的列表,因此可以里面有多个堆栈。 节点
我有一张图像,人眼清楚地包含几个(此处为 2 个)重叠的“花边”。 这源于一项相当冗长的实验图像分析。 红点是两个向量 px 和 py 中包含的所有点,一个是红色像素的 x_position,另一个是
一般性问题 假设您正在编写一个系统,该系统由一个图以及可以根据相邻节点的配置激活的图重写规则组成。也就是说,您有一个在运行时不可预测地增长/收缩的动态图。如果您天真地使用 malloc,新节点将被分配
感谢您的阅读。 我有一个情节,希望使我的数据集中最新的一年脱颖而出。我的数据只是一个长期的时间序列,所以我想绘制同比比较,所以我对其进行旋转,然后绘制它。 第一段代码运行并大致给出了我所追求的内容(没
我得到的数据类似于以下数据:pandas.DataFrame: diff_1 diff_2 1949-01-01 06:
我刚在美国公司找到一份工作,我继承了一堆讨厌的 php 4 平面文件。我想迁移到 Symfony 2,但我无法获得重构整个东西的许可。 有没有人对将项目的小部分或部分迁移到 Symfony 2 有任何
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 3 年前。 Improv
这个问题的灵感来自 How to transform a flow chart into an implementation?它询问从代码中通过算法消除 goto 语句的方法。 answer this
我刚刚在读 top 100 signs of spaghetti code我遇到了数字 4,它简单地说明: if ($status == "awake"){ $actitivity = "Wr
我有一个包含大约 50-55 个代码文件的 php 应用程序。代码量最大的文件大约有 1200 行代码(包括空格、制表符和多个换行符...),其余代码文件相对较小。 几乎每个文件中的应用程序代码都是
我的应用程序是关于意大利面条的,它应该允许您共享任何 text/plain 内容,前提是它是关于意大利面条的。所以我需要一个只接受此类内容的 Intent 过滤器。 如果有帮助,这些是意大利面条示例:
我是一名优秀的程序员,十分优秀!