c++源代码的函数识别

[日常] C++如何使用字符串获取函数 最近有朋友问我,C++ 里怎么实现用 string 取函数,因为要实现一个 server,根据送来报文里的类型字段选择合适的函数处理。答案是使用函数指针,或者使用 std::function 封装过的函数指针。注意,此时要求所有函数的签名类型是一样的,包括参数和返回值,因为这样编译器才能确定函数调用时的参数入栈顺序等。 如果各个函数长的不一样,请使用switch-case语句手动调用。... 阅读详情

 

仿照上一篇的方法写了个识别函数的程序,可以识别出函数名和起始终止行数。

状态表:


e是error,代码能编译过的话这种情况是不会出现的,程序中用0代替了。
7状态在函数体内,计数{和},当计数到0时,说明遇到了函数的最后半个},即函数结束,进入0状态。

源代码:
#include "stdio.h"
#include "string"
#include <list>
char fsm_RemoveComment[9][128];
char fsm_FindFunction[11][128];
void initfsm()
{
 const int line_len=sizeof(char)*128;
 memset(fsm_RemoveComment[0],0,line_len);
 memset(fsm_RemoveComment[1],0,line_len);
 memset(fsm_RemoveComment[2],2,line_len);
 memset(fsm_RemoveComment[3],3,line_len);
 memset(fsm_RemoveComment[4],3,line_len);
 memset(fsm_RemoveComment[5],5,line_len);
 memset(fsm_RemoveComment[6],5,line_len);
 memset(fsm_RemoveComment[7],0,line_len);
 memset(fsm_RemoveComment[8],0,line_len);
 fsm_RemoveComment[0]['/']=1;
 fsm_RemoveComment[0]['"']=5;
 fsm_RemoveComment[1]['/']=2;
 fsm_RemoveComment[1]['*']=3;
 fsm_RemoveComment[1]['"']=5;
 fsm_RemoveComment[2]['\n']=7;
 fsm_RemoveComment[3]['*']=4;
 fsm_RemoveComment[4]['/']=7;
 fsm_RemoveComment[4]['*']=4;
 fsm_RemoveComment[5]['"']=0;
 fsm_RemoveComment[5]['\\']=6;
 fsm_RemoveComment[7]['/']=1;
 fsm_RemoveComment[7]['"']=5;
 fsm_RemoveComment[0]['\\']=8;

memset(fsm_FindFunction[0],0,line_len);
 memset(fsm_FindFunction[1],2,line_len);
 memset(fsm_FindFunction[2],2,line_len);
 memset(fsm_FindFunction[3],3,line_len);
 memset(fsm_FindFunction[4],4,line_len);
 memset(fsm_FindFunction[5],5,line_len);
 memset(fsm_FindFunction[6],1,line_len);
 memset(fsm_FindFunction[7],7,line_len);
 memset(fsm_FindFunction[8],5,line_len);
 memset(fsm_FindFunction[9],9,line_len);
 memset(fsm_FindFunction[10],9,line_len);

fsm_FindFunction[0]['\n']=1;
 fsm_FindFunction[0][' ']=1;

fsm_FindFunction[0]['\t']=1; //原作者没有添加对制表符的识别导致以制表符开头的函数无法识别
 fsm_FindFunction[0]['}']=1;
 fsm_FindFunction[0][';']=1;

fsm_FindFunction[1]['(']=4;
 fsm_FindFunction[1][' ']=1;

fsm_FindFunction[1]['\t']=1; //同上
 fsm_FindFunction[1]['\n']=1;

fsm_FindFunction[2][';']=0;
 fsm_FindFunction[2][')']=0;
 fsm_FindFunction[2]['(']=4;
 fsm_FindFunction[2][',']=0;
 fsm_FindFunction[2]['{']=0;
 fsm_FindFunction[2]['}']=0;
 fsm_FindFunction[2][' ']=1;

fsm_FindFunction[2]['\t]=1; //同上
 fsm_FindFunction[2]['\n']=1;

fsm_FindFunction[3][';']=0;
 fsm_FindFunction[3]['{']=7;
 fsm_FindFunction[3]['}']=0;

fsm_FindFunction[4][';']=0;
 fsm_FindFunction[4][')']=6;
 fsm_FindFunction[4]['(']=0;
 fsm_FindFunction[4]['{']=0;
 fsm_FindFunction[4]['}']=0;

fsm_FindFunction[5]['"']=7;
 fsm_FindFunction[5]['\\']=8;

fsm_FindFunction[6]['\n']=6;
 fsm_FindFunction[6]['{']=7;
 fsm_FindFunction[6][' ']=6;

fsm_FindFunction[6]['\t']=6; //同上
 fsm_FindFunction[6][':']=3;

fsm_FindFunction[7]['\'']=9;
 fsm_FindFunction[7]['"']=5;

fsm_FindFunction[9]['\'']=7;
 fsm_FindFunction[9]['\\']=10;
}

bool RemoveComment(const std::string& Filename,char* &co,int &nLength)
{
 FILE *myfile=fopen(Filename.c_str(),"r");
 if (!myfile)
 {
 printf("can't open file.\n");
 return false;
 }
 fseek(myfile, 0, SEEK_END);
 nLength=ftell(myfile);
 fseek(myfile,0,SEEK_SET);

co=new char[nLength];

char c;
 std::string s;
 int state=0;
 int i=0;
 while (fscanf(myfile,"%c",&c)!=EOF)
 {
 state=fsm_RemoveComment[state][c];
 s+=c;
 switch(state)
 {
 case 0:
 memcpy(co+i,s.c_str(),s.length());
 i+=s.length();
 s="";
 break;
 case 7:
 s="";
 if(c=='\n'){
 co[i]=c;
 i++;
 }
 break;
 case 1:
 case 2:
 case 3:
 case 4:
 case 6:
 case 8:
 if ('\n'==c)
 {
 co[i]=c;
 i++;
 }
 break;
 }
 }
 fclose(myfile);
 nLength=i+1;
 return true;
}
struct FuncList_t
{
 std::string name;
 int nStartLine;
 int nEndLine;
};
bool FindFunc(const std::string& Filename, std::list<FuncList_t>& listFunc)
{
 //remove comment
 char *co=NULL;
 int nLength=0;
 if (!RemoveComment(Filename,co,nLength)){
 return false;
 }

//find functions
 FuncList_t st;
 int nLine=0;
 int state=0;
 int nLastState=0;
 int nBracket=0;
 int i=0;
 std::string s;
 for (;i<nLength;i++){
 char c=co[i];
 state=fsm_FindFunction[state][c];
 if (c=='\n'){
 nLine++;
 }

switch(state){
 case 2:
 if (nLastState==1){
 s="";
 }
 s+=c;
 break;
 case 7:
 if (6==nLastState||3==nLastState){
 st.name=s;
 st.nStartLine=nLine;
 s="";
 }
 if (c=='{'){
 nBracket++;
 }
 if ('}'==c){
 nBracket--;
 }
 if (0==nBracket){
 st.nEndLine=nLine+1;
 listFunc.push_back(st);
 state=0;
 }
 break;
 }
 nLastState=state;
 }
 delete []co;
 return true;
}

int main()
{
 initfsm();
 std::list<FuncList_t> listFunc;
 FindFunc("G:\\projects\\vc\\removeCppComment\\removeCppComment.cpp",listFunc);
 FILE *file=fopen("C:\\1.txt","w");
 std::list<FuncList_t>::iterator itFunc=listFunc.begin();
 for (;itFunc!=listFunc.end();itFunc++){
 fprintf(file,"%s: %d-%d\n",itFunc->name.c_str(),itFunc->nStartLine,itFunc->nEndLine);
 }
 fclose(file);
 system("C:\\1.txt");
 return 0;
}

用它自己这个cpp试验的运行结果:
initfsm: 6-86
RemoveComment: 88-141
FindFunc: 148-202
main: 204-217

C/C++函数调用分析 本文分析了C/C++的函数调用过程 阅读详情

相关推荐

如何让GCCE编译.cc后缀的源代码文件

总所周知,c++的实现文件的后缀多种多样,通常有:.cpp, .cc, .cxx, .c++等。其中.cpp最为常见。在Symbian环境下(OpenC/C++)可以顺利编译.cpp的代码,而在编译.cc文件时就不好使了(会产生一些莫名其妙的问题)。这只是一个文件后缀识别问题,以前我的解决方法是把.cc修改为.cpp。刚才在浏览一个帖子时,看到Forum Nokia Expert(jhnwkmn)

dyw的专栏 2614

一种快速在 C/C++源码中查找类名/函数名的方式

vim 和 ctags ctrl + t ctrl + ] -t -c 参考 Setting a vim option from the command line?

