Question

In: Computer Science

Develop an application that searches for files on a wild card basis (a*.c, .c, *a, etc)...

Develop an application that searches for files on a wild card basis (a*.c, .c, *a, etc) and then displays the resultant file names in all CAPITALS using pipes in a "multiprocess setup"

C language must be used

Solutions

Expert Solution

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MaxNameLen  32 //max length of names without '/0' being counted

struct nameInfo {
        char* name;
        char* replacement;
};

typedef struct nameInfo nameInfoT;
char* findMatch(char* str, char* expression);
void findAllReplacements(nameInfoT* names, size_t count, char* expression);
void printAllReplacements(nameInfoT* names, size_t count);
void clearAllReplacements(nameInfoT* names, size_t count);
int checkExpression(char* expression);
void freeNames(nameInfoT* names, size_t count);

nameInfoT* readNames(size_t* array_size);

int main(int argc, char* argv[]) {
        
        size_t names_count = 0;
        nameInfoT* names = readNames(&names_count); //call readNames to allocate memory
        char formatstring[13];
        char buffer[MaxNameLen + 1];
        
        while (1) {
                sprintf(formatstring,"%%%ds",MaxNameLen);
                scanf(formatstring, buffer);

                if (!strcmp(buffer, "END")) break;
                
                if (checkExpression(buffer)) printf("Skipping %s\n", buffer); //call checkExpression , if checkExpression returns 1 expression is not valid else the expression is valid and the code continues
                else {
                        printf("%s\n", buffer);
                        findAllReplacements(names, names_count, buffer); //call findAllReplacements
                        printAllReplacements(names, names_count); //call printAllReplacements
                        clearAllReplacements(names, names_count); //call clearAllReplacements
                }
        }

        freeNames(names, names_count); //call freeNames
        
        return(0);
}

nameInfoT* readNames(size_t* array_size) {//readNames prototype

        char buffer[MaxNameLen + 1];
        char formatstring[13];
        nameInfoT* tempPtr;
        nameInfoT* array = (nameInfoT*)malloc(sizeof(nameInfoT));  //allocate memory for the nameInfoT array
        
        if (array == NULL) {
                
                printf("Allocation failure.\nProgram will be terminated.\n"); /*if allocation fails , error message is printed and the program terminates because
                                                                                                                                                if a memory failure happens during runtime it is better to terminate the program rather than continue with the rest inputs. 
                                                                                                                                                If the program continued to the next names the output would differ from the stdoutput*/
                exit(1);
        }
        
        size_t max_size = 1;
        size_t size = 0;

        while (1) {
                
                sprintf(formatstring,"%%%ds",MaxNameLen);
                scanf(formatstring, buffer);

                if (!strcmp(buffer, "END")) break;

                if (size == max_size) { //every time the array is filled with names, it's size is doubled

                        max_size *= 2;
                        tempPtr = (nameInfoT*)realloc(array, max_size * sizeof(nameInfoT)); //tempPtr to use in reallocation
                        
                        if (tempPtr == NULL) {
                                printf("Reallocation failure.\nThe program will be terminated.\n");/*if reallocation fails , error message is printed and the program terminates because
                                                                                                                                                                        if a memory failure happens during runtime it is better to terminate the program rather than continue with the rest inputs. 
                                                                                                                                                                        If the program continued to the next names the output would differ from the stdoutput*/
                                exit(1);
                        }
                        array = tempPtr; //if reallocation is succesfull array  becomes tempPtr thus it's size is doubled
                }

                size_t len = strlen(buffer) + 1;

                array[size].name = (char*)malloc(len * sizeof(char));//allocate memory for names in the array
                if (array[size].name == NULL) {
                        printf("Reallocation failure.\nThe program will be terminated.\n");
                        freeNames(array, size); //if reallocation fails the array and the names are freed
                        exit(1);
                }
                array[size].replacement = NULL; //replacement points to NULL in this stage

                memcpy(array[size].name, buffer, len * sizeof(char));//save the current name in the array of names

                size++; //size escalates by 1
        }
        
        array = (nameInfoT*)realloc(array, size * sizeof(nameInfoT));//array of nameInfoT gets it's final memory allocation
        *array_size = size; //size of the array is returned by reference 

        return(array);
}

