首页 > 代码库 > c# 简易绘制C语言头文件包含关系图

c# 简易绘制C语言头文件包含关系图

最近在做一个项目的移植工作,项目很大,光c文件大约有1800多。由于某些需要,想要对某些代码文件引用的.h文件进行分析。

网上找了好久,暂无发现类似的工具。

正好,今天放假,就做了这么个工具。

好了,废话不多说了,先上图。

QQ截图20141012191057

由于是自己做的个demo,所以只是先注重大体功能上的实现,细节上还有很多不足。比如没有使用多线程,去除代码文件中注释的地方还有个漏洞(文件读取1M导致的,不过几乎没影响),还有循环绘制node的地方(逻辑上稍微修改下更好)。

后面奉上代码,大家可以自己根据需求继续修改,也可以凑合这么用。

言归正传。

树形关系呈现上使用了DotNetBar中的TreeGX控件。下载地址:

http://down2.cr173.com/soft1/DotNetBarSetup.zip

先setup,再patcher。

装好后,先添加引用,然后在工具箱中添加treeGX。

QQ截图20141012200812

没错,项目名Jonce,“穷死”。好名字。

界面布局。

QQ截图20141012202708

其实整个流程很简单,1获取指定目录下的所有代码文件;2分析出文件中#include包含的文件;3绘制node节点

CType.cs文件内容:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Jonce{    struct CType    {        public string FullPath;        public string FileName;        public List<string> IncludeList;    }}

该类型用于描述每个代码文件。

