Implement a command line-based text editor
Function:
1. Open a file
2. Save the file
3. Searching for files
4. Ability to replace files
5. Ability to delete files
/*
File: textproc. h
Compiler: Dev-C ++ OR TC2.0 (# define COMPILER_TC)
Define Macros And Tool Functions
*/
/* Define Result File Name */
# Define RESULT_FILE_NAME "010588_result.txt"
/* Define Debug Flag */
/* # Define DO_DEBUG 1 */
/* Define Compiler Flag Dev-C ++ OR TC2.0 */
/* # Define COMPILER_TC 1 */
/* Define Error Code */
# Define ERR_OPTR_UNKOWN-1
# Define ERR_OPND_NOT_MATCH-2
/* # Define ERR_DIR_FMT_INVALID-3 */
# Define ERR_FILE_CANT_FOUND-4
# Define err_file_cant_open-5
# Define err_file_write_error-6
# Define err_file_read_error-7
# Define err_memory_overflow-8
/* Define max value */
# Define max_arg_num 5
# Define max_cmd_len 1024
# Define max_str_len 256
/* Define for envtype */
Typedef struct
{
Char exepath [max_str_len + 1];
Char curpath [max_str_len + 1];
Int textlen;
Char * text;
Int arrlen;
Char * arr;
} Envtype;
/* Define for ffblk struct for tc2.0 */
Typedef struct
{
Char ff_reserved [21];/* DOS Reserved Word */
Char ff_attrib;/* File Attrib */
Int ff_ftime;/* File Time */
Int ff_fdate;/* File Date */
Long ff_fsize;/* File Size */
Char ff_name [13];/* File Name */
} Ffblk;
/* Split fileName, Extract pathName */
Int SplitDir (char pathName [], char fileName [])
{
Int I, flag = 1;
If (fileName [0]! = '//' & FileName [1]! = ':')
Flag = 0;
For (I = strlen (fileName)-1; I> = 0 & fileName [I]! = '//'; I --);
PathName [I + 1] = '/0 ';
While (I> = 0)
{
PathName [I] = fileName [I];
I --;
}
Return flag;
}
/* Dynamic Programming, Calc nextVal for KMP */
Void GetNextVal (int nextVal [], char T [], int T_len)
{
Int I = 0, j =-1;
NextVal [0] =-1;
While (I <T_len-1)
{
If (j =-1 | T [I] = T [j])
{
++ I; ++ j;
If (T [I]! = T [j])
NextVal [I] = j;
Else
NextVal [I] = nextVal [j];
}
Else
J = nextVal [j];
}
}
/* Index SubString (KMP )*/
Int IndexKMP (char S [], int S_len, char T [], int T_len, int nextVal [], int pos)
{
Int I = pos, j = 0;
While (I <S_len & j <T_len)
{
If (j =-1 | S [I] = T [j])
{
++ I; ++ j;
}
Else
J = nextVal [j];
}
If (j> = T_len)
Return i-T_len;
Else
Return-1;
}
/* Basic operation: Mark markarr array, using KMP Index */
Int getmarkarr (INT markarr [], char s [], int s_len, char T [], int t_len)
{
Int I, res, nextval [max_str_len], markcnt = 0;
Getnextval (nextval, T, t_len );
# Ifdef do_debug
Printf ("nextval_debug_begin/nnextval:/N ");
For (I = 0; I <t_len; I ++)
Printf ("% d", nextval [I]);
Printf ("/nnextval_debug_end/N ");
# Endif
For (I = 0; I <s_len; I ++)
Markarr [I] = 0;
I = 0;
Do {
Res = indexkmp (S, s_len, T, t_len, nextval, I );
If (res! =-1)
{
MarkArr [res] = 1;
MarkCnt ++;
I = res + T_len;
}
} While (I <S_len & res! =-1 );
Return markCnt;
}
/* Basic operation: Replace SubString */
Void ReplaceStr (char arr [], char text [], int textLen, int markArr [], int lenSrc, char strDest [], int lenDest)
{
Int I = 0, j = 0, k;
While (I <textLen)
{
If (markArr [I])
{
For (k = 0; k <lenDest; k ++)
{
Arr [j] = strDest [k];
J ++;
}
I + = lenSrc;
}
Else
{
Arr [j] = text [I];
J ++; I ++;
}
}
}
/*
File: textproc. cpp
Compiler: Dev-C ++ OR TC2.0 (# define COMPILER_TC)
Text Process Tools
*/
# Include <stdio. h>
# Include <stdlib. h>
# Include <string. h>
# Include <io. h>
# Include "textproc. h"
/* Open File Proc for Cmd "-o "*/
Int OpenProc (EnvType * env, char fileName [])
{
Char pathname [max_str_len + 1], TMP [max_str_len + 1];
# Ifdef compiler_tc
Ffblk fileinfo;
# Else
Struct _ finddata_t fileinfo;
# Endif
Int filehandle;
File * FP;
If (! Splitdir (pathname, filename ))
{
Strcpy (TMP, env-> exepath );
Strcat (TMP, pathname );
Strcpy (pathname, TMP );
Strcpy (TMP, env-> exepath );
Strcat (TMP, filename );
Strcpy (filename, TMP );
/* Return err_dir_fmt_invalid ;*/
}
# Ifdef compiler_tc
Filehandle = findfirst (filename, & fileinfo );
# Else
FileHandle = _ findfirst (fileName, & fileInfo );
# Endif
If (fileHandle =-1)
Return ERR_FILE_CANT_FOUND;
# Ifndef COMPILER_TC
_ Findclose (fileHandle );
# Endif
Fp = fopen (fileName, "rb ");
If (fp = NULL)
Return ERR_FILE_CANT_OPEN;
If (env-> text! = NULL)
{
Free (env-> text );
Env-> text = NULL;
Env-> textLen = 0;
}
If (env-> arr! = NULL)
{
Free (env-> arr );
Env-> arr = NULL;
Env-> arrLen = 0;
}
Strcpy (env-> curPath, pathName );
# Ifdef COMPILER_TC
Env-> textLen = fileInfo. ff_fsize;
# Else
Env-> textLen = fileInfo. size;
# Endif
Env-> text = (char *) malloc (env-> textLen * sizeof (char ));
If (env-> text = NULL)
Return ERR_MEMORY_OVERFLOW;
If (fread (env-> text, sizeof (char), env-> textLen, fp )! = Env-> textLen)
{
Fclose (fp );
Return ERR_FILE_READ_ERROR;
}
Fclose (fp );
Return 0;
}
/* Save File Proc for Cmd "-s "*/
Int SaveProc (EnvType * env, char fileName [])
{
Char pathname [max_str_len + 1], TMP [max_str_len + 1];
File * FP;
If (! Splitdir (pathname, filename ))
{
Strcpy (TMP, env-> exepath );
Strcat (TMP, pathname );
Strcpy (pathname, TMP );
Strcpy (TMP, env-> exepath );
Strcat (TMP, filename );
Strcpy (filename, TMP );
/* Return err_dir_fmt_invalid ;*/
}
Fp = fopen (filename, "WB ");
If (FP = NULL)
Return err_file_cant_open;
If (env-> Arr! = NULL)
{
Free (env-> text );
Env-> text = env-> arr;
Env-> textLen = env-> arrLen;
Env-> arr = NULL;
Env-> arrLen = 0;
}
Strcpy (env-> curPath, pathName );
If (fwrite (env-> text, sizeof (char), env-> textLen, fp )! = Env-> textLen)
{
Fclose (fp );
Return ERR_FILE_WRITE_ERROR;
}
Fclose (fp );
Return 0;
}
/* Find SubString, for Cmd "-f "*/
Int FindProc (EnvType * env, char strFind [], int strLen)
{
Int I, markCnt, * markArr = (int *) malloc (env-> textLen * sizeof (int ));
Char fileName [MAX_STR_LEN + 1];
FILE * fp;
If (markArr = NULL)
Return ERR_MEMORY_OVERFLOW;
MarkCnt = GetMarkArr (markArr, env-> text, env-> textLen, strFind, strLen );
Printf ("-f % d/n", markCnt );
# Ifdef DO_DEBUG
Printf ("MARKARR_DEBUG_BEGIN/nmarkArr:/n ");
For (I = 0; I <env-> textLen; I ++)
Printf ("% d", markArr [I]);
Printf ("/nMARKARR_DEBUG_END/n ");
# Endif
Strcpy (fileName, env-> curPath );
Strcat (fileName, RESULT_FILE_NAME );
Fp = fopen (fileName, "AB ");
If (fp = NULL)
Return ERR_FILE_CANT_OPEN;
Fprintf (fp, "-f % d/r/n", markCnt );
Free (markArr );
Fclose (fp );
Return 0;
}
/* Replace string and delete substring for cmd "-R" and "-d "*/
Int replaceproc (envtype * ENV, char strsrc [], int lensrc, char strdest [], int lendest)
{
Int I, markcnt, * markarr = (int *) malloc (env-> textlen * sizeof (INT ));
Char filename [max_str_len + 1];
File * FP;
If (markarr = NULL)
Return err_memory_overflow;
Markcnt = getmarkarr (markarr, env-> text, env-> textlen, strsrc, lensrc );
If (lendest = 0)
Printf ("-D % d/n", markcnt );
Else
Printf ("-R % d/n", markcnt );
# Ifdef do_debug
Printf ("markarr_debug_begin/nmarkarr:/N ");
For (I = 0; I <env-> textlen; I ++)
Printf ("% d", markarr [I]);
Printf ("/nmarkarr_debug_end/N ");
# Endif
Strcpy (filename, env-> curpath );
Strcat (filename, result_file_name );
Fp = fopen (filename, "AB ");
If (FP = NULL)
Return err_file_cant_open;
If (lendest = 0)
Fprintf (FP, "-D % d/R/N", markcnt );
Else
Fprintf (FP, "-R % d/R/N", markcnt );
If (env-> Arr! = NULL)
{
Free (env-> ARR );
Env-> arr = NULL;
Env-> arrlen = 0;
}
Env-> arrlen = env-> textlen + markcnt * (lendest-lensrc );
Env-> arr = (char *) malloc (env-> arrlen * sizeof (char ));
If (env-> arr = NULL)
Return ERR_MEMORY_OVERFLOW;
ReplaceStr (env-> arr, env-> text, env-> textLen, markArr, lenSrc, strDest, lenDest );
Free (markArr );
If (fwrite (env-> arr, sizeof (char), env-> arrLen, fp )! = Env-> arrLen)
{
Fclose (fp );
Return ERR_FILE_WRITE_ERROR;
}
Fprintf (fp, "/r/n ");
Fclose (fp );
Return 0;
}
/* Init WorkSpace */
Void Init (EnvType * env)
{
Getcwd (env-> exePath, MAX_STR_LEN );
Strcat (env-> exePath ,"//");
Env-> curPath [0] = '/0 ';
Env-> text = env-> arr = NULL;
Env-> textLen = env-> arrLen = 0;
}
/* Clear WorkSpace */
Void Clear (EnvType * env)
{
If (env-> text! = NULL)
{
Free (env-> text );
Env-> text = NULL;
Env-> textLen = 0;
}
If (env-> arr! = NULL)
{
Free (env-> arr );
Env-> arr = NULL;
Env-> arrLen = 0;
}
}
/* Read Cmd Line */
Int ReadCmd (int * argc, char argv [] [MAX_STR_LEN + 1], int argl [])
{
Int I;
Char line [MAX_CMD_LEN + 1];
Gets (line );
* Argc = 0;
Argl [* argc] = 0;
For (I = 0; line [I]! = '/0'; I ++)
{
If (line [I] = ''| line [I] = '/t ')
{
If (argl [* argc]> 0)
{
Argv [* argc] [argl [* argc] = '/0 ';
(* Argc) ++;
Argl [* argc] = 0;
}
}
Else
{
Argv [* argc] [argl [* argc] = line [I];
Argl [* argc] ++;
}
}
If (argl [* argc]> 0)
{
Argv [* argc] [argl [* argc] = '/0 ';
(* Argc) ++;
}
If (* argc = 1 & strcmp (argv [0], "-q") = 0)
Return 0;
Else
Return 1;
}
/* Display Usage */
Void DisplayUsage ()
{
Printf ("pai_format: OPTR [OPND1 [OPND2]/n ");
Printf ("OPTR pai_type OPND_LIST/n ");
Printf ("-o Open File. OPND1 = filename/n ");
Printf ("-h Help Info./n ");
Printf ("-s Save File. OPND1 = filename/n ");
Printf ("-F find substring. opnd1 = stringtofind/N ");
Printf ("-R replace substring. opnd1 = sourcestring/N ");
Printf ("opnd2 = targetstring/N ");
Printf ("-D Delete substring. opnd1 = stringtodelete/N ");
Printf ("-Q quit./N ");
Printf ("-e display env Info (Debug)./N ");
}
/* Display env info for debug */
Void displayenv (envtype env)
{
Int I;
Printf ("env_debug_begin/nexepath = % s/n", env.exe path );
Printf ("curpath = % s/n", ENV. curpath );
Printf ("textlen = % d, text:/N", ENV. textlen );
Printf ("-------------------/n ");
For (I = 0; I <env. textLen; I ++)
Printf ("% c", env. text [I]);
Printf ("/n -------------------/n ");
Printf ("arrLen = % d, arr:/n", env. arrLen );
Printf ("-------------------/n ");
For (I = 0; I <env. arrLen; I ++)
Printf ("% c", env. arr [I]);
Printf ("/n -----------------/nENV_DEBUG_END/n ");
}
/* Display Error Info for Debug */
Void DisplayError (int errCode)
{
Switch (errCode)
{
Case ERR_FILE_READ_ERROR: printf ("ERR_FILE_READ_ERROR/n"); break;
Case ERR_FILE_WRITE_ERROR: printf ("ERR_FILE_WRITE_ERROR"); break;
/* Case err_dir_fmt_invalid: printf ("err_dir_fmt_invalid/N"); break ;*/
Case err_file_cant_found: printf ("err_file_cant_found/N"); break;
Case err_file_cant_open: printf ("err_file_cant_open/N"); break;
Case err_memory_overflow: printf ("err_memory_overflow/N"); break;
Case err_optr_unkown: printf ("err_optr_unkown/N"); break;
Case err_opnd_not_match: printf ("err_opnd_not_match/N"); break;
Default: printf ("err_unkown/N ");
}
}
/* Main function */
Int main ()
{
Envtype env;
Int I, argc, argl [max_arg_num + 1], errcode;
Char argv [max_arg_num + 1] [max_str_len + 1];
Init (& env );
While (readcmd (& argc, argv, argl ))
{
# Ifdef do_debug
Printf ("arg_debug_begin/nargc = % d/N", argc );
For (I = 0; I <argc; I ++)
Printf ("% d % s/n", argl [I], argv [I]);
Printf ("arg_debug_end/N ");
# Endif
If (argc = 0 | argl [0]! = 2 | argv [0] [0]! = '-')
{
Displayusage ();
Continue;
}
Errcode = 0;
Switch (argv [0] [1])
{
Case 'O': If (argc! = 2)
Errcode = err_opnd_not_match;
Else
Errcode = openproc (& ENV, argv [1]);
Break;
Case 'H': If (argc! = 1)
Errcode = err_opnd_not_match;
Else
Displayusage ();
Break;
Case's ': If (argc! = 2)
Errcode = err_opnd_not_match;
Else
Errcode = saveproc (& ENV, argv [1]);
Break;
Case 'F': If (argc! = 2)
Errcode = err_opnd_not_match;
Else
Errcode = findproc (& ENV, argv [1], argl [1]);
Break;
Case 'r': If (argc! = 3)
Errcode = err_opnd_not_match;
Else
Errcode = replaceproc (& ENV, argv [1], argl [1], argv [2], argl [2]);
Break;
Case 'D': if (argc! = 2)
ErrCode = ERR_OPND_NOT_MATCH;
Else
ErrCode = ReplaceProc (& env, argv [1], argl [1], "", 0 );
Break;
Case 'q': if (argc! = 1)
ErrCode = ERR_OPND_NOT_MATCH;
Break;
Case 'E': if (argc! = 1)/* Used For Debug */
ErrCode = ERR_OPND_NOT_MATCH;
Else
DisplayEnv (env );
Break;
Default: errCode = ERR_OPTR_UNKOWN;
}
# Ifdef DO_DEBUG
DisplayEnv (env );
# Endif
If (errCode! = 0)
DisplayError (errCode );
}
Clear (& env );
Return 0;
}