char* findMatch(char* str, char* expression) { //findMatch prototype
        char* WildCards = "?*";
        char* wildcard = strpbrk(expression, WildCards); //wildcard takes the value of either '?' or '*'
        int len_str, len_exp;
        len_exp = strlen(expression);
        len_str = strlen(str);
        int len = wildcard - expression; //len indicates where the wildcard character is in the expression
        char *s = NULL; //pointer needed for pointer arithmetic afterwards
        
        // if there are characters before the wildcard,
        // check whether they are same for str and expression...
        // if not, return NULL
        if (len > 0 && strncmp(str, expression, len)) return (NULL);

        if (*wildcard == '?') { //if the expression contains '?'
                
                // check if all characters after the wildcard match,
                // if not, return NULL
                if (strcmp(str + len + 1, expression + len + 1)) return (NULL);
                
                else {
                        
                        char* ret = (char*)malloc(sizeof(char)* 2);// allocate a new string to contain the matched character as well as null terminating char
                        
                        if (ret == NULL) {
                                
                                printf("Allocation failure.\nThe program will continue to the next replacement.\n"); //if allocation fails the program will continue with the next replacement (that is prefered because names are already given)
                                
                                return (NULL);
                        }
                        
                        ret[0] = str[len];// the ret[0] has the value of the str in the position that len indicates(the position that the wildcard appeared in the expression
                        ret[1] = '\0'; //'\0' entered manually
                        
                        if (ret[0] == '\0') { //if the wildcard expression consists only of '?' then nothing will be printed and the ret string is freed

                                free (ret);
                                return (NULL);
                        }
                        return (ret);
                }
        }



        else if (*wildcard == '*') { //if the expression contains '*'
                
                if (len_exp == 1) {//if the expression consists only of '*' all the names are going to be printed with replacements being the same strings as the names

                        char* ret = (char*)malloc((len_str+1) * sizeof(char));// allocate a new string to contain the matched character as well as null terminating char
                        
                        if (ret == NULL) {
                                
                                printf("Allocation failure.\nThe program will continue to the next replacement.\n");//if allocation fails the program will continue with the next replacement (that is prefered because names are already given)
                                
                                return (NULL);
                        }
                        
                        memcpy(ret,str, (len_str) * sizeof(char));
                        
                        ret[len_str+1] = '\0';//'\0' entered manually
                        
                        return (ret);
                }
                
                if(len +1 == len_exp) { //if '*' at the end of the expression
                        
                        if (!strncmp(str, expression, len - 1)) { //if a previous character of the str matches a previous character of the expression
                                
                                char* ret = (char*)malloc((len_str - len + 2)*sizeof(char));// allocate a new string to contain the matched character as well as null terminating char
                                
                                if (ret==NULL) {
                                        
                                        printf("Allocation failure.\nThe program will continue to the next replacement.\n");//if allocation fails the program will continue with the next replacement (that is prefered because names are already given)
                                        return (NULL);
                                        
                                }
                                
                                strcpy(ret, &str[len]); //replacement is the remaining str after the position of the wildcard in the expression
                                
                                return (ret);
                        }
                        return (NULL);
                }
                
                
                // try to match the remainder of the expression,
                // if it cant be matched, move to next character of str and try to match from there
                // search stops when terminating char is found
                int len2 = 0;//int that indicates the length of the replacement
                for (s = str+len; *s; s++, len2++) {// figure out how many characters were skipped until match was found

                        if (!strcmp(s, expression + len + 1)) {         
                                
                                char* ret = (char*)malloc(len2 * sizeof(char));// allocate a new string to contain the matched character as well as null terminating char
                                if (ret == NULL) {
                                        printf("Allocation failure.\nThe program will continue to the next replacement.\n");//if allocation fails the program will continue with the next replacement (that is prefered because names are already given)
                                        return (NULL);
                                }
                                memcpy(ret, str + len, (len2) * sizeof(char));
                                ret[len2] = '\0';
                                return (ret);
                        }
                }
        }
        return(NULL);
}

void findAllReplacements(nameInfoT* names, size_t count, char* expression) { //findAllReplacements prototype

        size_t i = 0;
        
        for (i = 0; i < count; i++) names[i].replacement = findMatch(names[i].name, expression); //for all the names that were counted in readNames if a replacement is found, it is stored in the array

}

void printAllReplacements(nameInfoT* names, size_t count) { //printAllReplacements prototype

        size_t i = 0;
        
        for (i = 0; i < count; i++) if (names[i].replacement) printf("\tword: %s, replacement: %s\n", names[i].name, names[i].replacement); //if the replacement of the specific name exists then the name and the replacement are printed

}

void clearAllReplacements(nameInfoT* names, size_t count) { //clearAllReplacements prototype

        size_t i = 0;
        
        for (i = 0; i < count; i++) {
                
                if (names[i].replacement) free(names[i].replacement); //replacements are freed and pointed to NULL

                names[i].replacement = NULL;
                
        }
}