IWSDAB的博客 966

Opencv源代码分析HoughLines

一个有毅力的知识搬运工的第二天搬运: 霍夫变换是一种特征提取技术。经典的霍夫变换能够识别出图像中的直线,后来又发展到能够识别出任意形状,但更常见的识别形状是圆和椭圆。函数HoughLines的作用就是能够检测出边缘图像中的直线。 在直角坐标系下,直线被定义为: y = mx + b         (1) 其中,m为斜率,b为与y轴的截距,只要确定了m和b,一条直线就可

qq_19833853的博客 1671

C/C++常用头文件及函数汇总

C/C++头文件一览 C #include     //设定插入点 #include      //字符处理 #include      //定义错误码 #include      //浮点数处理 #include         //对应各种运算符的宏 #include     //定义各种数据类型最值的常量 #include     //定义本地化C函数 #include

thisispan 7万+

2024年“深圳杯”数学建模挑战赛C题-编译器版本的识别问题 思路、代码、论文

随着程序设计语言的不断变化,编译器也会不断更新。为方便使用电子计算机,人们需首先按照一定的规则(即程序设计语言)将需要电子计算机完成的指令以特定的顺序集成在一起,形成脚本(即程序),然后使用编译器自动将脚本翻译为一系列机器语言的组合(即编译),编译器的编译结果最后会提交电子计算机执行。用GCC中不同版本的C++编译器编译附件2中的源程序代码[3],给出直接使用问题2中得到的判别函数区分编译器区版本的结果。使用GCC中不同版本的C++编译器编译附件1中的程序源代码[2],并对比使用默认编译选项时的编译结果。

