2011-05-19 47 views
0

我製作了第一個C程序。它刪除C註釋('//')。我將一個字符串傳遞給函數strip_comments,創建一個與參數字符串大小相同的新字符串,然後我做一個拷貝,char by char,忽略註釋。C - 我不想分配我不會使用的內存! (newby question)

這是代碼:

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

#define IN 1 
#define OUT 0 

int file_size(FILE *file); 
char * strip_comments(char *content); 

int main(int argc, char *argv[]) 
{ 
    FILE *file; 
    char *buffer, *content; 
    int size; 

    if (argc == 1) 
    { 
     printf("USAGE: stripccomments filename\n"); 
     return 1; 
    } 

    if ((file = fopen(argv[1], "rw")) == NULL) 
    { 
     printf("Could not open file '%s'.\n", argv[1]); 
     return 1; 
    } 

    size = file_size(file); 
    buffer = malloc(sizeof(char) * size); 

    if (buffer == NULL) 
    { 
     printf("Could not allocate memory\n"); 
     return 1; 
    } 

    fread(buffer, sizeof(char), size, file); 

    content = strip_comments(buffer); 
    printf("%s", content); 

    free(buffer); 
    fclose(file); 

    return 0; 
} 

int file_size(FILE *file) 
{ 
    int size; 

    fseek(file, 0, SEEK_END); 
    size = ftell(file); 
    rewind(file); 

    return size; 
} 

char * strip_comments(char *content) 
{ 
    int state, length, i, j; 
    char *new_content; 

    state = OUT; 
    length = strlen(content); 
    new_content = malloc(sizeof(char) * length); 
    j = 0; 

    for (i = 0; i < length; i++) 
    { 
     if (content[i] == '/' && content[i + 1] == '/') 
     { 
      state = IN; 
      i++; 
      continue; 
     } 

     if (state && content[i] == '\n') 
     { 
      state = OUT; 
     } 

     if (!state) 
     { 
      new_content[j] = content[i]; 
      j++; 
     } 
    } 
    new_content[j + 1] = '\0'; 

    return new_content; 
} 

如果有一些意見,我將只使用分配的字符串的一些字節。我不想分配超過我將使用。什麼是最好的方法來做到這一點,並返回一個新的字符串?或者我應該修改作爲參數傳遞的字符串?

更新:這個未使用的空間會發生什麼?它是否仍然處於「僵局」?當執行到最後時,這個空間會發生什麼?

謝謝。

+0

不要阻止你,但剝離C中的註釋要比這更復雜一點。想象一下你的代碼如何迴應這種情況:'char * string =「this is a // string」;' – 2011-05-19 20:15:14

+0

刪除'sizeof(char)'。它只是顯示代碼的作者不知道C. – 2011-05-19 20:19:23

+0

所以,有一個錯誤:) – thom 2011-05-19 20:19:40

回答

2

如說這不會解決你的問題,但我的方法是將它寫成與輸入文件句柄和輸出文件句柄,即void strip_comments(FILE *infile, FILE *outfile);工作的功能。你真的只是在進行一次一個字符的解析,那麼怎樣才能從content[i++]轉換爲getc()?如果你使用文件句柄而不是字符串來完成,你a)不必將潛在的大型整個文件存儲在內存中,並且b)不必擔心爲緩衝區分配內存。也就是說,如果你想用char *代替它,你總是可以解析字符串兩次:一次計算分配多少字節,然後一次複製所述字節。或者您可以簡單地在末尾調用realloc將您的緩衝區縮小到適當的大小。

+0

我將搜索realloc。謝謝。 – thom 2011-05-19 20:39:35

0

我只能想,可能使你的配置更有效率的一種方式(不,我認爲它需要,說實話你現在正在做似乎很合理,尤其是對一個新的C程序員)。

我能想到的是通過兩遍你的文件。在第一遍中,您可以計算您需要分配的內存量。在此之後,您可以準確分配您需要的內存量,然後在第二步中進行實際的複製。

你也可能受益於使該使用的文件句柄,而不是完全在內存中這樣做,這樣你就不需要在一次分配的內存大片考慮看看。

+0

那麼指針算術呢?我可以使用它來完成這項任務嗎?謝謝! – thom 2011-05-19 20:38:50

1

因爲你的程序將不知道有多少內存需要包含您可以用初始緩衝大小開始,並根據需要增加源。另一種方法是首先掃描文件並計算大小的差異。這兩種方法會影響性能取決於傳入評論量。多malloc的/ realloc的會降低性能,以及在整個文件中讀取兩次,而在另一方面你擔心浪費內存,它是您決定選擇還是可以全部使用3,設置默認值,然後執行命令行標誌以讓用戶決定選擇哪個選項。

還記得+1按鈕添加到您的strlen佔空字符。如果文件不包含任何評論,您當前的實施將進入聯合國版圖區域malloc

作爲更新:

是浪費的空間將在您的字符串不勞而獲的結束,而是會得到妥善回收一次free被調用。例如,在分配15塊內存塊的情況下,strlen爲10的字符串可能如下所示:

size of 10\0#%^@& 
      ^^^garbage 
      ^^null char 
+0

當執行結束時,操作系統不會「釋放」嗎?謝謝。 – thom 2011-05-19 21:06:40

+0

如果您在退出時泄漏或不泄露,操作系統將清理您的應用程序空間中的內存。在你的例子中,你正在泄漏內存,但是即使你沒有使用全部內存,一個免費的調用也將能夠回收所有的內存。你應該在'printf(「%s」,內容)之後調用'free(content)';'在你的例子中,因爲你別無所求。 – Joe 2011-05-19 21:13:58