2
\$\begingroup\$

I've made a program that goes through your download directory (or any other directory; you just have to change the path) and finds the files that matches your query then asks you to rename or remove the file of your choice.

I'd like to know how to make my program shorter.

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#define SIZE 100
void nEraser(char expression[]);
void cases(char entery[] ,int ans ,int ansN);

int main(void)
{
     //DECLARATIONS
    //----------------------------------------------------------------------------------------------
    char fileNameContainer[SIZE] , entery[SIZE] , ans[3] , ansN[3] , *chrRes = NULL , fileNum[SIZE];
    int i , finderChecker = 0 , lenght = 0 , n = 0 , number = 1 , ansNInt =0 , fileNumInt = 0  ;
    DIR* directory = NULL;
    struct dirent* theFile = NULL;
    //----------------------------------------------------------------------------------------------
    do
    {
        /*these variables need to be reinitialized after each 'y' answer*/
        /*-----------------------------------------------------------------------------------*/
        number = 1;
        ansNInt = 0;
        finderChecker=0;
        n=0;
        ans[3]="";
        ansN[3] = "";
        fileNameContainer[SIZE]= "";
        fileNum[SIZE] = "";
        /*-----------------------------------------------------------------------------------*/
        directory = opendir("C:\\Users\\USER\\Downloads\\");//opening the targeted folder
        if(directory == NULL)//always good to check
        {
            printf("error while trying to open this directory");
            exit(-1);
        }
        do
        {
            printf("enter the name of the file you want to look for : ");
            fgets(entery , sizeof(entery) , stdin);
        /*the fgets function prints in addition to the carateres needed the \n which is a pain
        in the ass so the following function removes the extra \n*/
            nEraser(entery);
            lenght = (int)strlen(entery);
            if(lenght < 3)
            {
                printf("please enter a name that contains more than 3 caracters \n");
                n++;
            }
            if(n == 5)
            {
                printf("you don't want to enter a valid name ? bye then ");
                exit(1);
            }
        }
        while(lenght < 3);

        while((theFile = readdir(directory)) != NULL)//reading the fileNameContainer while there is something to read
        {
            strcpy(fileNameContainer,theFile->d_name);//copy the fileNameContainer name to fileNameContainer because its easier to deal with
            /*changing the name of the file to lower case so that it maches the name entered by the user*/
            for(i=0 ; fileNameContainer[i] != '\0' ; i++)
                fileNameContainer[i] = tolower(fileNameContainer[i]);
            /*this is where all the magic happens*/
            if((chrRes = strstr(fileNameContainer,entery)) != NULL)
            {
                printf("%d- \" %s \"\n", number , fileNameContainer);
                finderChecker++;
                number++;
            }
        }
        /*in case there is a match*/
        if(finderChecker != 0)
        {
            printf("\n%d results in total\n\n" , finderChecker);
            printf("what file do you want to modify , choose a number : ");
            fgets(fileNum , sizeof(fileNum) , stdin);
            nEraser(fileNum);
            fileNumInt = strtol(fileNum , NULL , 10);
            printf("what do you want to do with this files ?\n");
            printf("1.rename\n2.remove\n3.nothing I just want to get the hell out of here\n");
            fgets(ansN , sizeof(ansN) , stdin);
            nEraser(ansN);
            ansNInt = strtol(ansN , NULL , 10);
            cases(entery , ansNInt , fileNumInt);
            printf("would you like to perform another search ? y/n ");
            fgets(ans , sizeof(ans) , stdin);
            nEraser(ans);
            if(strcmp(ans,"n") == 0 || strcmp(ans,"N") == 0)
                break;
        }
        else
        {
            printf("we were unable to find this file , would you like to make another search ? y/n ");
            fgets(ans , sizeof(ans) , stdin);
            nEraser(ans);
        }

        if(closedir(directory) == -1)
            exit(-2);
    }
    while(strcmp(ans,"y") == 0 || strcmp(ans,"Y") == 0);
    getchar();
    return 0;
}

