简体   繁体   中英

Implementing chain of responisiblity in C with FILE* and array of structs

My goal is to create a program that writes from the CMD straight to a text file.

If the input string is one of the following strings: -exit -count -remove

It will do the tasks of exiting the program / counting lines in the file / removing the file.

I wrote a code that basically looks "ok"ish in my head, but on paper (on the monitor) it sucks.

The main function works 100% (without the call for InputCmp function . I can't figure out why I can't really connect these structs one to each other.

I want to create a chain of responsibility that will work in the following way: lets say the user writes the string: "-exit" , but exit is the 3 struct (index 2 in the array).

So I want the string to be sent to a function (that I wrote called InputCmp ) that will check strcmp with the string that inside the first struct, which is -remove . If it does not match, it will compare with the next struct in the array. Till it finds the 3rd struct which has the exact string inside of it, and then it will run a function of exiting.

But, the major issue here is to transfer somehow the FILE* from function to function. I mean I need it to be transferred from main to InputCmp and from InputCmp to each of the functions because count and remove need the file in order to operate.

I just got lost.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define BUFF_SIZE 1024

/******************************************************/

struct processor
{
        char *task;
        void (*InputCmp)(char*, size_t);
        void (*RunTask)(char*);
};
 
struct processor handlers[3];

handlers[0].task = "-remove";
handlers[1].task = "-count";
handlers[2].task = "-exit";
handlers[0].RunTask = RemoveFile;
handlers[1].RunTask = CountLines;
handlers[2].RunTask = ExitProgram;

/******************************************************/

int RemoveFile(char *string) /* needs somehow to get filename */
{ 

   if (remove(filename) == 0) 
      printf("Deleted successfully"); 
   else
      printf("Unable to delete the file"); 
  
   return 0; 
   
} 

/******************************************************/

void CountLines(char *string) /* needs somehow to get filename */
{
    FILE *fileptr;

    int count_lines = 0;

    char chr;

    fileptr = fopen(filename, "r");

    chr = getc(fileptr);

    while (chr != EOF)

    {

        if (chr == 'n')

        {

            count_lines = count_lines + 1;

        }

        chr = getc(fileptr);

    }

    fclose(fileptr); //close file.

    printf("Lines: %d",count_lines);

}

/******************************************************/

void ExitProgram(char *string)
{
    exit(1);
}


/******************************************************/

 int InputCmp(char *string, size_t index)
{
    assert(string);
    
    if (0 == strcmp(string, handlers[index].task))
    {
        return handlers[index].RunTask(string);
    }
    return handlers[index+1].InputCmp(string,index+1);
} 

/******************************************************/

int is_file_exists(char *file_name)
{
    
    FILE *file;
    if ((file = fopen(file_name,"r"))!=NULL)    
        {
            /* file exists */
            fclose(file);
            return 1;
        }    
    else  
        {
            /*File not found, no memory leak since 'file' == NULL
            fclose(file) would cause an error */
            return 0;
        }
        
}

/******************************************************/

int main(int argc, char **argv)
{
    char c;
    FILE *file;
    char buffer[BUFF_SIZE];

    if (argc >= 2)
    {
         if (is_file_exists(argv[1]))
         {
             file = fopen(argv[1], "a");
         }
         else
         {
             return 0;
         }
    }
    else
    {
         file = fopen("file.txt", "a");
    }

    while(1)
    {
    size_t i = 0;
    memset(buffer, 0, BUFF_SIZE);
    while ((c = getchar()) != '\n' && i < BUFF_SIZE)
    buffer[i++] = c;
    InputCmp(buffer, 0);
        buffer[i] = '\n';
        fputs(buffer, file); 
    }

    fclose(file);
    return 0;
}

Unfortunately you cannot derive the filename from the FILE object .

To solve this you first have to move these:

handlers[0].RunTask = RemoveFile;
handlers[1].RunTask = CountLines;
handlers[2].RunTask = ExitProgram;

in the main function, and correct the tiny mistakes here and there in your function (like \n is not n, \n allow the line return):

int RemoveFile(char *filename)
{
   if (remove(filename) == 0)
      printf("Deleted successfully\n");
   else
      printf("Unable to delete the file\n");
   return 0;
}

void (*RunTask)(char*, void*);

/******************************************************/

void CountLines(char *filename)
{
    FILE *file = fopen(filename, "r");
    int count_lines = 0;
    char chr;

    chr = getc(file);

    while (chr != EOF)
    {
        if (chr == '\n')
        {
            count_lines = count_lines + 1;
        }
        chr = getc(file);
    }
    fclose(file); //close file.
    printf("Lines: %d\n",count_lines);
}

/******************************************************/

void ExitProgram(char *s)
{
    (void)s; // to allow compilation with -Wall -Werror
    exit(EXIT_SUCCESS);
}

in your main you call functions like:

handlers[0].RunTask("file.txt");
handlers[1].RunTask("file.txt");
handlers[2].RunTask("file.txt");

or:

CountLines("file.txt");
RemoveFile("file.txt");
ExitProgram("");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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