2016-09-29 18 views
-1

我剛開始學習C.我的第一個項目是一個程序,它從文本文件中讀取文本,然後根據命令對其進行格式化在文件中。如何搜索文件中的單詞,將其放入數組中然後將其刪除C

我的解決方法是讓程序掃描文本文件,找到命令,將它們從文本文件中刪除,然後將它們放入數組中。然後通過每條命令的if語句運行剩餘的文本。

例如,如果該命令刪除多餘的空白,它會從代碼中刪除多餘的空白等等。到目前爲止,我只是有讀取文件並打印出來

#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
FILE *fp; 
char *filename; 
char ch; 



// Check if a filename has been specified in the command 
    if (argc < 2) 
    { 
     printf("Missing Filename\n"); 
     return(1); 
    } 
    else 
    { 
     filename = argv[1]; 
     printf("Filename : %s\n", filename); 
    } 

    // Open file in read-only mode 
    fp = fopen(filename,"r"); 


    // If file opened successfully, then print the contents 
    if (fp) 
     { 
     printf("File contents:\n"); 
     while ((ch = fgetc(fp)) != EOF) 
      { 
       printf("%c",ch); 
      } 

     } 
    else 
     { 
     printf("Failed to open the file\n"); 
     } 

return(0); 
} 

此代碼是不是完全屬於我要指出一個代碼。

我的問題是。我試圖編寫一段代碼掃描文本文件,找到一個特定的單詞,將它從文本文件中刪除並將其保存在數組中。而已。一旦在文本文件中找到該單詞,它就會保存在一個數組中,然後從文本文件中刪除。這個詞將是一個格式化選項。然後文本將根據選項的格式進行格式化,然後打印到另一個文本文件中。

例如,它掃描文本並找到單詞「LW30」,這個單詞意味着每行最多隻能有30個字符。一旦程序找到這個選項,它會根據選項的含義來格式化文本。它可能是不止一個選項,每個選項意味着不同的事情,但只有5個選項可能,當然,它將閱讀隨機文本文件,所以我不知道選項會是什麼。

格式化命令是:

.LW(寬度)的每一行被格式化使得存在從來沒有超過每行的「width」字符

.LM(左)這裏每行以下更該命令將從左側邊界縮進「左」空格。縮進包含在頁面寬度中。

.FT [off | on]這用於打開和關閉格式。如果該命令以「off」出現,那麼直到下一個「.FT」命令的命令下面的所有文本都將被輸出,而不被格式化。如果它以「on」出現,那麼直到下一個「.FT」命令的命令下的所有文本將輸出儘可能多的單詞,以填充給定的頁面寬度,如果「linespacing」爲「012」,不是零(0),那麼在每個文本行之間會出現行間距空行。輸入文件中的空白行被認爲與文本行相同。

而且,每個命令都會有它自己的行文本

我真的很感激一些幫助與此有關。

+1

請具體說明什麼問題在你需要幫助的代碼。你是否試圖解決這個問題? – Gerhard

+0

修改文件並重新讀取它不是一個好主意。相反,你應該在飛行中分析它。但是,答案取決於您作爲輸入文件的結構。沒有進一步的信息,我們無法真正幫助 –

+0

@Gerhard我編輯了它,我在代碼之後的段落中重述了我的問題。請告訴我,如果我需要更清楚 –

回答

1

這就是爲了解決問題必須分成小的問題。

  1. 閱讀每行

    一個輸入文件線。如果是格式化命令,請使用格式化選項更改程序的狀態

    b。否則打印正確格式化爲臨時文件的行

  2. 用臨時文件的內容覆蓋輸入文件。

首先,讓我們定義一些稍後將被重用的類型。如果您是C的新手,我邀請您檢查this page並閱讀enum,structunion

可能的命令

typedef enum Command_e { CMD_NONE, LW , LM , FT , LS } Command; 

不同種類線的enumaration的枚舉。基本上你有兩種線:要格式化的常規線和包含命令的線

typedef enum LineType_e { LT_NONE, REGULAR , COMMAND } LineType; 

表示線的結構。一行包含它的類型。此外,REGULAR行包含其長度及其內容。 A COMMAND包含其類型及其參數。我們將分別通過10分別代表onoff的值。

typedef struct Line_s 
{ 
    LineType type; 

    union 
    { 
    struct cmd_s 
    { 
     Command type; 
     int  arg; 
    } cmd; 

    struct reg_s 
    { 
     char * str; 
     size_t len; 
    } reg; 

    } content; 

} Line; 

在C中,沒有標準的getline函數。但是,使用fgets函數很容易。

// Read a line from the stream and returns a string containing every 
// characters of the line until a newline character is read or end-of-file 
// is reached. size is filled with the size of the string including the 
// newline character. 
// If end-of-file is reached before any character is read, the function 
// returns NULL 
char * getline(FILE * stream, size_t * s) 
{ 
    char * buf = NULL; // Buffer to return 
    int cnt = 0; 
    int size = 0; // Buffer size 
    int start = 0; // Where to start writing in the buffer 

    do 
    { 
    // Resize the buffer to (2^cnt * BUFF_SIZE) and fill the expanded 
    // part with the a null character 
    size = BUFF_SIZE * (1 << cnt); 
    start = BUFF_SIZE * (1 << (cnt - 1)) - 1; 
    start = start < 0 ? 0 : start; 
    buf = realloc(buf, size * sizeof(char)); 

    memset(& buf[start], '\0', size - start); 

    // Read a maximum of (size - start) characters from the stream or 
    // until a newline character has been reached 
    fgets(& buf[start], size - start, stream); 
    cnt ++; 
    } // Loop until a complete line has been read 
    while(buf[size - 2] != '\0' && 
     buf[size - 2] != '\n' && 
     ! feof(stdin)); 

    // If nothing has been read from the file, free the memory and returns 
    // a NULL pointer 
    if(buf[0] == '\0') 
    { 
    free(buf); 
    buf = NULL; 
    (* s) = 0; 
    } 
    else 
    { 
    (* s) = strlen(buf); 
    } 

    return buf; 
} 

哪裏BUFF_SIZE是定義的典型大小爲一個緩衝器的宏。此功能要求包括string.h,因爲它使用memsetstdlib.h以便使用realloc

鑑於此功能,您可以輕鬆地編寫另一個文件,每行讀取文件行,並填充作爲輸入傳遞的Line結構,並在達到文件結尾時返回等於零的整數。

int getNextLine(FILE * stream, Line * line) 
{ 
    size_t size; 
    char * str = getline(stream, & size); 

    if(! str) 
    { 
    line->type = LT_NONE; 
    return 0; 
    } 

    str[size - 1] = '\0'; // Remove the newline character 

    if(size - 1 > 2) 
    { 
    if(str[0] == 'L' && (str[1] == 'W' || str[1] == 'M' || str[1] == 'S')) 
    { 
     // If the remaining of the string is made characters between '0' and 
     // '9', then, str is a LW, LM or LS command 
     int val = 0; 
     int i; 
     for(i = 2; i < size - 1; i ++) 
     { 
     if(str[i] < '0' || str[i] > '9') break; 

     val = val * 10 + (str[i] - '0'); 
     } 

     if(i < size - 1) 
     { 
     line->type   = REGULAR; 
     line->content.reg.str = str; 
     line->content.reg.len = size; 
     } 
     else 
     { 
     line->type   = COMMAND; 
     line->content.cmd.arg = val; 

     switch(str[1]) 
     { 
      case 'W' : line->content.cmd.type = LW; break; 
      case 'M' : line->content.cmd.type = LM; break; 
      case 'S' : line->content.cmd.type = LS; break; 
     } 
     } 

     return 1; 
    } 

    if(size - 1 == 4 && str[0] == 'F' && str[1] == 'T' && 
         str[2] == 'o' && str[3] == 'n') 
    { 
     // FTon command found 
     line->type    = COMMAND; 
     line->content.cmd.type = FT; 
     line->content.cmd.arg = 1; 

     return 1; 
    } 

    if(size - 1 == 5 && str[0] == 'F' && str[1] == 'T' && 
         str[2] == 'o' && str[3] == 'f' && str[4] == 'f') 
    { 
     // FToff command found 
     line->type  = COMMAND; 
     line->content.cmd.type = FT; 
     line->content.cmd.arg = 0; 

     return 1; 
    } 
    } 

    // If we reach this point no command have been found 
    line->type = REGULAR; 
    line->content.reg.str = str; 
    line->content.reg.len = size; 

    return 1; 
} 

現在,你快完成了。在主循環中,當getNextLine將返回0時,您可以根據收到的命令設置幾個變量,並且當您收到常規線路時,可以調用格式化函數,該函數將輸出格式化爲應該的行流。這是一個這樣的功能的例子。

void format(FILE * stream, Line line, int ft, int lw, int lm, int ls) 
{ 
    if(! ft) 
    { 
    // If the formatting is disabled, simply send the line to the stream 
    fprintf(stream, "%s\n", line.content.reg.str); 
    } 
    else 
    { 
    int i; 
    int j; 
    char f[16] = { 0 }; 
    sprintf(f, "%%.%ds\n", lw - lm); 

    i = 0; 

    do 
    { 
     for(j = 0; j < lm; j ++) fprintf(stream, " "); 
     fprintf(stream, f, & line.content.reg.str[i * (lw - lm)]); 
     for(j = 0; j < ls; j ++) fprintf(stream, "\n"); 

     i++; 
    } 
    while(i * (lw - lm) < line.content.reg.len); 
    } 
} 

我之前談過的臨時文件可以用tmpfile函數打開。當您到達輸入文件的末尾時,只需關閉輸入文件並將臨時文件的內容複製到輸入文件中即可。這隻需要buffersfprintf。將格式化的行打印到臨時文件後,請不要忘記釋放調用free函數的內存,以避免內存泄漏。

最後,像

FTon 
LW30 
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam est arcu, congue vehicula consectetur in, tempus ac ex. Integer urna lectus, maximus vel felis sed, dapibus gravida risus. Curabitur diam arcu, accumsan at magna id, laoreet condimentum ante. 

FToff 
Nulla id velit justo. Aenean leo risus, interdum lobortis enim sit amet, aliquet elementum dolor. Morbi pretium velit sed mauris molestie viverra. Cras ut cursus nibh. Aliquam ut aliquam nunc, eget rhoncus sapien. 

LS1 
Sed efficitur justo aliquam orci molestie, vel condimentum dui semper. Sed lobortis dignissim ligula ut bibendum. Pellentesque finibus euismod massa a congue. 

FTon 
Sed placerat quam eget ante rutrum pretium a in orci. Quisque id lorem dapibus, tincidunt lorem et, convallis orci. Etiam sed placerat ante. 

LM5 
Donec mi est, sodales sed faucibus ac, elementum eu velit. Nam mollis varius porttitor. Sed dignissim sodales malesuada. 
LW15 
Donec nec tempus turpis, at condimentum velit. 

文件會給你下面的輸出

Lorem ipsum dolor sit amet, co 
nsectetur adipiscing elit. Ali 
quam est arcu, congue vehicula 
consectetur in, tempus ac ex. 
Integer urna lectus, maximus 
vel felis sed, dapibus gravida 
risus. Curabitur diam arcu, a 
ccumsan at magna id, laoreet c 
ondimentum ante. 

Nulla id velit justo. Aenean leo risus, interdum lobortis enim sit amet, aliquet elementum dolor. Morbi pretium velit sed mauris molestie viverra. Cras ut cursus nibh. Aliquam ut aliquam nunc, eget rhoncus sapien. 

Sed efficitur justo aliquam orci molestie, vel condimentum dui semper. Sed lobortis dignissim ligula ut bibendum. Pellentesque finibus euismod massa a congue. 

Sed placerat quam eget ante ru 

trum pretium a in orci. Quisqu 

e id lorem dapibus, tincidunt 

lorem et, convallis orci. Etia 

m sed placerat ante. 



    Donec mi est, sodales sed 

     faucibus ac, elementum e 

    u velit. Nam mollis variu 

    s porttitor. Sed dignissi 

    m sodales malesuada. 

    Donec nec 

    tempus tur 

    pis, at co 

    ndimentum 

    velit. 
+0

謝謝m8,這工作得很好! –

+1

我很感謝你解釋每一部分。還有一些我沒有得到的部分,但我只是看看它們。我不打算像完全複製你的作品,我仍然想自己學習,但我會用它來幫助。也許只是複製代碼的一小塊,但謝謝。這真的做得很好 –

+0

這就是精神!如果您需要更多信息,請隨時在此發表評論 –

相關問題