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);
}
-
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\$Glenn Rogers– Glenn Rogers2013年05月22日 14:46:22 +00:00Commented 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\$William Morris– William Morris2013年05月22日 17:41:50 +00:00Commented May 22, 2013 at 17:41
1 Answer 1
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.
Explore related questions
See similar questions with these tags.