zoukankan      html  css  js  c++  java
  • 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 = @"/*[sS]*?*/|//.*";
                            //去掉多行注释
                            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*includes(""|<).*";
                //匹配头文件
                string regStr2 = @"w+.(h|H)";
    
                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。

  • 相关阅读:
    字符串转换成整型数 atoi()
    求一个正整数各个数位上的数字之和
    求小于等于n的所有素数
    iomanip,setw(),setw: undeclared identifier
    计算机界的牛人前辈
    clrscr( )用法
    printf()
    realloc() 用法详解
    ADO和ADO.NET的区别
    C++中delete和delete[]的区别
  • 原文地址:https://www.cnblogs.com/geeking/p/4021044.html
Copyright © 2011-2022 走看看