YOLO 394

CodeBuddy 接入 MCP,一键生成网站!

2024 年 11 月,Anthropic 公司搞了个挺有意思的新玩意 - Model Context Protocol(模型上下文协议)简称为 MCP 协议。简单来说,它就是给 AI 和各类工具数据之间搭了个标准化的”桥梁”,让开发者不用再为对接问题头疼了。mcp.so如下图所示,这是 mcp.so 网站中的 MCP Server。使用百度/高德地图分析旅线计算时间接 Puppeteer 自动操作网页使用 Github/Gitlab 让大模型接管代码仓库。

悟空聊架构的专栏 1946

C++及C语言 头文件函数(第一弹)

C++及C语言 头文件函数(第一弹) —字符判断 特别说明:以下"判断"皆为是则为非0值,不是则为0 1.bool isalpha (char x) 判断一个字符是否为字母(a−z,A−Z)(a-z,A-Z)(a−z,A−Z) 手动代码如下: bool isalpha(char ch) { return ((ch>='a'&&ch<='z')||((ch&g...

sinat_41733179的博客 374

避开奸商套路!手把手教你用Thaiphoon Burner和CPU-Z,一眼看穿内存SPD信息有没有被篡改

本文教你使用Thaiphoon Burner和CPU-Z工具,快速识别内存SPD信息是否被篡改,避免购买到虚标频率或假冒颗粒的内存条。通过详细步骤和实战案例,帮助用户掌握内存检测技巧,确保硬件购买的透明度和安全性。

weixin_32228501的博客 685

哈希查找的应用之打印c++源文件中关键字和函数名

#include #include #include #include #include #include using namespace std; /*unsigned int BKDRHash(const string str) {  unsigned int seed=131;  unsigned int hash=0;  string::const_iterator

wangzhicheng2013的专栏 1604

26 硬件工程师笔面试高频考点真题解析——CAN总线

CAN总线是一种差分多主串行半双工总线,采用非破坏性位仲裁机制和五层硬件错误检测(位错误、填充错误、CRC校验、格式错误、应答错误),具有高可靠性和故障容错能力。关键设计包括两端120Ω终端电阻匹配阻抗、手拉手总线拓扑、显性/隐性电平优先级仲裁。常见故障分析指出多节点异常多因终端电阻错配/漏装、星型布线违规或总线过载;高速通讯失败常由阻抗失配或线缆过长导致信号反射。相比RS485,CAN支持多主架构、硬件自动仲裁和节点故障隔离,更适用于汽车、工业等高可靠场景。

XU157303764的博客 550

统信UOS专业版服务器无人值守安装

(2)、专业版:主要针对整机厂商、政府单位、事业单位和企业用户使用,cpu目前支持x86、arm、mips、sw64和LoogngArch架构,试用期免费获得90天的使用,随后需要单位采购授权,获得正式激活码后才可以正常使用。其中企业版代号为d,行业版为a/c,欧拉版则为e,在最近的更新中,c版已经停止更新迭代,后续行业版本将都为a版,版本代号体现在镜像名字中以及版本号上,例如1050d则表示企业版1050版本。UOS系统服务器版本分为:专业版(d版)、行业版(a版)、欧拉版(e版)

靠谱运维 2254

深圳杯&东三省联赛数学建模挑战赛2024C题

编译器版本的识别问题作为一种重要的工具,电子计算机自诞生以来,经历了极为快速的发展。区区百年的时间内,无论从体积、能耗、计算速度,还是应用能力等方面,电子计算机都出现了极为显著的变化。但要充分利用这一工具,必须使用能够被电子计算机解释执行的指令序列,即程序。最早可用于在电子计算机上执行的程序通常使用机器语言(machine language)编制。由于该类语言并不直观,故它极大地限制了电子计算机的普及。为克服这一困难,1957年诞生了第一个自动编译器,FORTRAN。此后,大量性能更高并支持近乎自然语言的编

qq_33690821的博客 1265

C# 读取图片和扫描PDF中的文本

本博客将探讨如何使用C#和OCR库实现从图片和扫描的 PDF 中提取文本。Spire.OCR for .NET 是一个OCR文字识别库,专为在 .NET 应用程序中识别图片的文本而设计。首先,使用 Spire.PDF 将扫描的 PDF 转换为图片,然后利用 Spire.OCR 从这些图片中提取文本。由于该OCR库并不支持直接处理PDF,因此要从扫描的 PDF 中提取文本,我们首先需要将 PDF 文档转换为图片。转换完成后,再利用 Spire.OCR 从生成的图片中提取文本。方法来识别图片中的文本。

nuclear2011的博客 5402

C++源代码统计分析器:从量化分析到工程化思维培养

在软件开发中,代码质量分析是提升工程能力的关键环节。其核心原理是通过静态分析技术,对源代码的规模、结构和复杂度进行量化评估,从而识别潜在问题。这项技术的价值在于将主观的代码感受转化为客观数据,帮助开发者建立工程化思维,从“能运行”迈向“易维护”。常见的应用场景包括课程设计复盘、项目代码审查以及个人编码习惯优化。本文聚焦于C++程序源代码统计分析器的实现,详细探讨了如何利用有限状态机和启发式规则进行代码行、注释、函数等核心指标的统计,并深入解析了函数签名识别等关键技术难点与解决方案。

weixin_33898233的博客 347

RT-Thread 5.1.0 实战:手把手教你用CubeMX和RT-Studio创建第一个工程(附常见编译错误修复)

本文详细介绍了如何使用STM32CubeMX和RT-Thread Studio 5.1.0创建第一个RT-Thread工程,包括开发环境准备、CubeMX配置、工程整合及常见编译错误修复。通过实战指南,帮助开发者快速上手RT-Thread 5.1.0,解决开发过程中的典型问题,提升嵌入式开发效率。

weixin_29165465的博客 286

ubuntu为Docker配置代理

我们平常在ubuntu终端中使用curl或git命令时,往往会很慢。所以,首先需要给ubuntu终端环境添加代理。查看自身那个软件的端口号,我这里是7890。

不想随波逐流的大学生一枚,我们每个人都在努力奔跑 1643

C++第16周项目4 -处理C++源代码 - (1)有没有main函数?

课程首页地址:http://blog.youkuaiyun.com/sxhelijian/article/details/7910565,本周题目链接:http://blog.youkuaiyun.com/sxhelijian/article/details/9078413【项目4】写处理C++源代码的程序   (1)读入一个C++程序,判断其中是否只有一个main()函数,输出“暂时没有发现问题”,或者“没有main(

迂者-贺利坚的专栏 4224

Open3D 高斯牛顿法优化的ICP点云配准

本文介绍了基于高斯牛顿法的ICP点云配准算法。算法通过最小化源点云与目标点云之间的误差函数,求解最优的刚性变换参数(平移向量和欧拉角)。核心内容包括:1)建立误差函数和目标函数;2)推导雅可比矩阵计算,特别是旋转导数的李代数近似;3)详细阐述高斯牛顿法的迭代流程,包括变换计算、最近邻搜索、参数更新等步骤;4)分析算法的优缺点,指出其具有二阶收敛速度但可能陷入局部最优。最后给出了完整的数学推导过程,包括误差函数的泰勒展开和目标函数的近似优化。该算法适用于三维点云配准任务,但需要良好的初始位姿以避免局部收敛问题

