這就是爲了解決問題必須分成小的問題。
閱讀每行
一個輸入文件線。如果是格式化命令,請使用格式化選項更改程序的狀態
b。否則打印正確格式化爲臨時文件的行
用臨時文件的內容覆蓋輸入文件。
首先,讓我們定義一些稍後將被重用的類型。如果您是C的新手,我邀請您檢查this page並閱讀enum
,struct
和union
。
可能的命令
typedef enum Command_e { CMD_NONE, LW , LM , FT , LS } Command;
不同種類線的enumaration的枚舉。基本上你有兩種線:要格式化的常規線和包含命令的線
typedef enum LineType_e { LT_NONE, REGULAR , COMMAND } LineType;
表示線的結構。一行包含它的類型。此外,REGULAR
行包含其長度及其內容。 A COMMAND
包含其類型及其參數。我們將分別通過1
和0
分別代表on
和off
的值。
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
,因爲它使用memset
和stdlib.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
函數打開。當您到達輸入文件的末尾時,只需關閉輸入文件並將臨時文件的內容複製到輸入文件中即可。這隻需要buffers
和fprintf
。將格式化的行打印到臨時文件後,請不要忘記釋放調用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.
請具體說明什麼問題在你需要幫助的代碼。你是否試圖解決這個問題? – Gerhard
修改文件並重新讀取它不是一個好主意。相反,你應該在飛行中分析它。但是,答案取決於您作爲輸入文件的結構。沒有進一步的信息,我們無法真正幫助 –
@Gerhard我編輯了它,我在代碼之後的段落中重述了我的問題。請告訴我,如果我需要更清楚 –