CFileHelper.cs文件内容:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;namespace Jonce{    class CFileHelper    {        private List<string> fileList = new List<string>();        /// <summary>        /// 获取及分析所有C代码文件        /// </summary>        /// <param name="path">C项目路径</param>        /// <returns></returns>        public List<CType> GetAllCFile(string path)        {            List<CType> retList = new List<CType>();            getAllByPath(path);            //过滤出所有文件中的代码文件            //分析引用,并存入List<CType>结构内            foreach (string item in fileList)            {                string extension = Path.GetExtension(item).ToLower();                if (extension == ".c" || extension == ".h" || extension == ".cpp")                {                    CType cType = new CType();                    cType.FullPath = item;                    cType.FileName = Path.GetFileName(item);                    //获取C文件中include引用的头文件                    cType.IncludeList = SourceHelper.GetIncludeFile(SourceHelper.RemoveComments(item));                    retList.Add(cType);                }            }            return retList;        }        //获取指定目录下的所有文件        private void getAllByPath(string path)        {            if (path.EndsWith("\\"))            {                fileList.Add(path);            }            else            {                fileList.Add(path + "\\");            }            string[] dirs = Directory.GetDirectories(path);            fileList.AddRange(Directory.GetFiles(path));            foreach (string dir in dirs)            {                getAllByPath(dir.ToString());            }        }    }}

SourceHelper.cs文件内容:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;using System.Windows.Forms;using System.Text.RegularExpressions;namespace Jonce{    class SourceHelper    {        /// <summary>        /// 去掉代码文件中的注释        /// </summary>        /// <param name="filePath">文件全路径</param>        /// <returns>文件前1M内容(去掉注释)</returns>        public static string RemoveComments(string filePath)        {            string retStr = "";            //1M缓冲区            char[] buffer = new char[1024 * 1024];            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))            {                using (StreamReader sr = new StreamReader(fs, Encoding.Default))                {                    try                    {                        //string fileStr = sr.ReadToEnd();                        //读取文件。只读取<=1M内容                        sr.Read(buffer, 0, buffer.Length);                        //字符数组转换为字符串,进行正则匹配                        string fileStr = new string(buffer);                        //正则表达式,匹配多行注释和单行注释                        string regStr = @"/\*[\s\S]*?\*/|//.*";                        //去掉多行注释                        retStr = Regex.Replace(fileStr, regStr, "");                    }                    catch (Exception ex)                    {                        MessageBox.Show(ex.ToString(), "ERR");                    }                }            }            return retStr;        }        /// <summary>        /// 获取C文件中include引用的头文件        /// </summary>        /// <param name="fileStr">文件全路径</param>        /// <returns>头文件List集合</returns>        public static List<string> GetIncludeFile(string fileStr)        {            List<string> headFileList = new List<string>();            //匹配include语句            string regStr1 = @"#\s*include\s(""|<).*";            //匹配头文件            string regStr2 = @"\w+\.(h|H)\b";            Match mc1 = Regex.Match(fileStr, regStr1);            while (mc1.Success)            {                Match mc2 = Regex.Match(mc1.ToString(), regStr2);                if (mc2.Success)                {                    headFileList.Add(mc2.ToString());                }                mc1 = mc1.NextMatch();            }            return headFileList;        }    }}

Form1.cs内容:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.IO;using DevComponents.Tree;namespace Jonce{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            //选取目录            FolderBrowserDialog fbd = new FolderBrowserDialog();            if (fbd.ShowDialog()==DialogResult.OK)            {                string path = fbd.SelectedPath;                CFileHelper fileHelper = new CFileHelper();                //获取及分析所有C代码文件                List<CType> cTypeList = fileHelper.GetAllCFile(path);                //treeGX.Node节点用style                ElementStyle style = new ElementStyle();                //节点文字颜色设置                style.TextColor = Color.Blue;                foreach (CType item in cTypeList)                {                    if (Path.GetExtension(item.FullPath).ToLower() == ".c")                    {                        Node cNode = new Node();                        cNode.Name = item.FileName;                        cNode.Text = item.FileName;                        cNode.Style = style;                        cNode.NodeDoubleClick += cNode_NodeDoubleClick;                        this.node1.Nodes.Add(cNode);                        loopDraw(cTypeList, item.FileName, ref cNode);                    }                }                //this.node1.ExpandAll();                this.node1.Text = path;                //刷新treeGX                this.treeGX1.Refresh();            }                    }        void cNode_NodeDoubleClick(object sender, EventArgs e)        {            Node node = sender as Node;            node.Expand();            //node.ExpandAll();            //throw new NotImplementedException();        }        private void loopDraw(List<CType> cTypeList, string fileName,ref Node node)        {            foreach (CType item in cTypeList)            {                if (item.FileName==fileName)                {                    foreach (string strItem in item.IncludeList)                    {                        Node incNode = new Node();                        incNode.Name = strItem;                        incNode.Text = strItem;                        incNode.NodeDoubleClick += cNode_NodeDoubleClick;                        node.Nodes.Add(incNode);                        loopDraw(cTypeList, strItem, ref incNode);                    }                }            }        }        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)        {            if (comboBox1.SelectedItem==null)            {                return;            }            //DevComponents.Tree.eNodeLayout layout = (DevComponents.Tree.eNodeLayout)Enum.Parse(typeof(DevComponents.Tree.eNodeLayout), comboBox1.SelectedItem.ToString());            DevComponents.Tree.eMapFlow mapFlow = (DevComponents.Tree.eMapFlow)Enum.Parse(typeof(DevComponents.Tree.eMapFlow), comboBox1.SelectedItem.ToString());            if (treeGX1.MapLayoutFlow != mapFlow)            {                treeGX1.MapLayoutFlow = mapFlow;                treeGX1.RecalcLayout();                treeGX1.Refresh();            }        }        private void button2_Click(object sender, EventArgs e)        {            this.node1.ExpandAll();            treeGX1.Refresh();        }        private void button3_Click(object sender, EventArgs e)        {            this.node1.Nodes.Clear();            treeGX1.Refresh();        }    }}

 

以上就是所有代码,大家可以自己重新搭建一个。

当然,如果谁csdn下载积分多的,也可以下载整个项目:http://download.csdn.net/detail/geeking/8030119

只要两个下载积分。本来想免费发的,可是我的积分一个也没有了,很多资源都没法下。shit,积分制度就是shit。

c# 简易绘制C语言头文件包含关系图