[完整步骤:安装+配置+dot基本语法+代码实现动态画图] C++函数调用Graphviz软件动态生成图片

引言:
最近实现课程项目实践考核,要求将自动机生成的中间结果以图的形式展现出来。就随手学了一下Graphviz这个软件,非常的简单好用,下面将使用C++函数利用Graphviz生成对应图片的方法进行如下总结。

安装和配资:
安装和配置十分简单,下面以windows为例:
(1)下载:
在官网直接进行下载:https://graphviz.gitlab.io/download/
下载2.38稳定版的.msi文件
在这里插入图片描述
在这里插入图片描述
(2)安装配置
下载后直接双击可执行文件进行安装即可,记住安装路径,方便之后的环境变量的配置。
例如我的安装路径为:D:\graphviz
我们将 D:\graphviz\bin 添加到 环境变量Path中:
在这里插入图片描述

配置完成后使用可能需要重启电脑,使环境变量修改生效

dot基本语法:
(1)打开Gvedit.exe:安装完成后不会生成快捷方式,要在相关路径中查找,查找到后可以生成方式,保存在桌面。
在这里插入图片描述
(2)基本语法:
在.gv文件中输入下面代码,按F5生成图片。

digraph G{
    a -> b[label="{f}"];
    a -> c[label="{g}"];
    b -> c[label="{s}"];
}

在这里插入图片描述
我们看看代码就可以知道
在大括号{ }中每一个;号代表一条边
-> 两遍代表有向边的两个节点名
[label=“xxxxx”]代表边上的转移关系
更多更详细的有关画图属性的语法说明,可以上网搜索

(3)cmd命令行执行:
** Step 1: ** 首先,需要编辑dot脚本

可以使用你熟悉的纯文本编辑器进行脚本编写(必须是纯文本编辑器,如vim、notepad++,像word这样的富文本编辑器是不行的),只需设置编码为UTF-8。
编辑下面的脚本代码,保存为test.dot(先不用管其具体的意思,直接复制就行了):

digraph G{
    main -> parse -> execute;
    main -> init;
    main -> cleanup;
    execute -> make_string;
    execute -> printf;
    init -> make_string;
    main -> printf;
    execute -> compare;
}

Step 2: 随后,选用布局生成结果

使用如下命令生成结果:
dot -Tpng sample.dot -o sample.png

对于这条命令,dot表示用dot布局,-Tpng表示生成png图片格式,sample.dot是脚本文件名,-o sample.png表示生成输出的图片名称。

改命令也可以写成dot -Kdot -Tpng sample.dot -o sample.png,其中-Kdot表示使用dot布局。

C++函数实现图片生成: 环境codeblocks
(1)最简单的调用:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

void gen_graphic()
{
    freopen("graph.dot","w",stdout);
    cout<<"digraph G{"<<endl;
    cout<<"main -> parse -> execute;"<<endl;
    cout<<"main -> init;"<<endl;
    cout<<"}"<<endl;
    fclose(stdout);
    system("dot -Tpng graph.dot -o sample.png");
}
int main()
{
    gen_graphic();
    return 0;
}

将相关dot语句直接使用cout写入graph.dot文件中
调用system函数执行系统命令 dot -Tpng graph.dot -o sample.png 生成图片。
从上面的例子我们可以看出,使用Graohviz生成图片的关键在于,我们只需要生成所需拼接处表示边的字符串即可。

(2)动态生成有向图:
在codeblocks中添加grapg_in.txt文件,其中包含建图需要的四元组信息。(以从某一txt文件中读入动态信息为例,也可以直接从某一数组或数据结构中读入数据)。包含以下信息:

({f},s,{f,g},{null})
({f},q,{f},{g})
({f},p,{g},{f})
({g},s,{f,g},{null})
({g},q,{f},{g})
({null},true,{f,g},{null})

一个四元组表示一条有向边,第一个元素为边尾节点,最后一个元素为边头结点,中间两个元素为边上转移关系。

使用以下函数生成对应的graph.dot文件:
执行 readGraph(“graph_in.txt”,“graph.dot”);

//参数说明:
//string input:包含四元组的txt文件名
//string output:对应生成的dot文件名
void readGraph(string input,string output) //.txt 转 .dot
{
    const char* in = input.data();
    const char* ou = output.data();

    freopen(in,"r",stdin);
    freopen(ou,"w",stdout);
    cout<<"digraph G{"<<endl;

    string s;
    while(cin>>s)
    {
        string u,v,lable;
        int n = s.length();
        int i = 1;
        u = "\"";
        while(s[i] != ',' || s[i-1] != '}') i++;
        u += s.substr(1,i-1);
        u += "\"";
        v = "\"";
        int j = n-2;
        while(s[j] != ',' || s[j+1] != '{') j--;
        v += s.substr(j+1,n-1-j-1);
        v += "\"";
        lable = s.substr(i+1,j-i-1);

        string edge = "";
        edge += u;
        edge += "->";
        edge += v;
        edge += "[label=\"";
        edge += lable;
        edge += "\"];";
        cout<<edge<<endl;
    }
    cout<<"}"<<endl;
    fclose(stdin);
    fclose(stdout);
}

结果:
在这里插入图片描述

根据生成的dot文件生成图片:
执行: makeGraph(“graph.dot”,“graph4.png”);

//参数说明:
//string inputname:dot文件名
//string outputname:生成的png文件名
void makeGraph(string inputname,string outputname) //生成png图片
{
    string s = "";
    s += "dot -Tpng ";
    s += inputname;
    s += " -o ";
    s += outputname;
    const char* cmd = s.data();
    const char* iname = inputname.data();
    system(cmd);

}

结果:
在这里插入图片描述

完整代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

void readGraph(string input,string output) //.txt 转 .dot
{
    const char* in = input.data();
    const char* ou = output.data();

    freopen(in,"r",stdin);
    freopen(ou,"w",stdout);
    cout<<"digraph G{"<<endl;

    string s;
    while(cin>>s)
    {
        string u,v,lable;
        int n = s.length();
        int i = 1;
        u = "\"";
        while(s[i] != ',' || s[i-1] != '}') i++;
        u += s.substr(1,i-1);
        u += "\"";
        v = "\"";
        int j = n-2;
        while(s[j] != ',' || s[j+1] != '{') j--;
        v += s.substr(j+1,n-1-j-1);
        v += "\"";
        lable = s.substr(i+1,j-i-1);

        string edge = "";
        edge += u;
        edge += "->";
        edge += v;
        edge += "[label=\"";
        edge += lable;
        edge += "\"];";
        cout<<edge<<endl;
    }
    cout<<"}"<<endl;
    fclose(stdin);
    fclose(stdout);
}

void makeGraph(string inputname,string outputname) //生成png图片
{
    string s = "";
    s += "dot -Tpng ";
    s += inputname;
    s += " -o ";
    s += outputname;
    const char* cmd = s.data();
    const char* iname = inputname.data();
    system(cmd);

}

void gen_graphic()
{
    freopen("graph.dot","w",stdout);
    cout<<"digraph G{"<<endl;
    cout<<"main -> parse -> execute;"<<endl;
    cout<<"main -> init;"<<endl;
    cout<<"}"<<endl;
    fclose(stdout);
    system("dot -Tpng graph.dot -o sample.png");
}


int main()
{
//  gen_graphic();
    readGraph("graph_in.txt","graph.dot");
    makeGraph("graph.dot","graph4.png");
    return 0;
}

  • 15
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值