c - 如何从此代码中绘制控制流图?
问题描述
int main() {
int i, grade = 0;
printf (" Enter points: \n");
scanf ("%d", &i);
if (i >= 50 && i <= 60) grade = 5;
else if (i > 50 && i <= 60) grade = 6;
else if (i > 60 && i <= 70) grade = 7;
else if (i > 70 && i <= 80) grade = 8;
else if (i > 80 && i <= 90) grade = 9;
else if (i > 90 && i <= 100) grade = 10;
char sign = ' ';
if (grade) {
int p = i % 10;
if (grade != 5) {
if (p >= 1 && p <= 3)
sign = '-';
else if (grade != 10 && (p >= 8 || p == 0))
sign = '+';
}
printf (" The grade is %d%c. \n", grade, sign);
}
return 0;
}
如何从此代码中绘制控制流图?如果有人可以展示该过程,我将不胜感激。我可以从一个非常简单的案例中得出 CFG,但我不能做到这一点。我还需要确定基础路径和多个条件标准的测试。这不是家庭作业问题,我只是尝试理解课程材料。谢谢。
解决方案
这是 Wikipedia 中对 CFG 的定义,我知道您已经知道了,但为了完整起见,我将其放在这里
计算机科学中的控制流图 (CFG) 是使用图形符号表示在程序执行期间可能遍历的所有路径的表示。
参考:https ://en.wikipedia.org/wiki/Control_flow_graph
以下是路径的定义
路径:CFG上的一系列节点(静态),包括入口节点和出口节点;路径段:沿路径的节点子序列
参考:http ://web.cs.iastate.edu/~weile/cs513x/4.ControlFlowAnalysis.pdf
所以画一个的原因是为了确定程序采取的所有可能的路径,这可能有助于我们在不实际运行程序的情况下确定测试覆盖率(静态分析)。
以下是我们绘制 CFG 时可以遵循的简单规则
- 任何语句都将是图中的一个节点
- 所有节点都有一条有向边,要么到达它们,要么离开它们,或者两者兼而有之。入口节点(第一条语句)只有传出边,出口节点只有传入边。
if/else if
只有像,switch
,这样的条件语句loops
才会有多个出边。- 从一个节点出来的所有路径都会在某个点收敛,在最坏的情况下它们会在出口处收敛。
这是一个备忘单,可以更好地解释它
现在让我们将程序中的每个语句映射到我们将用来表示 CFG 节点的数字
int main() {
1. int i, grade = 0;
2. printf (" Enter points: \n");
3. scanf ("%d", &i);
4. if (i >= 50 && i <= 60)
5. grade = 5;
6. else if (i > 50 && i <= 60)
7. grade = 6;
8. else if (i > 60 && i <= 70)
9. grade = 7;
10. else if (i > 70 && i <= 80)
11. grade = 8;
12. else if (i > 80 && i <= 90)
13. grade = 9;
14. else if (i > 90 && i <= 100)
15. grade = 10;
16. char sign = ' ';
17. if (grade) {
18. int p = i % 10;
19. if (grade != 5) {
20. if (p >= 1 && p <= 3)
21. sign = '-';
22. else if (grade != 10 && (p >= 8 || p == 0))
23. sign = '+';
}
24. printf (" The grade is %d%c. \n", grade, sign);
}
25. return 0;
}
这是按照上面备忘单图表中的说明创建的输出。请注意,节点 16 和 24 之前充当了许多条件节点的连接节点。
信用:我使用draw.io创建上面发布的图像。
注意:绘制 CFG 的秘诀是将每个语句独立于程序,绘制它,然后将它的入口和出口链接到图形的其余部分。
以下是我遵循的一些初始步骤
- 语句 1、2 和 3 是无条件的,因此我创建了三个块将它们链接在一起。
- 语句 4 是条件语句。所以我必须为它创建 4 个块。第一个用于语句 4,第二个和第三个用于 TRUE、FALSE 边,最后一个用于 JOIN 节点。如果为真,则运行语句 5,否则运行语句 6。从语句 5 我们直接转到语句 16,这是我们的连接节点。最后,我们将块 4 链接到块 3 的出边。
- 现在语句 6 本身是一个条件语句,所以我们再次需要 4 个块。我们已经有一个自己的块 6。它的加入节点将是语句 16,就好像它的条件为真,然后运行语句 7,它直接转到 16。现在我们已经有了块 6 和 16,所以我们只需要块为 TRUE , FALSE 分支是语句 7 和 8。
依此类推,我们不断检查适用节点的备忘单并单独创建它们,然后与之前的节点链接。
推荐阅读
- dataframe - 如何根据数据集中某列的值制作散点图?
- java - 初始用户名显示剩余的名字在android中为空
- javascript - 在饼图中绑定动态Json数据
- javascript - Javascript 设置 Cookie 以记住表单提交
- amazon-dynamodb - AWS AppSync 未从 DynamoDB 返回所有记录
- asp.net - 如何在本地对 asp.net 应用程序进行负载/压力测试?
- node.js - 从任何服务器运行 Web 浏览器
- javascript - 将事件监听器添加到索引元素
- html - 字体粗细和字体大小不能一起工作
- android - 二进制 XML 文件第 22 行:错误膨胀类 ImageView 仅在根设备上由 android.content.res.Resources$NotFoundException 引起