[代码实例][C++]分析C程序源文件(不完善)

#define TEMP	1	/*ABCDEFG*/			

#include <cstdlib>

#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <sstream>

using namespace std;

#if (TEMP==1)

// Macro definition
#define MACRO		0
#define MACROFUN	1
#define STRUCTURE	2
#define DATATYPE	3
#define VARIABLE	4
#define FUNCTION	5
#define STATICFUN	6
#define EXTERNFUN	7
#define TYPE_COUNT	8

// Macro function definition
#define MAX(x, y)	(if((x) >= (y)) ? (x) : (y))

// Structure definition
typedef struct MyStruct
{
	int field1;
	int field2;
} MyType;

// Variable definition
int myInteger1 = 123;
extern int myInteger2;

void fun(void)
{

}

static void staticFun(void)
{

}

extern void externFun(void)
{

}

#endif // (TEMP==1)

map<int, string>* fileLineMap = nullptr;

// 判断字符串1是不是以字符串2开始
bool startWith(string str1, string str2)
{
	return str1.compare(0, str2.length(), str2) == 0;
}

// 获取指定行序号(从0开始的)之前,并且紧临的注释
// 从后往前,逐行扫描“//”或被“/*”“*/”包含的行
string getComment(map<int, string>* codeLineMap, size_t index)
{
	string comment;
	size_t i = index - 1;
	bool isCommentInner = false;
	bool isCommentEnd = false;
	size_t pos;

	do
	{
		if ((*codeLineMap)[i].find_first_not_of(" \n") == string::npos)
		{
			break;
		}

		while (!isCommentInner && (pos = (*codeLineMap)[i].find("//")) != string::npos)
		{
			i--;
		}

		if ((*codeLineMap)[i].find_first_not_of(" \n") == string::npos)
		{
			break;
		}

		while ((*codeLineMap)[i].find("*/") != string::npos)
		{
			isCommentInner = true;
			i--;

			do
			{
				if ((*codeLineMap)[i].find("/*") != string::npos)
				{
					isCommentInner = false;
				}
				i--;
			} while (isCommentInner);
		}
	} while ((!isCommentInner && (*codeLineMap)[i].find("//") != string::npos)
		|| (*codeLineMap)[i].find("*/") != string::npos);

	for (int j = i + 1; j < index; j++)
	{
		comment.append((*codeLineMap)[j]);
	}

	return comment;
}

// 获取宏定义
// 如果某一行以“#define ”开始,但并不包含“(”,则为宏定义
list<pair<string, string>>* getMacro(map<int, string>* codeLineMap)
{
	list<pair<string, string>>* macroList = new list<pair<string, string>>();

	for (map<int, string>::iterator itor = codeLineMap->begin(); itor != codeLineMap->end(); itor++)
	{
		if (startWith(itor->second, "#define ") && itor->second.find_first_of("(") == string::npos)
		{
			string name;
			for (size_t i = 8; i < itor->second.length(); i++)
			{
				if (itor->second[i] == ' ' || itor->second[i] == '\n')
				{
					break;
				}
				else
				{
					name.push_back(itor->second[i]);
				}
			}

			macroList->push_back(make_pair(name, getComment(fileLineMap, itor->first) + fileLineMap->at(itor->first)));
		}
	}

	return macroList;
}

// 获取宏函数定义
// 如果某一行以“#define ”开始,但并包含“(”,则为宏函数定义
list<pair<string, string>>* getMacroFunc(map<int, string>* codeLineMap)
{
	list<pair<string, string>>* macroFuncList = new list<pair<string, string>>();

	for (map<int, string>::iterator itor = codeLineMap->begin(); itor != codeLineMap->end(); itor++)
	{
		if (startWith(itor->second, "#define ") && itor->second.find_first_of("(") != string::npos)
		{
			string name;
			for (size_t i = 8; i < itor->second.length(); i++)
			{
				if (itor->second[i] == '(')
				{
					break;
				}
				else
				{
					name.push_back(itor->second[i]);
				}
			}

			macroFuncList->push_back(make_pair(name, getComment(fileLineMap, itor->first) + fileLineMap->at(itor->first)));
		}
	}

	return macroFuncList;
}