// Returns 0 if expression is valid else 1 is returned
int checkExpression(char* expression) { //checkExpression prototype

        int c = 0;
        int i = 0;
        
        for (i = 0; expression[i] != '\0'; i++) {
                
                if (expression[i] == '?' || expression[i] == '*') {
                        
                        c++;
                }
        }
        
        if (c == 1) return 0;
        
        return (1);
        
}

void freeNames(nameInfoT* names, size_t count) { //freeNames prototype

        size_t i = 0;
        
        for (i = 0; i < count; i++){
                
                if (names[i].name) free(names[i].name); //names are freed

                names[i].name = NULL;
                
        }

        free(names); //the array of nameInfoT is freed
}

Related Solutions

Write a program in Python that walks through a folder tree and searches for files with...
Write a program in Python that walks through a folder tree and searches for files with a certain file extension (such as .pdf or .jpg). Copy these files from whatever location they are in to a new folder. The user can enter an absolute path for the start folder, or if the user does not enter a folder, the current directory is used. Likewise, the user can enter extensions to copy but if the user does not enter an extension,...
C# Simple Text File Merging Application - The idea is to merge two text files located...
C# Simple Text File Merging Application - The idea is to merge two text files located in the same folder to create a new txt file (also in the same folder). I have the idea, and I can merge the two txt files together, however I would like to have an empty line between the two files. How would I implement this in the code below? if (File.Exists(fileNameWithPath1)) { try { string[] file1 = File.ReadAllLines(fileNameWithPath1); string[] file2 = File.ReadAllLines(fileNameWithPath2); //dump...
In C++, develop a menu program which reads in data from 4 different input files -...
In C++, develop a menu program which reads in data from 4 different input files - appetizers, entrees, desserts, and drinks. Then, record the item information ordered by the customer for each item selected. When finished, display all items ordered to the screen with the subtotal, tax (10% for easy math), and the total. Be sure to get tip as well. Then, ensure enough payment was received before generating an output file receipt which can be printed off. Use functions...
Develop a client /server talk application in C or C++. You should run your server program...
Develop a client /server talk application in C or C++. You should run your server program first, and then open another window if you use loopback to connect the local host again, or you may go to another machine to run the client program that will connect to the server program. In this case you must find the server’s IP address first, and then connect to it. If you use loopback, your procedure may look like: ➢ Server Server is...
1. Create customized versions of the /etc/login.defs and /etc/default/useradd files in order to meet the new...
1. Create customized versions of the /etc/login.defs and /etc/default/useradd files in order to meet the new user account criteria you provide. 2. Research online for various Linux utilities that can be used to store and sort various Linux log files. Have them share their findings with the class.
) The popular card game UNO has a deck of 108 cards. Four are ‘Wild’, and...
) The popular card game UNO has a deck of 108 cards. Four are ‘Wild’, and four are ‘Wild Draw Four’. The remaining cards are grouped into four suits — Blue, Green, Red, and Yellow — with 25 cards per suit. The cards within each suit are a single zero card, two each of the cards one through nine, two ‘Draw Two’ cards, two ‘Skip’ cards, and two ‘Reverse’ cards. (a) If you draw one card at random from a...
Using C#, modify the codes below to do the following: Develop a polymorphic banking application using...
Using C#, modify the codes below to do the following: Develop a polymorphic banking application using the Account hierarchy created in the codes below. Create an array of Account references to SavingsAccount and CheckingAccount objects. For each Account in the array, allow the user to specify an amount of money to withdraw from the Account using method Debit and an amount of money to deposit into the Account using method Credit. As you process each Account, determine its type. If...
Taxpayer files bankruptcy, basis of property subject to reduction is limited to?
Taxpayer files bankruptcy, basis of property subject to reduction is limited to?
FINDtwo different credit card applications (e.g., online, at restaurants, etc.). COMPAREthe two credit card offers by...
FINDtwo different credit card applications (e.g., online, at restaurants, etc.). COMPAREthe two credit card offers by completing the chart below to describe key features of each. Credit Card Feature Card #1 What is the name of the Credit Card? What is the APR (annual percentage rate)? Is it fixed or variable? Penalty APR and trigger events when it is charged Annual fee Late fee Over-the-limit fee Transaction fees (balance transfers, cash advances, etc.) Grace period Method for computing account balance...
            It is not uncommon to develop the logic of a program as a console application...
            It is not uncommon to develop the logic of a program as a console application (NO GUI) and then graft a GUI on to it later. There are also many reasons for separating the GUI of the program from the rest of the code logic. (This is part of a common design pattern called Model View Controller (MVC) where the GUI represents the View aspect.) For instance, you might have a Web-based or mobile device GUI in addition to...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT