求助!写一个函数判断一个文件里有多少个函数?? 怎么写啊, 各位大侠帮下忙啊。。思路也行,代码就更好。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 要写怎样的正则?考虑到要计算大括号还有if,while,swich等,感觉好复杂啊,想了好久都不行 额,那就奇怪了,你为什么说:考虑到要计算大括号还有if,while,swich等,感觉好复杂啊,想了好久都不行? 失败,实在是太失败啊,十五分钟变成了一个多小时,唉下面代码经过两次测试,一次是课程实验时写的一个程序,有31个函数,测试与实际相符import java.io.*;import java.util.*;import java.util.regex.*;/** * 2011-7-3 0:41:37 * @author Administrator */public class Test { public Test(String filePath){ try{ FileInputStream fis=new FileInputStream(filePath); byte b[]=new byte[1024]; ByteArrayOutputStream bos=new ByteArrayOutputStream(); while(fis.available()>0){ int num=fis.read(b); bos.write(b, 0, num); } String code=new String(bos.toByteArray()); //说明一下这里使用StringTokenizer而不用Scanner的原因 //我想把形如int prime(int a,int b)这种函数头在读取时分开成如下字符串(各字符串以空格间隔) // int prime ( int a , int b ) //这样在以后的判断中比较方便。在这里,"("作为分隔符,但是读取时得读取进来,我想了一会儿,Scanner //好像是不能返回读取到时的分隔符的,所以改用了StringTokenizer String delimeter=new String("(),{}\t\r\n* "); //说明一下,对于*,这个东西是比较烦的,定义的时候有下面三种情况 // int *p // int* p // int * p //这样在检查函数的参数表时,是比较麻烦的。所以在这里,直接将*忽略,这样并不影响参数表的 //结构。 StringTokenizer st=new StringTokenizer(code,delimeter,true); ArrayList<String> list=new ArrayList<String>(); while(st.hasMoreTokens()){ String s=st.nextToken(); if(!s.matches("[\\s\\*]+")){ list.add(s); } } String namePattern=new String("[_a-zA-Z]\\w*"); int functionNumber=0; for(int i=0;i<list.size();i++){ String text=list.get(i); //看看是否是左括号 if(text.equals("(")){ //检查其上一个字符串是否符合函数名规则 if(i==0){ continue; } String funName=list.get(i-1); if(!funName.matches(namePattern)){ continue; } //现在可以说明括号的左边符合函数名的规则了,(说明一下,如VC6.0的C语言中一个 //函数的函数头,不一定要定义返回值类型的,所以这里检查过括号左边的函数名后没有 //检查是否有返回值类型的定义。现在看括号右边的情况,形如 if(a>b)这种情况,其 //括号左边是符合函数名规则的 //按参数表规则检查,如果遇到一个类型定义,就应该接一个变量名(这里是检查函数的定义, //不是函数申明,所以类型名后面的变量名不能省略),再接一个逗号或者是右括号 //第一步,如果右边直接是右括号,直接通过 //如果不是,检查参数格式 int rightPosition=0; if(i>=list.size()-1){ continue; } if(!list.get(i+1).equals(")")){ boolean success=false; for(int j=i+1;j+2<list.size();j+=3){ //三个字符串依次为:变量类型 变量名 逗号或者右括号 if(!list.get(j).matches(namePattern)||!list.get(j+1).matches(namePattern)){ break; } String para3=list.get(j+2); if(para3.equals(",")){ continue; } else if(para3.equals(")")){ success=true; rightPosition=j+2; break; } else{ break; } } if(!success){ continue; } } else{ rightPosition=i+1; } //现在函数头是没问题了,可是要检查一下有没有函数体,因为不能将函数提前申明 //也算进去。判断方法很简单,rightPosition记住了右括号的位置,现在检查下一字符串 //是不是{ if(list.get(rightPosition+1).equals("{")){ //如果是的,现在是没有问题了 functionNumber++; //但是我们做一些小小的优化,其实其他可以优化的地方也很多 //这里的优化是,既然现在成功了,那么下次再检查的时候,就应该从这个函数的后面开始 //检查,而不是从这个函数头的第二个字符串后面检查,所以,现在做一个跳跃 //跳跃的方法是找到"}",当然,在函数体中可能出现N个"}",而我们要找的是与函数头的"{" //所对应的"}" int leftNum=0; for(int j=rightPosition+2;j<list.size();j++){ String s=list.get(j); if(s.equals("{")){ leftNum++; } else if(s.equals("}")){ if(leftNum==0){ //找到匹配的了 i=j; break; } else{ leftNum--; } } //说明一下,如果直到跳循环还没找到,那就蛋疼了,说明这个 //程序有问题。这个计算程序是针对没问题的程序写的,对于有 //问题的程序,哈哈,我没考虑 } } else{ continue; } } } System.out.println("函数个数:"+functionNumber); }catch(Exception e){ } } public static void main(String args[]){ new Test("test.c"); }} 0. 把文件读入内存1. 把文件中的注意去掉3. 根据函数的特点有返回值,名字,(), {},使用正则表达式来进行搜索[\\w]+\\s+\\w+(\\.+)\\s+\\{\\.+\\}注意\\.+这里要处理贪婪的问题,这个去查一下相关文档 急!如何不用interrupt从线程外部终止一个线程? 问个算法和数据库的问题 安装Java 完成以后 怎么配置它? 问几个个低级的问题!送100分 j2ee j2se 到底有什么区别?谁能够详细的告诉我? 写入时报错:bad file descriptor 请教多线程 java想找出字符串中最后一个英文字符的位置 为什么不输出 this is a error 用jbuilder6编程,光标的位置不在输入点,为什么? 求高手帮忙看一下。。 初学:字符串转整数输出
考虑到要计算大括号还有if,while,swich等,感觉好复杂啊,想了好久都不行?
下面代码经过两次测试,一次是课程实验时写的一个程序,有31个函数,测试与实际相符import java.io.*;
import java.util.*;
import java.util.regex.*;
/**
* 2011-7-3 0:41:37
* @author Administrator
*/
public class Test {
public Test(String filePath){
try{
FileInputStream fis=new FileInputStream(filePath);
byte b[]=new byte[1024];
ByteArrayOutputStream bos=new ByteArrayOutputStream();
while(fis.available()>0){
int num=fis.read(b);
bos.write(b, 0, num);
}
String code=new String(bos.toByteArray());
//说明一下这里使用StringTokenizer而不用Scanner的原因
//我想把形如int prime(int a,int b)这种函数头在读取时分开成如下字符串(各字符串以空格间隔)
// int prime ( int a , int b )
//这样在以后的判断中比较方便。在这里,"("作为分隔符,但是读取时得读取进来,我想了一会儿,Scanner
//好像是不能返回读取到时的分隔符的,所以改用了StringTokenizer
String delimeter=new String("(),{}\t\r\n* ");
//说明一下,对于*,这个东西是比较烦的,定义的时候有下面三种情况
// int *p
// int* p
// int * p
//这样在检查函数的参数表时,是比较麻烦的。所以在这里,直接将*忽略,这样并不影响参数表的
//结构。
StringTokenizer st=new StringTokenizer(code,delimeter,true);
ArrayList<String> list=new ArrayList<String>();
while(st.hasMoreTokens()){
String s=st.nextToken();
if(!s.matches("[\\s\\*]+")){
list.add(s);
}
}
String namePattern=new String("[_a-zA-Z]\\w*");
int functionNumber=0;
for(int i=0;i<list.size();i++){
String text=list.get(i);
//看看是否是左括号
if(text.equals("(")){
//检查其上一个字符串是否符合函数名规则
if(i==0){
continue;
}
String funName=list.get(i-1);
if(!funName.matches(namePattern)){
continue;
}
//现在可以说明括号的左边符合函数名的规则了,(说明一下,如VC6.0的C语言中一个
//函数的函数头,不一定要定义返回值类型的,所以这里检查过括号左边的函数名后没有
//检查是否有返回值类型的定义。现在看括号右边的情况,形如 if(a>b)这种情况,其
//括号左边是符合函数名规则的
//按参数表规则检查,如果遇到一个类型定义,就应该接一个变量名(这里是检查函数的定义,
//不是函数申明,所以类型名后面的变量名不能省略),再接一个逗号或者是右括号
//第一步,如果右边直接是右括号,直接通过
//如果不是,检查参数格式
int rightPosition=0;
if(i>=list.size()-1){
continue;
}
if(!list.get(i+1).equals(")")){
boolean success=false;
for(int j=i+1;j+2<list.size();j+=3){
//三个字符串依次为:变量类型 变量名 逗号或者右括号
if(!list.get(j).matches(namePattern)||!list.get(j+1).matches(namePattern)){
break;
}
String para3=list.get(j+2);
if(para3.equals(",")){
continue;
}
else if(para3.equals(")")){
success=true;
rightPosition=j+2;
break;
}
else{
break;
}
}
if(!success){
continue;
}
}
else{
rightPosition=i+1;
}
//现在函数头是没问题了,可是要检查一下有没有函数体,因为不能将函数提前申明
//也算进去。判断方法很简单,rightPosition记住了右括号的位置,现在检查下一字符串
//是不是{
if(list.get(rightPosition+1).equals("{")){
//如果是的,现在是没有问题了
functionNumber++;
//但是我们做一些小小的优化,其实其他可以优化的地方也很多
//这里的优化是,既然现在成功了,那么下次再检查的时候,就应该从这个函数的后面开始
//检查,而不是从这个函数头的第二个字符串后面检查,所以,现在做一个跳跃
//跳跃的方法是找到"}",当然,在函数体中可能出现N个"}",而我们要找的是与函数头的"{"
//所对应的"}"
int leftNum=0;
for(int j=rightPosition+2;j<list.size();j++){
String s=list.get(j);
if(s.equals("{")){
leftNum++;
}
else if(s.equals("}")){
if(leftNum==0){
//找到匹配的了
i=j;
break;
}
else{
leftNum--;
}
}
//说明一下,如果直到跳循环还没找到,那就蛋疼了,说明这个
//程序有问题。这个计算程序是针对没问题的程序写的,对于有
//问题的程序,哈哈,我没考虑
}
}
else{
continue;
}
}
}
System.out.println("函数个数:"+functionNumber);
}catch(Exception e){
}
}
public static void main(String args[]){
new Test("test.c");
}
}
1. 把文件中的注意去掉
3. 根据函数的特点有返回值,名字,(), {},使用正则表达式来进行搜索
[\\w]+\\s+\\w+(\\.+)\\s+\\{\\.+\\}
注意\\.+这里要处理贪婪的问题,这个去查一下相关文档