繁体   English   中英

我尝试分解函数,但是不确定是否做对了

[英]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 (以及其他所有功能)应该只做一件特定的事情 ,但是要做好那件事。

但是,它不仅仅顾名思义就是“去刺”。 它也有在命令行变量提取其实际参数argcargv ,这是由在它迫使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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM