比较两个头文件是否相同

python3.6, windows下

需求:

有一个新的版本的include目录中有一些头文件被更改(内容有修改,内容没有修改但位置有变更)

用Compare工具不能很好的比较出头文件中内容位置变更的文件,此时用python可以进行比较

实现:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os,re,shutil,sys

src_dir = 'C:\\Users\\Administrator\\Desktop\\tmp\\1'
dest_dir ='C:\\Users\\Administrator\\Desktop\\tmp\\2'
res_file = 'C:\\Users\\Administrator\\Desktop\\tmp\\diff.txt'

def ListAllFile(dir):
	"""
	返回目录下所有的文件名
    :param data: dir 文件夹
    :return	所有文件
	"""
	files=[]
	list = os.listdir(dir)
	for i in range(0, len(list)):
		path = os.path.join(dir, list[i])
		if os.path.isdir(path):
			files.extend(ListAllFile(path))
		elif os.path.isfile(path) and path.endswith('.h'):
			files.append(path)
	return files
	
def InitHeaderFile(filename):
	"""
    针对头文件中有嵌套类,将一个class看做一个层级,嵌套类属于下一个层级
	#include<> 层级0,
	class A { 层级1,
		xxxA
		class B{层级2,
			xxxB
		};
		class C{层级2
			xxxc
		};
	};
    :param data: filename 头文件名
    :return dict字典 "0":["#include<>"], "1":["class A {", "};"]
    """
	try:
		with open(filename) as f:
			lines = f.readlines()
			i = 0
			dict = {}
			
			for line in lines:
				line = line.strip()
				class_end = False
				
				if line == '':
					continue
				
				if line.endswith('{'):
					i = i + 1
				elif line.startswith('}'):
					i = i - 1
					class_end = True
				
				if i not in dict:
					tmp = []
					tmp.append(line)
					dict[i] = tmp
				else:
					if not class_end:
						dict[i].append(line)
					else:
						dict[i+1].append(line)
			return dict
	except Exception:
		raise RuntimeError('open [%s] failed'% filename)
	
def CheckHeaderSame1(src_dict, dest_dict):
	'''
	该函数针对头文件中的类存在嵌套类,且类的格式如下:
	class Test { // 类的开头行以'{'结尾
		xxx		
		void func{
		}	类中如果有函数实现,也必须是函数声明行以'{'结尾,函数结束以'}'开头
		
	}; // 类的结尾行以'}'开头
	
	:param data: src_dict, dest_dict 经过InitHeaderFile得到的字典
	:return 返回比较结果
	'''	
	for k, v in src_dict.items():
		if k not in dest_dict:
			return False
		
		for line in v:
			if line not in dest_dict[k]:
				return False
	return True

def CheckHeaderSame2(src_file, dest_file):
	'''
	该函数针对头文件中除空行外不存在相同行的情况
	
	:param data:src_file,dest_file要比较的头文件
	:return 返回比较结果
	'''	
	src_lines = {}
	dest_lines = {}
	
	try:
		with open(src_file, 'r') as f:
			for line in f:
				src_lines[line.strip()] = None
	except Exception:
            raise RuntimeError('open [%s] failed'% src_file)
			
	try:
		with open(dest_file, 'r') as f:
			for line in f:
				dest_lines[line.strip()] = None
	except Exception:
            raise RuntimeError('open [%s] failed'% dest_file)
			
	for key in src_lines:
		if key not in dest_lines:
			return False
			
	return True
if __name__ == "__main__":
	src_files = ListAllFile(src_dir)
	dest_files = ListAllFile(dest_dir)
	
	diff_files = []
	

	for src_file in src_files:
		raw_file = src_file.split('\\')[-1]
		
		for dest_file in dest_files:
			if dest_file.split('\\')[-1] == raw_file:
				src_dict = InitHeaderFile(src_file)
				dest_dict = InitHeaderFile(dest_file)
				
				if not CheckHeaderSame1(src_dict, dest_dict):
					diff_files.append(src_file)
					print('Different file: ' + src_file)
				else:
					print('Same file: ' + src_file)
			
	try:
		with open(res_file, 'a+') as f:
			for file in diff_files:
				f.write(src_file)
				f.write('\n')
	except Exception:
		raise RuntimeError('open [%s] failed'% res_file)

执行结果:

比较结果会保存到diff.txt中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C、传统 C++ #include <assert.h>    //设定插入点 #include <ctype.h>     //字符处理 #include <errno.h>     //定义错误码 #include <float.h>     //浮点数处理 #include <fstream.h>    //文件输入/输出 #include <iomanip.h>    //参数化输入/输出 #include <iostream.h>   //数据流输入/输出 #include <limits.h>    //定义各种数据型最值常量 #include <locale.h>    //定义本地化函数 #include <math.h>     //定义数学函数 #include <stdio.h>     //定义输入/输出函数 #include <stdlib.h>    //定义杂项函数及内存分配函数 #include <string.h>    //字符串处理 #include <strstrea.h>   //基于数组的输入/输出 #include <time.h>     //定义关于时间的函数 #include <wchar.h>     //宽字符处理及输入/输出 #include <wctype.h>    //宽字符分 ////////////////////////////////////////////////////////////////////////// 标准 C++ (同上的不再注释) #include <algorithm>    //STL 通用算法 #include <bitset>     //STL 位集容器 #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex>     //复数 #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque>      //STL 双端队列容器 #include <exception>    //异常处理 #include <fstream> #include <functional>   //STL 定义运算函数(代替运算符) #include <limits> #include <list>      //STL 线性列表容器 #include <map>       //STL 映射容器 #include <iomanip> #include <ios>       //基本输入/输出支持 #include <iosfwd>     //输入/输出系统使用的前置声明 #include <iostream> #include <istream>     //基本输入流 #include <ostream>     //基本输出流 #include <queue>      //STL 队列容器 #include <set>       //STL 集合容器 #include <sstream>     //基于字符串的流 #include <stack>      //STL 堆栈容器     #include <stdexcept>    //标准异常 #include <streambuf>    //底层输入/输出支持 #include <string>     //字符串 #include <utility>     //STL 通用模板 #include <vector>     //STL 动态数组容器 #include <cwchar> #include <cwctype> using namespace std; ////////////////////////////////////////////////////////////////////////// C99 增加 #include <complex.h>   //复数处理 #include <fenv.h>    //浮点环境 #include <inttypes.h>  //整数格式转换 #include <stdbool.h>   //布尔环境 #include <stdint.h>   //整型环境 #include <tgmath.h>   //通用型数学宏 --------------------------------------------------------------------------------------------------------- 补充: 经常在CSDN以及其他之的技术论坛上问关于C++ 头文件的问题。提出这些问题的往往就是那些刚学C++的新手。当初我是菜鸟的时候也问过似的问题。 现在来看看下面两个include: #include<iostream> // 这个就是1998年标准化以后的标准头文件 #include<iostream.h> // 这个就是标准化以前的头文件 更本质上的区别就是iostream把标准C++库的组件放在一个名位std的namespace里面。而相对的iostream.h则将这些标准组件放在全局空间里,同时在标准化以后旧有的C标准库也已经经过改造了。 看看下面这两个头文件 // 标准化后经过改造的C的标准库,所有的组件都放在了std中 #include<cstdio> // 标准化以前C++中的C标准库 #include<stdio.h> // 在看看这个头文件C标准库下 基于char* 的字符处理函数库 #include<string.h> // 在标准化以后他变成了这样 #include<cstring> // 但是很多朋友还看见过这个字符串处理函数库,他包含了新的string class #include<string> 经过了标准委员会如此大规模手术后,在98年以前出品的C++编译器(BC3.0,BC5.0)上能顺利通过编译的源文件,在支持新标准的编译器上可能无法顺利通过编译也就是很正常的事了。 [起因] 在回过头来看看标准程序库,这个程序库涵盖范围相当广大,提过了许许多多好用的功能。正是因为这样标准程序库中class的名称和函数名与第三方提供的程序库中的class名或是函数名发生名字冲突的可能性大大增大。为了避免这个问题的发生,标准委员会决定将标准程序库中每一样东西都放在namespace std中。但是这么做同时有引来了一个新的问题。很多C++程序代码依赖那些已经存在很多年的C++ “准”标准程序库(C++迟迟未标准化才导致这些情况的发生),例如iosteam.h,complex.h等等。 为了解决这个新出现的问题,标准化委员会决定设计一些新的头文件名,给那些穿上std外衣的组件所使用。把C++头文件的.h去掉,于是就有前面出现的iostream,同样C的头文件也做了相同的处理,同时在前面加上了一个字母c,以表示是C的头文件(感觉上有中种族歧视的感觉)。同时标准化委员会声明就有的C++头文件将不再列于被支持的名单之中了,而旧有的C头文件为了满足“对C的兼容性”这个古老契约,仍然将继续存活下去。 但是,那些编译器厂商不可能去推翻他们客户的旧有编译器(也跟本不会去这么做),所以那些旧有的C++头文件仍然苟延残喘的活了下来,并不断的扰乱那些C++新兵的心智。 下面就是现在大多数C++开发工具表示头文件的组织状态: 1. 旧的C++头文件 比如iostream.h,他们虽然被标准化委员会所抛弃,但由于各大厂商为了各自的商业利益仍然将继续存活下去,这些头文件的内容将不处于namespace std中。 2. 新的C++头文件如iostream虽然提供了和旧有头文件相同的功能,但他的内容都并入了namespace std中,从而有效避免了名字污染的问题。 3. 标准C的头文件如stdio.h继续获得支持,这文件的内容并未放在std中。 4. C函数库的技能也有对应的新式C++版本,起名称似cstdio,这头文件的内容也有幸穿上了std的外衣。 其实标准化以后的标准程序库的改动并不只有这些而已,很多的标准化组件都被“tamplate化”。其中就有元老级人物iostream。标准程序库的问题并不是用一篇,两篇文章就可以说清楚的。如果你像进一步的了解C++的标准程序库的话,你可以看看侯先生的《C++标准程序库》。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值