// 获取全局变量定义
// 对于某一行,需要排除宏(或宏函数)(以#define开始)、数据类型(以typedef struct开始)、函数(包含括号)
// 同时还要排除这一行在代码块中
// 排除这些情况,基本可认定这就是一个全局变量。
list<pair<string, string>>* getVariable(map<int, string>* codeLineMap)
{
	list<pair<string, string>>* variableList = new list<pair<string, string>>();

	int count = 0;
	bool isStringInner = false;
	for (map<int, string>::iterator itor = codeLineMap->begin(); itor != codeLineMap->end(); itor++)
	{
		if (itor->first == 325)
		{
			int kkk = 0;
			kkk++;
		}

		string line = itor->second;
		if (line.length() > 0)
		{
			line.erase(line.length() - 1, 1);
		}

		for (int i = 0; i < line.length(); i++)
		{
			if (line[i] == '\"' && !isStringInner)
			{
				isStringInner = true;
			}
			else if (line[i] == '\"' && isStringInner)
			{
				isStringInner = false;
			}
			if ((line[i] == '\'' && line[i + 1] == '{' && line[i + 2] == '\'')
				|| (line[i] == '\'' && line[i + 1] == '}' && line[i + 2] == '\''))
			{
				i += 2;
			}
			else if (line[i] == '{' && !isStringInner)
			{
				count++;
			}
			else if (line[i] == '}' && !isStringInner)
			{
				count--;
			}
		}


		if (!startWith(line, "#define ") && !startWith(line, "typedef struct")
			&& line.find("using ") == string::npos
			&& line.find_first_of(";") != string::npos && count == 0
			&& line.find_first_of("(") == string::npos && line.find_first_of(")") == string::npos
			&& line.find_first_of("{") == string::npos && line.find_first_of("}") == string::npos
			&& line.find("extern ") == string::npos)
		{
			string name;
			size_t pos;

			pos = line.find_first_of("=");
			if (pos != string::npos)
			{
				if (line[--pos] == ' ')
				{
					pos--;
				}
			}
			else
			{
				pos = line.find_first_of(";");
				pos--;
			}

			do
			{
				name.push_back(line[pos]);
			} while (line[--pos] != ' ');
			reverse(name.begin(), name.end());

			variableList->push_back(make_pair(name, getComment(fileLineMap, itor->first) + fileLineMap->at(itor->first)));
		}
	}

	return variableList;
}

