简体   繁体   English

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

[英]I tried decomposing my function, but I'm not sure if I did it right

Originally, this function was embedded into the main function, creating a very cluttered main function. 最初,此功能已嵌入到main函数中,从而创建了一个非常混乱的main函数。 The program replaces tabs with the number of spaces. 该程序用空格数替换制表符。 I'm still confused as to what goes inside the argument lists for my functions and how to pass argc/argv from main into these functions. 对于函数的参数列表中的内容以及如何将argc / argv从main传递到这些函数中,我仍然感到困惑。 Did I do this right? 我这样做对吗?

There are some defined variables at the top of the file: 文件顶部有一些已定义的变量:

#define OUTFILE_NAME "detabbed"
#define TAB_STOP_SIZE 8
#define NUM_ARGS 2
#define FILE_ARG_IDX 1

Here's my second attempt at it: 这是我第二次尝试:

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;
}

What I need help with, is figuring out what goes in the argument lists of the functions. 我需要帮助的是弄清楚函数参数列表中的内容。 I think what confuses me is how to get my argument types to match, so that I can pass variables from one function to the other. 我认为让我感到困惑的是如何使我的参数类型匹配,以便我可以将变量从一个函数传递给另一个函数。

Decomposition is not your biggest problem here. 分解不是您最大的问题。 Rather careless error checking, the use of old overweighted fscanf() and fprintf() and global variables are. 相当粗心的错误检查,使用旧的超重fscanf()fprintf()以及全局变量。 Furthermore, the lack of const correctness in the input filenames, the overly long and verbose variable names and your unawareness of the += and ++ operators are just the bonus. 此外,输入文件名中缺少const正确性,变量名过长和冗长,以及您对+=++运算符的不了解仅是加分项。 I suppose that's why your code looks like it's bloated (and it is, in fact). 我想这就是为什么您的代码看起来过分膨胀(实际上是这样)的原因。

I'd rewrite the function like this: 我将这样重写函数:

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);
}

If you want to decompose this even further, then you may write a function taking two FILE * and the tab stop as its arguments and it shall contain the while loop only - doing that is left to you as an exercise. 如果要进一步分解,则可以编写一个函数,该函数使用两个FILE *和制表位作为其参数,并且仅包含while循环-练习时留给您。

Note: This answer was given to an earlier edit of the question. 注意:此答案是对问题的早期编辑。 It has changed in the meantime, so this answer may no longer seem relevant. 同时,它已经更改,因此该答案似乎不再有意义。

Coming from an OOP background, I will focus on one single issue that is there known as Single Responsibility Principle (SRP) . 来自OOP背景,我将集中讨论一个单一问题,即单一责任原则(SRP) I argue that detab (and every other function) should do only one specific thing , but do that thing well. 我认为detab (以及其他所有功能)应该只做一件特定的事情 ,但是要做好那件事。

But it doesn't just "detab", as its name suggests; 但是,它不仅仅顾名思义就是“去刺”。 it also has to extract its actual arguments from the command-line variables argc and argv , which were forced upon it by main : 它也有在命令行变量提取其实际参数argcargv ,这是由在它迫使main

detab(argc, argv);

main has done some validation before that, but because the command-line is then simply passed to the function, you obviously felt like continuing validation in detab (I also make some additional remarks about violating the SRP below): 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?
   }
   …
}

It would seem much more reasonable to concentrate all the command-line validation and value extraction logic in one place, and the detabbing in another; 将所有命令行验证和值提取逻辑集中在一个地方,将取消标记集中在另一个地方似乎更加合理。 that is, draw clear boundaries of responsibility. 也就是说,划清责任界限。 Don't let logic of one function spill over into another! 不要让一个功能的逻辑溢出到另一个功能中!

To me, detab 's signature should look more like eg this: 在我看来, detab的签名应该更像这样:

void detab(FILE *in, FILE *out);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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