2012-12-21 48 views
2

我正在編寫C程序來查找函數並計算C文件中函數的行數,並將其存儲到結構中。下面給出了我的代碼。將細節存儲到C結構中

#include <stdio.h> 
#include <string.h> 

#define SIZE 1024 
struct fundetails 
{ 
    int nooflines; 
    char *funcname; 
}s[20]; 
char *ffname(char *line) 
{ 
    int i=1,j=0; 
    char *dt; 
    char name[SIZE]; 
    strtok(line,"("); 
    dt = strchr(line,' '); 
    if(dt[i] == '*') 
     i++; 
    while(dt[i] != '\0') 
    { 
     name[j]=dt[i]; 
     i++; 
     j++; 
    } 
    name[j] ='\0'; 
    return name; 
} 

int main(int argc, char **argv) 
{ 
    if(argc < 2) 
    { 
     printf("Give the filename \n"); 
     printf("Usage: %s filename\n", argv[0]); 
     return -1; 
    } 
    int i, lines =0, funlines =0,count =0, fn =0, flag =0, size=0,emptyflag=0; 
    char c[SIZE],b[SIZE]; 
    char *fname; 
    FILE *fd; 
    fd = fopen(argv[1],"r"); 
    while(fgets(c,SIZE,fd)) 
    { 
     emptyflag=0; 
     lines++; 
     size = strlen(c); 
     if(size == 1 && (strcmp(c,"\n"))== 0) 
      emptyflag=1; 
     for(i=0;i<size;i++) 
     { 
      while(c[i] =='\t' || c[i] == ' ') 
      { 
       i++; 
      } 
      if(c[i] == '{') 
      { 
       count++; 
       if(flag) 
       { 
        if(!emptyflag) 
         funlines++; 
        else 
         emptyflag=0; 
       } 
       if(count == 1) 
       { 
        fn++; 
        printf("Function %d is Started..............\n", fn); 
        flag = 1; 
        fname=ffname(b); 
        printf("Function name is:%s\n",fname); 
       } 
       break; 
      } 
      else if(c[i] == '}') 
      { 
       count--; 
       if(!count) 
       { 
        flag = 0; 

        printf("No of lines in the function %d is: %d\n", fn, funlines); 
        printf("Function %d is finished..........\n", fn); 
        s[fn-1].nooflines=funlines; 
        s[fn-1].funcname=fname; 
        funlines = 0; 
       } 
       else 
       { 
        if(!emptyflag) 
         funlines++; 
        else 
         emptyflag=0; 
       } 
       break; 
      } 
      else if(flag) 
      { 
       if(!emptyflag) 
         funlines++; 
        else 
         emptyflag=0; 
       break; 
      } 
     } 
     strcpy(b,c); 
    } 
    printf("FUN_NAME\tNO_OF_LINES\n"); 
    for(i=0;i<fn;i++) 
    { 
    printf("%s\t\t%d\n",s[i].funcname,s[i].nooflines); 
    } 
    return 0; 
} 

它產生的警告爲try.c:26:2: warning: function returns address of local variable [enabled by default]。它產生如下所示的輸出。

Function 1 is Started.............. 
Function name is:fundetails 

No of lines in the function 1 is: 2 
Function 1 is finished.......... 
Function 2 is Started.............. 
Function name is:dhahira 
No of lines in the function 2 is: 1 
Function 2 is finished.......... 
Function 3 is Started.............. 
Function name is:add 
No of lines in the function 3 is: 3 
Function 3 is finished.......... 
Function 4 is Started.............. 
Function name is:sub 
No of lines in the function 4 is: 9 
Function 4 is finished.......... 
Function 5 is Started.............. 
Function name is:main 
No of lines in the function 5 is: 13 
Function 5 is finished.......... 
FUN_NAME NO_OF_LINES 
main  2 
main  1 
main  3 
main  9 
main  13 

我存儲function name and no of lines在相同loop.WQhile i1m在GDB運行它,的

s[fn-1].nooflines=funlines; 
s[fn-1].funcname=fname; 

上述行每次,線的數目中的結構存儲correctly.But不在 函數名的情況下。 Problem:我不明白,爲什麼它正常工作的線和不工作的函數名?是因爲那個警告嗎?請指導我,謝謝。

回答

1

首先使結構

struct fundetails 
{ 
    int nooflines; 
    char funcname[128]; 
}s[20]; 

然後修復FUNC ffname的返回值:你不能返回一個指針,數據即會消失走出去的範圍(在這種情況下,函數的結束) 。作爲廉價快速修改,只是把你的

char name[SIZE]; 

static char name[SIZE]; 

然後

strcpy(s[fn-1].funcname, fname); 

,而不是你

s[fn-1].funcname=fname; 

輸出會像

FUN_NAME  NO_OF_LINES 
fundetails 
       2 
ffname   15 
main   82 

我還沒有檢查如何識別功能,但它似乎太多天真。 (答案可能不能解決你的代碼的所有問題;例如,在代碼被分配之前可能存在路徑)...

4

在ffname()中,名稱[]是本地的,執行該函數時將其推送到堆棧。 ffname()返回後,堆棧彈出,這意味着名稱[]佔用的內存被釋放,系統可以重新使用內存,但在內存被重用之前,數據仍然存在。這就是爲什麼有時它有效,有時不適用。另外,這就是爲什麼你會收到警告。

您應該在結構中將funcname定義爲數組而不是指針。因爲當funcname時,你總是將funcname指向相同的名字[],而名稱[]寫在每個循環中,這樣最後你打印出相同的名字5次。

更改後funcname的數組,你應該使用的strcpy複製名稱:

strcpy(funcname, name); // this is right way when funcname is array 

不是: funcname的=名稱;

+0

如果我將name []聲明爲全局的,將先生,它解決了這個問題? – Dhasneem

+0

如果您將名稱[]定義爲全局名稱,則會在您的progream的生命週期中抓取內存。它會解決問題。但這不是最好的解決方案。更好的方法是將一個緩衝區傳遞給ffname()。 – TieDad

+0

謝謝你,先生,這有助於克服警告。但輸出保持不變。 – Dhasneem