// 获取全局变量定义
// 对于某一行,需要排除宏(或宏函数)(以#define开始)、数据类型(以typedef struct开始)
// 排除这些情况,同时满足包含括号,基本可认定这就是一个函数。
void getFunction(map<int, string>* codeLineMap, list<pair<string, string>>* functionList, list<pair<string, string>>* staticFunctionList, list<pair<string, string>>* externFunctionList)
{
	int count = 0;
	for (map<int, string>::iterator itor = codeLineMap->begin(); itor != codeLineMap->end();)
	{
		string line = itor->second;

		if (!startWith(line, "#define ") && !startWith(line, "typedef struct")
			&& line.find("using ") == string::npos && line.find("=") == string::npos && line.find(";") == string::npos
			&& line.find_first_of("(") != string::npos
			&& count == 0)
		{
			string name;
			size_t pos;

			pos = line.find_first_of("(");
			if (line[--pos] == ' ')
			{
				pos--;
			}

			do
			{
				name.push_back(line[pos]);
			} while (line[--pos] != ' ');
			reverse(name.begin(), name.end());

			bool hasBodyInner = false;
			string code;
			map<int, string>::iterator itor_temp;
			for (itor_temp = itor; itor_temp != codeLineMap->end(); itor_temp++)
			{
				for (int i = 0; i < itor_temp->second.length(); i++)
				{
					if ((itor_temp->second[i] == '\'' && itor_temp->second[i + 1] == '{' && itor_temp->second[i + 2] == '\'')
						|| (itor_temp->second[i] == '\'' && itor_temp->second[i + 1] == '}' && itor_temp->second[i + 2] == '\''))
					{
						i += 2;
					}
					else if (itor_temp->second[i] == '{')
					{
						count++;
						hasBodyInner = true;
					}
					else if (itor_temp->second[i] == '}')
					{
						count--;
					}
				}

				code.append(fileLineMap->at(itor_temp->first));

				if (hasBodyInner && count == 0)
				{
					break;
				}
			}

			if (line.find("extern ") == string::npos && line.find("static ") == string::npos)
			{
				functionList->push_back(make_pair(name, getComment(fileLineMap, itor->first) + code));
			}
			else if (line.find("static ") != string::npos)
			{
				staticFunctionList->push_back(make_pair(name, getComment(fileLineMap, itor->first) + code));
			}
			else if (line.find("extern ") != string::npos)
			{
				externFunctionList->push_back(make_pair(name, getComment(fileLineMap, itor->first) + code));
			}

			itor = itor_temp;
			if (itor->second[itor->second.length() - 1] == '\n')
			{
				itor++;
			}
		}

		itor++;
	}
}

// 获取宏定义
// 如果某一行以“typedef struct”开始,则为数据类型
list<pair<string, string>>* getDatatype(map<int, string>* codeLineMap)
{
	list<pair<string, string>>* datatypeList = new list<pair<string, string>>();

	int count = 0;
	for (map<int, string>::iterator itor = codeLineMap->begin(); itor != codeLineMap->end();)
	{
		string line = itor->second;

		if (startWith(line, "typedef struct")
			&& line.find("using ") == string::npos && line.find("=") == string::npos && line.find(";") == string::npos
			&& count == 0)
		{
			string name;
			bool hasBodyInner = false;
			string code;
			map<int, string>::iterator itor_temp;
			for (itor_temp = itor; itor_temp != codeLineMap->end(); itor_temp++)
			{
				for (int i = 0; i < itor_temp->second.length(); i++)
				{
					if (itor_temp->second[i] == '{')
					{
						count++;
						hasBodyInner = true;
					}
					else if (itor_temp->second[i] == '}')
					{
						count--;
					}
				}

				code.append(fileLineMap->at(itor_temp->first));

				if (hasBodyInner && count == 0)
				{
					size_t pos = itor_temp->second.find_last_of("}") + 1;
					while (itor_temp->second[pos] == ' ')
					{
						pos++;
					}
					for (size_t i = pos; i < itor_temp->second.length(); i++)
					{
						if (itor_temp->second[i] == ';' || itor_temp->second[i] == ' ' || itor_temp->second[i] == '\n')
						{
							break;
						}

						name.push_back(itor_temp->second[i]);
					}

					break;
				}
			}

			datatypeList->push_back(make_pair(name, getComment(fileLineMap, itor->first) + code));

			itor = itor_temp;
			if (itor->second[itor->second.length() - 1] == '\n')
			{
				itor++;
			}
		}

		itor++;
	}

	return datatypeList;
}

// 去除空白
void eraseWhite(map<int, string>* codeLineMap)
{
	for (map<int, string>::iterator itor = codeLineMap->begin(); itor != codeLineMap->end(); itor++)
	{
		size_t pos;

		// 替换制表符为空格
		while ((pos = itor->second.find_first_of("\t")) != string::npos)
		{
			itor->second.replace(pos, 1, " ");
		}

		// 合并两个连续的空格为一个空格
		while ((pos = itor->second.find("  ")) != string::npos)
		{
			itor->second.replace(pos, 2, " ");
		}

		// 去除开始的空格
		itor->second.erase(0, itor->second.find_first_not_of(" "));

		// 去除结尾的空格
		if (itor->second.length() >= 2 && itor->second[itor->second.length() - 2] == ' ')
		{
			itor->second.erase(itor->second.length() - 2, 1);
		}

		// 去除分号的空格
		if (itor->second.find(" ;") != string::npos)
		{
			itor->second.erase(itor->second.find(" ;"), 1);
		}
	}
}