void nEraser(char expression[])
{
    int i , lenght = strlen(expression);
    for(i=0 ; i<lenght ; i++)
    {
        if(expression[i] == '\n')
            expression[i] = '\0';
    }
}
void cases(char entery[] ,int ans , int ansN)
{
    //---------------------------------------------------------------------------------------------------------------------------------
    int i , number = 0;
    struct dirent* filename = NULL;
    DIR* directory = NULL;
    char  *chrRes = NULL , fileNameContainer[SIZE] , Path[SIZE] = "C:\\Users\\USER\\Downloads\\" , newFileName[SIZE] , removeAns[3];
    //---------------------------------------------------------------------------------------------------------------------------------
    directory = opendir(Path);
        if(directory == NULL)//always good to check
        {
            printf("error while trying to open this directory");
            exit(-1);
        }
        while((filename = readdir(directory)) != NULL)//reading the fileNameContainer while there is something to read
        {
            strcpy(fileNameContainer , filename->d_name);//copy the fileNameContainer name to fileNameContainer because its easier to deal with
            for(i=0 ; fileNameContainer[i] != '\0' ; i++)      
                fileNameContainer[i] = tolower(fileNameContainer[i]);
            chrRes = strstr(fileNameContainer,entery);
            if(chrRes != NULL)
            {
                number++;
            }
            if(number == ansN)
                break;
        }
    switch(ans)
    {
        case 1:
            printf("what's the new file name ? : ");
            fgets(newFileName , sizeof(newFileName) , stdin);
            nEraser(newFileName);
            strcat(Path , filename->d_name);
            if(rename(Path, newFileName) == 0)
                printf("the file %s (PATH : %s )was renamed successfuly , the new name is : %s\n" , filename->d_name , Path , newFileName);
            else
                printf("the renaming process didn't go well ...\n");
            break;
        case 2:
            printf("are you sure you want to remove the file : %s ? y/n \n" , filename->d_name);
            fgets(removeAns , sizeof(removeAns) , stdin);
            nEraser(removeAns);
            if(strcmp(removeAns , "y") == 0 || strcmp(removeAns , "Y") == 0)
            {
                strcat(Path , filename->d_name);
                remove(Path);
            }
            break;
        case 3:
            break;
        default :
            printf("please enter a valid answer");
    }
    if(closedir(directory) == -1)
        exit(-3);
}
\$\endgroup\$
2
  • 2
    \$\begingroup\$ We'll only be able to answer if you show us the working code, as mentioned in the faq. Otherwise, your question will be closed. Thanks! \$\endgroup\$ Commented May 22, 2013 at 14:46
  • 2
    \$\begingroup\$ I suggest you compile your program with warnings enabled (eg -Wall for gcc/clang) and fix the warnings. Then paste the whole program into the question here, just like you did at pastebin. After pasting, select the whole program and use ctrl-k to indent it. \$\endgroup\$ Commented May 22, 2013 at 17:41

1 Answer 1

2
\$\begingroup\$

This code has too many issues to go through in detail. Here are some that stand out.

Firstly, compiling the code leads to a page of warnings that you should have caught yourself. Code such as

char fileNameContainer[SIZE] , entery[SIZE] , ans[3] , ansN[3] ...
...
ans[3] = "";
ansN[3] = "";
etc

should give some warnings:

code.c:26:15: warning: incompatible pointer ...
code.c:26:9: warning: array index 3 is past the end of the array ...

If you had defined one variable per line (as is best practice) and initialized it immediately, there would have been no problem.

char fileNameContainer[SIZE] = "";
char entery[SIZE] = "";
char ans[3] = "";
char ansN[3] = "";

Secondly, you do not decompose the program into suitable functions. main and cases are much too long. Its component parts should be extracted into separate functions. main is typically quite short.

Thirdly, you are converting file names to lower case for comparison, but some fielsystems are case sensitive.

Minor tidbit, you nEraser function, which deletes the trailing \n on a string is excessive. The standard function strchr will find the character for you so all you need is:

char *s = strchr(expr, '\n');
if (s) {
    *s = '\0';
}

There are many other issues, and maybe someone else will point some out. But you can improve the program by correcting those above.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.