c# 简易绘制C语言头文件包含关系图
最近在做一个项目的移植工作,项目很大,光c文件大约有1800多。由于某些需要,想要对某些代码文件引用的.h文件进行分析。
网上找了好久,暂无发现类似的工具。
正好,今天放假,就做了这么个工具。
好了,废话不多说了,先上图。

由于是自己做的个demo,所以只是先注重大体功能上的实现,细节上还有很多不足。比如没有使用多线程,去除代码文件中注释的地方还有个漏洞(文件读取1M导致的,不过几乎没影响),还有循环绘制node的地方(逻辑上稍微修改下更好)。
后面奉上代码,大家可以自己根据需求继续修改,也可以凑合这么用。
言归正传。
树形关系呈现上使用了DotNetBar中的TreeGX控件。下载地址:
http://down2.cr173.com/soft1/DotNetBarSetup.zip
先setup,再patcher。
装好后,先添加引用,然后在工具箱中添加treeGX。

没错,项目名Jonce,“穷死”。好名字。
界面布局。

其实整个流程很简单,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语言头文件包含关系图的更多相关文章
- c# 简易绘制C语言头文件包含关系图 v2.0
老规矩,先上图 节点样式说明: 1.粉色圆角,说明该节点下有循环引用 2.黄色菱形,说明该节点代表的文件在项目目录下未找到. 3.红色圆角,说明循环引用(从开始到最终,这种感情没变过,没有谁..... ...
- 利用python+graphviz绘制数据结构关系图和指定目录下头文件包含关系图
作为一名linux系统下的C语言开发,日常工作中经常遇到两个问题: 一是分析代码过程中,各种数据结构互相关联,只通过代码很难理清系统中所有结构体的整体架构,影响代码消化的效率; 二是多层头文件嵌套包含 ...
- c语言头文件中定义全局变量的问题
c语言头文件中定义全局变量的问题 (转http://www.cnblogs.com/Sorean/) 先说一下,全局变量只能定义在 函数里面,任意函数,其他函数在使用的时候用extern声明.千万不要 ...
- c头文件包含关系--记今天调试的郁闷经历
c头文件包含关系--记今天调试的郁闷经历 彭会锋 2016-08-05 21:54:08 c头文件的包含
- 嵌入式C语言头文件的建立与使用
如何正确编写 C 语言头文件和与之相关联的 c 源程序文件,这首先就要了解它们的各自功能. 要理解 C 文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程. 一般说来编译器会做以下几 ...
- 51单片机C语言学习笔记6:51单片机C语言头文件及其使用
很多初学单片机者往往对C51的头文件感到很神秘,而为什么要那样写,甚至有的初学者喜欢问,P1口的P为什么要大写,不大写行不行呢?其实这个是在头文件中用sfr定义的,现在定义好了的是这样的 sfr P1 ...
- C语言头文件
最近在工作当中遇到了一点小问题,关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题.学习C语言已经有好几年了,工作使用也近半年了,但是对于这部分的东西的确还没有深入的思考过.概念上还是比 ...
- C++标准库头文件名字和C语言头文件名字的区别
1.C++版本的C标准库头文件,一般是cname,而C语言头文件一般是name.h 2.命名为cname的头文件中定义的名字都是从std中来的,而如果是name.h则不是这样的. 3.与是用name. ...
- C语言头文件的使用(转载)
C语言头文件的使用 ——by janders 转载请注名作者和出处,谢谢! C语言中的.h文件和我认识由来已久,其使用方法虽不十分复杂,但我却是经过了几个月的“不懂”时期,几年的“一知半解”时期才逐渐 ...
随机推荐
- win7 win10双系统开机系统引导
以win7启动管理器引导作为启动引导 安装一个easybcd 然后里面添加引导选项(添加新条目---->编辑引导菜单(选择倒计时30秒)把use metro bootloader勾去掉就是默认的 ...
- November 04th, 2017 Week 44th Saturday
It does not do to dwell on dreams and forget to live. 整天沉溺于梦想而忘记如何好好生活,毫无意义. Bingo, and I think it i ...
- java使用elasticsearch分组进行聚合查询(group by)-项目中实际应用
java连接elasticsearch 进行聚合查询进行相应操作 一:对单个字段进行分组求和 1.表结构图片: 根据任务id分组,分别统计出每个任务id下有多少个文字标题 .SQL:select id ...
- Algorithms: 二叉平衡树(AVL)
二叉平衡树(AVL): 这个数据结构我在三月份学数据结构结构的时候遇到过.但当时没调通.也就没写下来.前几天要用的时候给调好了!详细AVL是什么,我就不介绍了,维基百科都有. 后面两月又要忙了. ...
- BZOJ4810:[YNOI2017]由乃的玉米田(莫队,bitset)
Description 由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐. 由乃认为玉米田不美,所以她决定出个数据结构题 这个题是这样的: 给你一 ...
- weex+vue2.x 踩坑实录(不定期更新)
执行 npm start 显示空白页面 这个是开始使用weex就出现的一个大坑,说实话对新手真的很不友好. 1.打开控制台显示:Cannot assign to read only property ...
- Python2.7-anydbm
anydbm模块,把各种数据库模块(dbhash (requires bsddb), gdbm, or dbm)的接口进行了统一.打开后返回的对象操作和字典类似 模块方法: anydbm.open(f ...
- Android An unexpected exception occurred while creating a change object. see the error log for more details
今天再给Android项目工程中的包重命名时出现了这个错误(之前重命名的时候就没有出现,郁闷):An unexpected exception occurred while creating a ch ...
- HDU 2767 Proving Equivalences(至少增加多少条边使得有向图变成强连通图)
Proving Equivalences Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- day76
昨日回顾: 1 ajax 什么是ajax:异步的JavaScript 和xml 2 特点:异步,局部刷新 3 简单的与后台交互:(携带数据:可以拼到url上---->从GET中取,) ...