// 去除注释
void eraseComment(map<int, string>* codeLineMap)
{
	bool isCommentInner = false;
	bool isStringInner = false;
	for (map<int, string>::iterator itor = codeLineMap->begin(); itor != codeLineMap->end(); itor++)
	{
		for (size_t i = 0; i < itor->second.length();)
		{
			if (itor->second[i] == '/' && i < itor->second.length() && itor->second[i + 1] == '*')
			{
				if (!isStringInner)
				{
					isCommentInner = true;
					itor->second.erase(i, 2);
				}
				else
				{
					i += 2;
				}
			}
			else if (itor->second[i] == '*' && i < itor->second.length() && itor->second[i + 1] == '/')
			{
				if (!isStringInner)
				{
					isCommentInner = false;
					itor->second.erase(i, 2);
				}
				else
				{
					i += 2;
				}
			}
			else if (isCommentInner)
			{
				itor->second.erase(i, 1);
			}
			else if (itor->second[i] == '\\' && i < itor->second.length() && itor->second[i + 1] == '\"')
			{
				i += 2;
			}
			else if (itor->second[i] == '\"')
			{
				isStringInner = !isStringInner;
				i++;
			}
			else if (itor->second[i] == '/' && i < itor->second.length() && itor->second[i + 1] == '/')
			{
				if (!isStringInner)
				{
					itor->second.erase(i, itor->second.length() - 1);
				}
				else
				{
					i += 2;
				}
			}
			else
			{
				i++;
			}
		}
	}
}

map<int, string>* dealWithCodeLineList(map<int, string>* fileLineMap)
{
	map<int, string>* codeLineMap = new map<int, string>();
	for (map<int, string>::iterator itor = fileLineMap->begin(); itor != fileLineMap->end(); itor++)
	{
		codeLineMap->insert(make_pair(itor->first, itor->second));
	}

	eraseComment(codeLineMap);
	eraseWhite(codeLineMap);

	return codeLineMap;
}

map<int, string>* readFile(string srcFileName)
{
	map<int, string>* fileLineMap = new map<int, string>();

	ifstream ifstream(srcFileName);
	ostringstream buf;
	char ch;
	int i = 0;
	while (ifstream.get(ch))
	{
		// 首先得排除BOM(EF BB BF)三个字节的情况
		if (ch == (char)0xEF || ch == (char)0xBB || ch == (char)0xBF)
			continue;

		if (ch != '\n')
		{
			buf.put(ch);
			continue;
		}

		buf.put('\n');
		fileLineMap->insert(make_pair(i++, buf.str()));
		buf.str("");
	}

	if (buf.str().length() >= 0)
	{
		fileLineMap->insert(make_pair(i, buf.str()));
	}

	return fileLineMap;
}