点云侠的博客 128

C++正则表达式 分组

前言 输入的代码当做是字符串,我需要把其中的标识符、数字、复数、函数、关键字等识别出来。之前做的计算器改进版本时,用了两次匹配,第一次分割Token,第二次分类Token,但是我想让这个分类步骤快一点,如果能在第一次分割的时候得到分组信息也就能省略第二次匹配了! ...

痛苦的时候装出幸福相,这不是那么难做到的事 2263

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

提取C++库函数的代码(java)

 闲来无事,写了一个提取C++库函数的代码,没有仔细测试。package edu.kevin.regular;import java.io.*;import java.util.*;import java.util.regex.*;public class SrcAnalyze ...{    private String srcDir;    private HashSet allA

心灵的家园 910

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

VS2019无法识别scanf、fopen、strcpy等函数的解决方案(超详细)

文章目录前言一、VS2019常见的函数无法识别报错汇总二、解决方案1.在该代码文件第一行添加#define _CRT_SECURE_NO_WARNINGS2.在VS2019里面改预处理器定义3.最牛叉的方法,一次性解决后顾之忧总结 前言 当你看过我的这篇博客后,你将彻底和函数后缀’_s’说拜拜 写C/C++语言程序时,你是否还在为scanf、strcpy、fopen等函数需要加后缀而感到烦恼? 而且即使加了后缀,可能也会存在错误与警告提示让你浑身难受? 你看了别的博主的一些解决方案也是似懂非懂? 一、

m0_46442631的博客 6804

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

实现一个函数int my_atoi(char s[]),可以将一个字符串转换为对应的整数。

比如:输入字符串“1234”,返回数字1234。 输入字符串“+1234”,返回数字1234. 输入字符串“-1234”,返回数字-1234. #include<stdio.h> intmain() { intn; intmy_atoi(chars[10]); charstr[10]; gets(str); n=...

weixin_34401479的博客 453

C语言词法分析器源代码

<br />#include <iostream> #include<string> using namespace std; #define MAX 22 char ch =' '; string key[15]={"begin","end","if","then","else","while","write","read", "do", "call","const","char","until","procedure","repeat"};

wx6430的专栏 1769

写一个函数,可以处理C++代码,将其中的注释去掉

写一个函数,可以处理C++代码,将其中的注释去掉 考虑两种注释:

Rover1234的专栏 1318

深圳杯数学建模挑战赛2024年C题思路+论文+代码

编译器版本的识别问题作为一种重要的工具,电子计算机自诞生以来,经历了极为快速的发展。区区百年的时间内,无论从体积、能耗、计算速度,还是应用能力等方面,电子计算机都出现了极为显著的变化。但要充分利用这一工具,必须使用能够被电子计算机解释执行的指令序列,即程序。最早可用于在电子计算机上执行的程序通常使用机器语言(machine language)编制。由于该类语言并不直观,故它极大地限制了电子计算机的普及。为克服这一困难,1957年诞生了第一个自动编译器,FORTRAN。此后,大量性能更高并支持近乎自然语言的编

m0_58496908的博客 2428
上一篇: 【转载】R6034错误,C Runtime Error
下一篇: 获取文件信息
CButtonST
博客等级 码龄16年 42粉丝 15原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值