[英]I tried decomposing my function, but I'm not sure if I did it right
最初,此功能已嵌入到main函數中,從而創建了一個非常混亂的main函數。 該程序用空格數替換制表符。 對於函數的參數列表中的內容以及如何將argc / argv從main傳遞到這些函數中,我仍然感到困惑。 我這樣做對嗎?
文件頂部有一些已定義的變量:
#define OUTFILE_NAME "detabbed"
#define TAB_STOP_SIZE 8
#define NUM_ARGS 2
#define FILE_ARG_IDX 1
這是我第二次嘗試:
void open_file(FILE *inf, FILE *outf, char *in[]) /*I feel like the arguments aren't right
{ and this function is just opening
and reading files*/
inf = fopen(in[1], "r");
outf = fopen(OUTFILE_NAME, "w");
if (inf == NULL)
{
perror(in[1]);
exit(1);
}
else if (outf == NULL)
{
perror(OUTFILE_NAME);
exit(1);
}
fclose(inf);
fclose(outf);
}
void detab(FILE *infile, FILE *outfile, char *argument[]) /* Confused about argument list
{ and this function actually
char c; does the detabbing */
int character_count = 0, i, num_spaces;
open_file(infile, outfile, argument); /* I want to call the previous
function but again, confused
while (fscanf(infile, "%c", &c) != EOF) about the argument list */
{
if (c == '\t')
{
num_spaces = TAB_STOP_SIZE - (character_count % TAB_STOP_SIZE);
for (i = 0; i < num_spaces; i++)
{
fprintf(outfile, " ");
}
character_count += num_spaces;
}
else if (c == '\n')
{
fprintf(outfile, "\n");
character_count = 0;
}
else
{
fprintf(outfile, "%c", c);
character_count++;
}
}
}
int main(int argc, char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "usage: prog file\n");
exit(1);
}
else if (argc < NUM_ARGS)
{
fprintf(stderr, "usage: %s file\n", argv[0]);
exit(1);
}
detab(argc, argv); /* I want to pass argc and argv to the detab function, but I'm
having trouble with the argument list */
return 0;
}
我需要幫助的是弄清楚函數參數列表中的內容。 我認為讓我感到困惑的是如何使我的參數類型匹配,以便我可以將變量從一個函數傳遞給另一個函數。
分解不是您最大的問題。 相當粗心的錯誤檢查,使用舊的超重fscanf()
和fprintf()
以及全局變量。 此外,輸入文件名中缺少const正確性,變量名過長和冗長,以及您對+=
和++
運算符的不了解僅是加分項。 我想這就是為什么您的代碼看起來過分膨脹(實際上是這樣)的原因。
我將這樣重寫函數:
void detab(const char *in, const char *out, int tabstop)
{
FILE *inf = fopen(in, "r");
if (!inf) return;
FILE *outf = fopen(out, "w");
if (!outf) {
fclose(inf);
return;
}
int n = 0;
int c;
while ((c = fgetc(inf)) != EOF) {
if (c == '\t') {
int pad = tabstop - n % tabstop;
for (int i = 0; i < pad; i++)
fputc(' ', outf);
n += pad;
} else if (c == '\n') {
fputc('\n', outf);
n = 0;
} else {
fputc(c, outf);
n++;
}
}
fclose(inf);
fclose(outf);
}
如果要進一步分解,則可以編寫一個函數,該函數使用兩個FILE *
和制表位作為其參數,並且僅包含while
循環-練習時留給您。
注意:此答案是對問題的早期編輯。 同時,它已經更改,因此該答案似乎不再有意義。
來自OOP背景,我將集中討論一個單一問題,即單一責任原則(SRP) 。 我認為detab
(以及其他所有功能)應該只做一件特定的事情 ,但是要做好那件事。
但是,它不僅僅顧名思義就是“去刺”。 它也有在命令行變量提取其實際參數argc
和argv
,這是由在它迫使main
:
detab(argc, argv);
main
在此之前已經進行了一些驗證,但是由於僅將命令行傳遞給了函數,因此您顯然感覺像是在detab
繼續驗證(我也對違反以下SRP提出了一些補充意見):
void detab(int arg_list, char *array[]) // why ask for arg_list if you don't need it?
{
…
infile = fopen(array[1], "r"); // not obvious to caller that only array[1] is relevant
…
if (infile == NULL)
{
perror(array[1]);
exit(1); // should your function really have the power to terminate the program?
}
…
}
將所有命令行驗證和值提取邏輯集中在一個地方,將取消標記集中在另一個地方似乎更加合理。 也就是說,划清責任界限。 不要讓一個功能的邏輯溢出到另一個功能中!
在我看來, detab
的簽名應該更像這樣:
void detab(FILE *in, FILE *out);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.