int main()
{
	try
	{
#if (TEMP==1)
		string srcFileName = "D:\\Project\\VisualStudio\\CPlusPlus\\SrcAnalysis\\SrcAnalysis\\SrcAnalysis.cpp";
		//string srcFileName = "D:\\Project\\VisualStudio\\CPlusPlus\\SrcAnalysis\\SrcAnalysis\\test_code.c";
		string outputFileName_1 = "D:\\Project\\VisualStudio\\CPlusPlus\\SrcAnalysis\\Debug\\output1.txt";
		string outputFileName_2 = "D:\\Project\\VisualStudio\\CPlusPlus\\SrcAnalysis\\Debug\\output2.txt";
#else
		string srcFileName;
		cin >> srcFileName;
		string outputFileName_1;
		string outputFileName_2;
		cin >> outputFileName_1;
		cin >> outputFileName_2;
#endif // (TEMP==1)

		fileLineMap = readFile(srcFileName);

		ofstream ofstream1(outputFileName_1);
		ofstream ofstream2(outputFileName_2);

		map<int, string>* codeLineMap = dealWithCodeLineList(fileLineMap);

		list<pair<string, string>>* macroList = getMacro(codeLineMap);
		cout << "***** Macro *****" << endl;
		ofstream1 << "***** Macro *****" << endl;
		for (list<pair<string, string>>::iterator itor = macroList->begin(); itor != macroList->end(); itor++)
		{
			cout << "[" << itor->first << "] => " << endl << itor->second << endl;
			ofstream1 << "[" << itor->first << "] => " << endl << itor->second << endl;
		}

		list<pair<string, string>>* macroFuncList = getMacroFunc(codeLineMap);
		cout << "***** Macro Function *****" << endl;
		ofstream1 << "***** Macro Function *****" << endl;
		for (list<pair<string, string>>::iterator itor = macroFuncList->begin(); itor != macroFuncList->end(); itor++)
		{
			cout << "[" << itor->first << "] => " << endl << itor->second << endl;
			ofstream1 << "[" << itor->first << "] => " << endl << itor->second << endl;
		}

		list<pair<string, string>>* variableList = getVariable(codeLineMap);
		cout << "***** Variable *****" << endl;
		ofstream1 << "***** Variable *****" << endl;
		for (list<pair<string, string>>::iterator itor = variableList->begin(); itor != variableList->end(); itor++)
		{
			cout << "[" << itor->first << "] => " << endl << itor->second << endl;
			ofstream1 << "[" << itor->first << "] => " << endl << itor->second << endl;
		}

		list<pair<string, string>>* datatypeList = getDatatype(codeLineMap);
		cout << "***** Datatype *****" << endl;
		ofstream1 << "***** Datatype *****" << endl;
		for (list<pair<string, string>>::iterator itor = datatypeList->begin(); itor != datatypeList->end(); itor++)
		{
			cout << "[" << itor->first << "] => " << endl << itor->second << endl;
			ofstream1 << "[" << itor->first << "] => " << endl << itor->second << endl;
		}

		list<pair<string, string>>* functionList = new list<pair<string, string>>();
		list<pair<string, string>>* staticFunctionList = new list<pair<string, string>>();
		list<pair<string, string>>* externFunctionList = new list<pair<string, string>>();
		getFunction(codeLineMap, functionList, staticFunctionList, externFunctionList);
		cout << "***** Static Function *****" << endl;
		ofstream2 << "***** Static Function *****" << endl;
		for (list<pair<string, string>>::reverse_iterator itor = staticFunctionList->rbegin(); itor != staticFunctionList->rend(); itor++)
		{
			cout << "[" << itor->first << "] => " << endl << itor->second << endl;
			ofstream2 << "[" << itor->first << "] => " << endl << itor->second << endl;
		}
		cout << "***** Extern Function *****" << endl;
		ofstream2 << "***** Extern Function *****" << endl;
		for (list<pair<string, string>>::reverse_iterator itor = externFunctionList->rbegin(); itor != externFunctionList->rend(); itor++)
		{
			cout << "[" << itor->first << "] => " << endl << itor->second << endl;
			ofstream2 << "[" << itor->first << "] => " << endl << itor->second << endl;
		}
		cout << "***** Function *****" << endl;
		ofstream2 << "***** Function *****" << endl;
		for (list<pair<string, string>>::reverse_iterator itor = functionList->rbegin(); itor != functionList->rend(); itor++)
		{
			cout << "[" << itor->first << "] => " << endl << itor->second << endl;
			ofstream2 << "[" << itor->first << "] => " << endl << itor->second << endl;
		}
	}
	catch (const std::exception& ex)
	{
		cerr << endl << "[ERROR] " << ex.what() << endl;
	}

	return EXIT_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值