* / printf(" -------------------进入SCENERIO(2)--- ---------------- \\\"); printf(" log_cnt =%d \ n",log_cnt); if(!(stat(log_name,& statbuf))) { log_size =(long)statbuf.st_size; } printf(存在最大的%s,大小=%ld bytes \ n,log_name,log_size); printf(" BACKUP =%d \ n",BACKUP); / * move_log(log_cnt - 1) log_create(0); * / // ========================== ======================== ========================== ======== // =========== ===============重新命名机制================================= ======= int backup_cnt; if(BACKUP) { backup_cnt = log_cnt + 1; } else { backup_cnt = log_cnt; } char temp_oldname [LOG_NAME_SIZE]; char temp_newname [LOG_NAME_SIZE]; for(int i = backup_cnt; (i LOG_BASE_NUM)&& (i< LOG_CNT_MAX); --i) { if(sprintf(temp_oldname,LOG_NAME,i-1)< 0) { perror(SPRINTF ERROR oldname :: S2 --case b\ n); 退出(EXIT_FAILURE); } if(sprintf(temp_newname,LOG_NAME,i)< 0) { perror(" SPRINTF ERROR newname :: S2 - -case b \ n"); 退出(EXIT_FAILURE); } printf(" i =% d \ n",i); printf(" temp_oldname =%s \ n",temp_oldname); printf(" temp_newname =%s \\ \\ n",temp_newname); if(rename(temp_oldname,temp_newname)< 0) { perror( RENAME ERROR :: S2 --case b); 退出(EXIT_FAILURE); } 其他 { printf(" renamed<%sto<%s> \ n",temp_oldname,temp_newname); // sleep(2) ; } } //创建0.log if(sprintf(log_name,LOG_NAME,LOG_BASE_NUM)< 0) { perror(SPRINTF ERROR :: S2 --case b\ n); 退出(EXIT_FAILURE) ; } //打开文件并附加数据 if(!(fp = fopen(log_name," a"))) )// S2 - 案例a { perror(" FOPEN()ERROR whne log_cnt == 0"); 退出(EXIT_FAILURE); } if(fwrite(log_recv_arr,1,log_recv_size,fp)!= log_recv_size) { perror(log_cnt中的FWRIRE错误== 0); 退出(EXIT_FAILURE); } if(fclose(fp)) { perror(第187行附近的FLOSE()错误); 退出(EXIT_FAILURE); } //更新log_size if(!(stat(log_name,&) statbuf))) { log_size =(long)statbuf.st_size; } printf("%s书写=%ld \ n \\ nn",log_name,log_size); / /更新log_cnt if((log_size + log_recv_size)> = LOG_SIZE) { ++ log_cnt; } // ==========================重新命名机制==== ==================================== // ==== ============================================== ==== ============================== } // S2开始结束 // SCENERIO(3) else // log_cnt> = LOG_CNT_MAX { printf(" ----- --------------进入SCENERIO(3)------------------- \ n"); printf(" log_cnt =%d,LOG_CNT_MAX =%d \ n",log_cnt,LOG_CNT_MAX); if(! (stat(log_name,& statbuf))) { log_size =(long)statbuf.st_size; } printf(" Oldest%s存在,大小=%ld bytes \ n",log_name,log_size); printf(" BACKUP =%d \ n",BACKUP); / *这里我们是log_cnt> = LOG_CNT_MX。我们将简单地做三件事: 1)删除最旧的文件,即(LOG_CNT_MAX - 1).log 2)重命名所有文件 3)创建0.log名称 4)创建0.log文件 5)写入数据 * / // ======================================== ========== ================================== // ==========================重新命名机制================== ====================== int backup_cnt = log_cnt - 1; char temp_oldname [LOG_NAME_SIZE]; char temp_newname [LOG_NAME_SIZE]; for(int i = backup_cnt;(i LOG_BASE_NUM)&& (i< LOG_CNT_MAX); - i) { if(sprintf(temp_oldname,LOG_NAME,i-1)< 0) { perror(" SPRINTF ERROR oldname :: S2 --case b\ n); 退出(EXIT_FAILURE); } if(sprintf(temp_newname,LOG_NAME,i)< 0) { perror("的sprintf ERROR newname :: S2 --case b\ n"); 退出(EXIT_FAILURE); } printf (i =%d \ n,i); printf(" temp_oldname =%s \ n",temp_oldname); printf(" ; temp_newname =%s \ n",temp_newname); if(rename(temp_oldname,temp_newname)< 0) { perror(RENAME ERROR :: S2 --case b); 退出(EXIT_FAILURE); } 其他 { printf("重命名<%sto<%s> \ n" ;,temp_oldname,temp_newname); // sleep(2); } } //创建0.log if(sprintf(log_name,LOG_NAME,LOG_BASE_NUM)< 0) { perror(" SPRINTF ERROR: :S2 --case b \ n"); 退出(EXIT_FAILURE); } //打开文件并附加数据 if(!(fp = fopen(log_name," a")))// S2 - 案例a { perror (FOPEN()ERROR whne log_cnt == 0"); 退出(EXIT_FAILURE); } 如果(fwrite(log_recv_arr,1,log_recv_size,fp)!= log_recv_size) { perror(" FWRIRE ERROR in log_cnt == 0"); 退出(EXIT_FAILURE); } if(fclose(fp)) { perror(第187行附近的FLOSE()错误); 退出(EXIT_FAILURE); } //更新log_size if(! (stat(log_name,& statbuf))) { log_size =(long)statbuf.st_size; } printf("%s write =%ld \ n \ n",log_name,log_size); //无需更新log_cnt as log_cnt == LOG_CNT_MAX // ========================== RENAME MECHANISM ====== ================================== // ====== ============================================ ====== ============================ / * if(!( stat(log_name_old,& statbuf))) { log_size =(long)statbuf.st_size; } printf(" File%s存在,大小=%ld bytes \ n",log_name,log_size); printf(" //代码尚未写入\ nn \\ n"); * / } } // for(...)循环 返回0; } /> // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^ // R. ENAM E FILE S // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ b char temp_oldname [LOG_NAME_SIZE]; char temp_newname [LOG_NAME_SIZE]; for(int i = log_cnt; i< = 0; --i) { if(sprintf(temp_oldname,LOG_NAME,i)< 0) { perror( SPRINTF ERROR oldname :: S2 --case b\ n;) 退出(EXIT_FAILURE); } if(sprintf(temp_newname,LOG_NAME,(i + 1))< 0) { perror(" SPRINTF ERROR newname :: S2 --case b\ n; 退出(EXIT_FAILURE); } printf(" i =%d \\ \\ n",i); printf(" temp_oldname =%s \ n",temp_oldname); printf(" temp_newname =%s \ n" ;,temp_newname); printf(" ---------------------- -------------------------------------------------- --------- \ n\\\"); system(" ls"); if(rename(temp_oldname,temp_newname) < 0) { perror(RENAME ERROR :: S2 --case b); 退出(EXIT_FAILURE); } system(" ls"); printf(" --------------- -------------------------------------------------- ---------------- \ n\\\"); } //创建0.log if(sprintf(log_name,LOG_NAME,0)< 0) { perror(" SPRINTF ERROR :: S2 --case b \ n"); 退出(EXIT_FAILURE); } //打开文件并附加数据 if(!(fp = fopen(log_name," a")))// S2 - 案例a { perror(" FOPEN() ERROR whne log_cnt == 0"); 退出(EXIT_FAILURE); } if(fwrite(log_recv_arr,1 ,log_recv_size,fp)!= log_recv_size) { perror(log_cnt中的FWRIRE ERROR == 0); 退出( EXIT_FAILURE); } if(fclose(fp)) { perror(第187行附近的FLOSE()错误); 退出(EXIT_FAILURE); } //更新log_size if(! (stat(log_name,& statbuf))) { log_size =(long)statbuf.st_size; } printf("%s write =%ld \ n \ n",log_name,log_size); //更新log_cnt if(log_size> = LOG_SIZE) { ++ log_cnt; printf(" log_cnt =% d \ n",log_cnt); if(sprintf(log_name,LOG_NAME,log_cnt)< 0) { perror( SPRINTF ERROR :: S2 - case b(END)\ n); 退出(EXIT_FAILURE); } } } // S2< - 案例b } * / // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^ // R. ENAM E FILE S // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $〜$ b - b - ~~ $ b - b - www.lispmachine.wordpress.com 我的电子邮件是@上面的博客 查看关于我自己页面 解决方案 8月11日,07:46,arnuld< sunr ... @ invalid.addresswrote: 我创建了一个创建和重命名文件的程序。我有 描述了评论中的所有内容。 *我所拥有的只是 cod-duplication。像fopen,sprint和fwrite这样的函数被一次又一次地称为。 我知道删除代码重复我必须创建函数并传递 他们的参数,但我无法想到这样做的方式。你可以给我发一些例子吗? < snip waffly comments> > < snip code> 你有一个600行的主要功能!!!! 作为规则拇指开始问自己这个功能是否可以分开 分数为10到20美元。一个50行的功能并不总是错的(例如,大的 开关 声明)但是闹铃应该响了。 步骤1编写一个测试程序,验证您的程序是否正确。 或许基于此骨架 / *对记录器运行测试 日志目录包含测试前的in文件 读取数据目录中的数据 日志目录应该包含相同的文件as out 目录 * / void run_log_test(const char * test_name) { char test_dir_in [80]; char test_dir_out [80]; sprintf(test_dir_in," test%s / in",test_name); sprintf(test_dir_dat," test%s / data",test_name); sprintf(test_dir_out," test%s / out",test_name); clear_log_directory(); copy(test_dir_in,log); read_data(test_dir_dat); match_dir(log,test_dir_out); / *调用断言如果有任何文件 不匹配* / } void test_logger() { run_log_test(" 1"); run_log_test(" 2"); run_log_test(" 3); } 它应该被设计成你不必手动检查数据 -程序为你完成所有工作。 编写一些测试,验证它是否适用于各种 场景。 例如。没有0.log短输入(没有文件翻转) 0.log目前短输入 中输入(翻到1.log) 长输入(少于创建的最大日志文件) 非常长的输入(文件必须删除) 任何可能会给你的程序带来压力的事情 步骤2运行测试 步骤3识别重复代码的短位。 从重复代码创建函数。 调用代码重复的函数。 步骤4运行测试 目前你的代码纠缠不清难以挑选 简单的重复代码。 我会包装如下所示的呼叫 if(sprintf(log_name,LOG_NAME,log_cnt)< 0) { perror(" SPRINTF错误 - 靠近第217行); 退出(EXIT_FAILURE); } void make_name(char * log_name ,int log_cnt) { if(sprintf(log_name,LOG_NAME,log_cnt)< 0) { perror(SPRINTF ERROR - 第217行附近); 退出(EXIT_FAILURE); } } 这对你来说并不算太多。但是你需要给他们打电话。 同样fopen(),fwrite(),fclose()。 根据经验,如果你发现自己使用了块评论 就像 // ================================================== ======================= * =========== // ==========================重新命名机制=========== ============================= t母鸡是*乞求*变成一个功能。即使 如果它只出现一次会简化你的主要。 这似乎好像出现几次 //打开文件并追加数据 if(!(fp = fopen(log_name," a")))// S2 - case a { perror(" FOPEN()ERROR whne log_cnt == 0"); 退出(EXIT_FAILURE); } if(fwrite(log_recv_arr,1,log_recv_size,fp)!= log_recv_size) { perror (log_cnt中的FWRIRE错误== 0); 退出(EXIT_FAILURE); } if(fclose (fp)) { perror(第187行附近的FLOSE()错误); 退出(EXIT_FAILURE); } //更新log_size if(! (stat(log_name,& statbuf))) { log_size =(long)statbuf.st_size; } printf("%s write =%ld \ n \ n",log_name,log_size); //更新log_cnt if((log_size + log_recv_size)> = LOG_SIZE) { ++ log_cnt; } 尝试识别更高级别的功能。以下代码是 未编译。 int main(无效) { FILE * stream; get_log_stream(stream); / * TBD * / process_log_data(stream); 返回0; } void process_log_data(FILE * stream) { int log_cnt = 0; int i; FILE * curr_log; 而(more_stuff) { if(!log_file_exists(0)) create_log(0); curr_log = open_log(0); if(store_records(curr_log,stream)== STREAM_EMPTY) 返回; / *当前日志全部 - 移至下一个日志* / fclose(curr_log); / *重命名日志* / for(i = log_cnt; i> = 0 i--) rename_log(i,i + 1); log_cnt ++; / * TBD处理太多日志文件* / } } / *存储在当前日志中记录,直到 - 流耗尽 - 日志已满 * / Store_result store_records(curr_log,stream) { / * TBD * / } / * primitives * / int log_file_exists(int n) { FILE * f; make_name(n) if((f = fopen(make_name(n)," w")= = NULL) 返回FALSE; fclose(f) 返回TRUE; } char * make_name(int n) { 静态名称[80]; sprintf(名称, LOG_NAME,n); 返回姓名; } 仍然相当凌乱,但我可能反其道而行 $ b $对你的方式。您编写了代码页然后认为 我如何模块化这个?。我想这是什么节目 试图做到这一点以及它能做什么功能 我很容易写出来。 我很快意识到我想打开文件,重命名文件等。 所以目前process_log_data代表程序的内容。 log renmae循环可能会进入函数 和处理太多日志。 - Nick Keighley 2008-08-11,Nick Keighley< ni ****************** @ hotmail.comwrote: I''d" wrapper"如下所示的呼叫 if(sprintf(log_name,LOG_NAME,log_cnt)< 0) { perror(" SPRINTF错误 - 靠近第217行); 退出(EXIT_FAILURE); } void make_name(char * log_name ,int log_cnt) { if(sprintf(log_name,LOG_NAME,log_cnt)< 0) { perror(SPRINTF ERROR - 第217行附近); 退出(EXIT_FAILURE); } } 这对你来说并不算太多。但是你需要给他们打电话。 同样fopen(),fwrite(),fclose()。 What *would* save him a lot, if the code is designed to always display an error message and exit, would be to have a macro/function combination: /* Start */ #ifdef DEBUG #define DBG(msg) _err( msg, "DEBUG", __func__, 0) #else #define DBG(msg) #endif #define ERR(msg) _err(msg, "ERROR", __func__, 0) #define DIE(msg) _err(msg, "FATAL", __func__, 1) void _err(const char *error_msg, const char *severity, const char *caller, char bool_terminate) { if(error_msg != NULL) fprintf(stderr, "%s: %s: %s\n", severity, caller, error_msg); if(bool_terminate) exit(EXIT_FAILURE); } /* End */ For most projects, I can put that verbatim into a header file, and from there almost all of my error-checking can be reduced to something like: if((buff = malloc(sizeof buff)) == NULL) DIE("Out of memory!"); Then if I decided not to terminate, but to change tactics and attempt using a pre-allocated buffer, or a file, or whatever, it’’s a simple matter t o change DIE to an ERR or DBG, which won’’t terminate the program, and then insert my recovery code. On a related note, it’’s generally bad code design to terminate a program on error, unless the error in question is, for example, a failure to open a critical configuration file. Depending how important stability is (or how volatile your environment is!), you can use stdin or stdout in lieu of a failed file access, use static buffers (or disk files) in lieu of failed memory allocation, and in many cases, you can skip over sections of code entirely without critically hurting program flow. If you prompt the user in these cases, he’’ll likely be very impressed, and relieved that any work the program was in the middle of was not lost. Having said that, don’’t go too far: having your program output "Printing contents of program memory - please take page to another computer, run the program with the --recover flag, and type it all in" is NOT recommended! arnuld wrote: \t\t \t\t\t\t> I have created a program which creates and renames files. I have described everything in comments. All I have is the cod-duplication. function like fopen, sprint and fwrite are being called again and again. I know to remove code-duplication I have to make functions and pass arguments to them but I am not able to think of a way doing it. Can you post some example for me, out of this code: Throw it away. Write simple code, with short functions. Such as: int main(int argc, char **argv) { if (initialize(...)) { if (readdata(...)) { if (writedata(...)) { if (goodclose(...)) return 0; } } } return EXIT_FAILURE; } Now you have to write the functions referenced, and set up the parameters passed. You also have to add the necessary #includes, and appropriate data objects. You can make temporary function to test things, such as: int initialize(...) { puts("Initializing"); return 1; } and test things. The idea is to start compiling and testing as soon as possible, then revise to make it do what you want. Also note how easy it is to separate things out into separate source files that do useful things. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.I have created a program which creates and renames files. I havedescribed everything in comments. All I have is thecod-duplication. function like fopen, sprint and fwrite are being calledagain and again. I know to remove code-duplication I have to make functions and passarguments to them but I am not able to think of a way doing it. Can youpost some example for me, out of this code: /* The Logging program: * A programs that will take input from stdin and put that into log files.* using C99 (GNU-Linux/UNIX specific extensions may be there)** VERSION 1.0*Each log file is of fixed size called LOG_SIZE, if input from stdin is more thanLOG_SIZE then we will write the date to 2nd file. file naming convention is %d.log,e.g. 1.log, 2.log , 3.log etc. We have 3 scenerios: 1) if we already have 0.log and (new incoming data + sizeof(0.log)) is less thanLOG_SIZE then we will write the data to 0.log. otherwise we wil go to scenerionumber 2.2) if we have 0.log filled with size LOG_SIZE, then we will rename it to 1.log andcreate a new file 0.log and feed the new data into it. Hence largest the numberoldest is the file. 3) Number of log-files are to be kept less than LOG_CNT_MAX, if we hit the LOG_CNT_MAXthen we we will delete the oldest file, rename the files to new numbers and createa new file to write data. e.g. if LOG_CNT_MAX = 3 and we have 0.log, 1.log, 2.logfilled with data of LOG_SIZE, then we will not create 3.log but we will delete 2.logand rename 1.log to 2.log and 0.log to 1.log respectively and create a new 0.log towrite data. thats the whole basic idea of my logging system.*/ #include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include <dirent.h>#include <errno.h> #define LOG_NAME "%d.log"#define LOG_DIR "."#define TRUE 1#define FALSE 0 enum { LOG_NAME_SIZE = 6, LOG_SIZE = 6, LOG_CNT_MAX = 30, LOG_BASE_NUM = 0 };int find_log_num( const char * ); /* LOG_NAME_SIZE is the size of LOG_NAME in bytes * LOG_CNT_MAX is the maximum number of log files to be kept on the system * LOG_SIZE is the size of log file. * LOG_INPUT_MAX is also the maximum input that a client-log is supposed to send.* if the log-input is more than LOG_INPUT_MAX, then it means we are not having a log file* but either a system bug or malicious intentions of some SPAMMER. So refuse the baby to* access your system ;)* * If you insist on using this file as a separate program running in main() then make sureLOG_CNT_MAX and "i" in main for loop are in COMPLETE HARMONY***/int main( void ){// char log_arr[LOG_SIZE];const char log_recv_arr[] = "Love\n";char log_name[LOG_NAME_SIZE];long log_size;int log_cnt;FILE *fp;size_t log_recv_size;int BACKUP; /* directory and file manipulation variables */struct stat statbuf; /* initialize arrays */memset( log_name, ''\0'', LOG_NAME_SIZE);log_size = 0;log_recv_size = strlen( log_recv_arr );// printf("INPUT IS: %s\n\n", log_recv_arr);log_cnt = 0;printf("log_cnt = %d\n", log_cnt); for( int i = 0; i != LOG_CNT_MAX ; ++i ){if( sprintf(log_name, LOG_NAME, i) < 0 ){perror("SPRINTF ERROR - (BEGIN PROGRAM)");exit( EXIT_FAILURE );} if( ! (stat(log_name, &statbuf)) ){log_cnt = i;}else if( ENOENT == errno ){continue;}else{perror("STAT ERROR");exit( EXIT_FAILURE );}} printf("--- log_cnt = %d\n", log_cnt);if( log_cnt ){BACKUP = TRUE;}else{BACKUP = FALSE;}// we have the log_cnt, which means file exists, so we can find its sizeif( sprintf(log_name, LOG_NAME, log_cnt) < 0 ){perror("SNPRINTF ERROR - after search loop");exit( EXIT_FAILURE );} if( ! (stat(log_name, &statbuf)) ){log_size = (long) statbuf.st_size;}else{log_size = 0;} printf("%s = %ld\n", log_name, log_size); /* start Logging */for(int i = 0 ; i != 8; ++i){printf("\n\nLOOP #%d\n", i); if( !log_cnt ) // S1 -- begin{/* There are 2 sub-cases here: 1) 0.log does not exist, we create a new one. since we created a fresh file, hence we are sure that size of fresh fileis == LOG_SIZE, so we don''t need any check before writing to it. aftercreating the file we need to check how much data we have written. filesize == LOG_SIZE --create a new filename, probably 1.logfilesize < LOG_SIZE --go for input once more2) 0.log exists but size is less than LOG_SIZE (filesize + received data) <= LOGSIZE --write dataELSE --create anew file*/printf("--------------- Into SCENERIO (1) :: log_cnt == 0 -----------------\n\n"); // log_size == 0 means we have no backup files, hence we will do a fresh log// or else we can use BACKUP flagif( ! log_size ) // S1 1st case{printf("Entered 1st case\n");printf("File does not exist, Creating a new one\n"); // In future, it will be a function: create_log_name( log_name );if( sprintf(log_name, LOG_NAME, log_cnt) < 0 ){perror("SPRINTF ERROR -- near line 217");exit( EXIT_FAILURE );} // In future, it will be a function: write_data( log_name );if( NULL == (fp = fopen(log_name, "a")) ){perror("FOPEN() EROR");exit( EXIT_FAILURE );} if( (fwrite(log_recv_arr, 1, log_recv_size, fp)) != log_recv_size ){perror("FWRITE() ERROR");exit( EXIT_FAILURE );} if( fclose(fp) ){perror("FLOSE() ERROR near line 219");exit( EXIT_FAILURE );}// update log_sizeif( ! (stat(log_name, &statbuf)) ){log_size = (long)statbuf.st_size;} printf(" %s written = %ld\n\n", log_name, log_size); if( log_size LOG_SIZE ){perror("YOU STUPID MORON .... 1st case (END)");exit( EXIT_FAILURE );}} // S1 1st case else if( (log_size + log_recv_size) <= LOG_SIZE )//S1 --2nd case{printf("Entered 2nd case\n");printf("File exists\n");printf("%s size = %ld\n", log_name, log_size);/* open file and append the data */if( ! (fp = fopen(log_name, "a")) ){perror("FOPEN() ERROR whne log_cnt == 0");exit( EXIT_FAILURE );} if( fwrite(log_recv_arr, 1, log_recv_size, fp) != log_recv_size ){perror("FWRIRE ERROR in log_cnt == 0");exit( EXIT_FAILURE );} if( fclose(fp) ){perror("FLOSE() ERROR near line 187");exit( EXIT_FAILURE );} /* update log_size */if( ! (stat(log_name, &statbuf)) ){log_size = (long) statbuf.st_size;} printf("%s written = %ld\n\n", log_name, log_size);} // S1 <-- 2nd case else if( (log_size + log_recv_size) LOG_SIZE ) // S1 --3rd case{printf("Entered 3rd case\n");printf("%s = %ld\n", log_name, log_size);++log_cnt;} } // if( !log_cnt ) S1 <--- END// SCENERIO (2)else if( (log_cnt 0) && (log_cnt < LOG_CNT_MAX) )//log_cnt < LOG_CNT_MAX ) // S2 --begin{ /* Entering into this condition means we are definitely sure that 0.log has beeneither filled or size of (new input + size of (0.log)) is LOG_SIZE. NOTE: 1st of all we will move the log files. we will reach at 1.log with final move.we will create an empty 0.log file and then proceed as usual. sinec ewe have fresh file, 0.log, we can fit all the data into it as, because of the ENUMconstants above, we are sure the data will always be <= LOG_SIZE */ printf("------------------- Into SCENERIO (2) -------------------\n");printf("log_cnt = %d\n", log_cnt); if( ! (stat(log_name, &statbuf)) ){log_size = (long) statbuf.st_size;} printf("Oldest %s exists with size = %ld bytes\n", log_name, log_size);printf( "BACKUP = %d\n", BACKUP); /* move_log( log_cnt - 1 )log_create( 0 );*/ //================================================== ==================================//========================== RENAME MECHANISM ======================================== int backup_cnt; if( BACKUP ){backup_cnt = log_cnt + 1;}else{backup_cnt = log_cnt;} char temp_oldname[LOG_NAME_SIZE];char temp_newname[LOG_NAME_SIZE]; for( int i = backup_cnt; (i LOG_BASE_NUM) && (i < LOG_CNT_MAX); --i ){if( sprintf(temp_oldname, LOG_NAME, i-1) < 0 ){perror("SPRINTF ERROR oldname :: S2 --case b\n");exit( EXIT_FAILURE );} if( sprintf(temp_newname, LOG_NAME, i ) < 0 ){perror("SPRINTF ERROR newname :: S2 --case b\n");exit( EXIT_FAILURE );} printf("i = %d\n", i );printf("temp_oldname = %s\n", temp_oldname);printf("temp_newname = %s\n", temp_newname); if( rename(temp_oldname, temp_newname) < 0 ){perror("RENAME ERROR :: S2 --case b");exit( EXIT_FAILURE );}else{printf("renamed <%sto <%s>\n", temp_oldname, temp_newname);//sleep(2);}}// create 0.logif( sprintf(log_name, LOG_NAME, LOG_BASE_NUM) < 0 ){perror("SPRINTF ERROR :: S2 --case b\n");exit( EXIT_FAILURE );}// open file and append the dataif( ! (fp = fopen(log_name, "a")) ) // S2 -- case a{perror("FOPEN() ERROR whne log_cnt == 0");exit( EXIT_FAILURE );} if( fwrite(log_recv_arr, 1, log_recv_size, fp) != log_recv_size ){perror("FWRIRE ERROR in log_cnt == 0");exit( EXIT_FAILURE );} if( fclose(fp) ){perror("FLOSE() ERROR near line 187");exit( EXIT_FAILURE );} // update log_sizeif( ! (stat(log_name, &statbuf)) ){log_size = (long) statbuf.st_size;} printf("%s written = %ld\n\n", log_name, log_size); // update the log_cntif( (log_size + log_recv_size) >= LOG_SIZE ){++log_cnt;} //========================== RENAME MECHANISM ========================================//================================================== ==================================} // S2 begin ends// SCENERIO (3)else // log_cnt >= LOG_CNT_MAX{printf("------------------- Into SCENERIO (3) -------------------\n"); printf("log_cnt = %d, LOG_CNT_MAX = %d\n", log_cnt, LOG_CNT_MAX); if( ! (stat(log_name, &statbuf)) ){log_size = (long) statbuf.st_size;} printf("Oldest %s exists with size = %ld bytes\n", log_name, log_size);printf( "BACKUP = %d\n", BACKUP); /* well here we are log_cnt >= LOG_CNT_MX. We will simply do 3 things: 1) Delete the oldest file, which is (LOG_CNT_MAX - 1).log2) Rename all files3) create 0.log name4) create 0.log file5) write data*///================================================== ==================================//========================== RENAME MECHANISM ======================================== int backup_cnt = log_cnt - 1; char temp_oldname[LOG_NAME_SIZE];char temp_newname[LOG_NAME_SIZE]; for( int i = backup_cnt; (i LOG_BASE_NUM) && (i < LOG_CNT_MAX); --i ){if( sprintf(temp_oldname, LOG_NAME, i-1) < 0 ){perror("SPRINTF ERROR oldname :: S2 --case b\n");exit( EXIT_FAILURE );} if( sprintf(temp_newname, LOG_NAME, i ) < 0 ){perror("SPRINTF ERROR newname :: S2 --case b\n");exit( EXIT_FAILURE );} printf("i = %d\n", i );printf("temp_oldname = %s\n", temp_oldname);printf("temp_newname = %s\n", temp_newname); if( rename(temp_oldname, temp_newname) < 0 ){perror("RENAME ERROR :: S2 --case b");exit( EXIT_FAILURE );}else{printf("renamed <%sto <%s>\n", temp_oldname, temp_newname);//sleep(2);}}// create 0.logif( sprintf(log_name, LOG_NAME, LOG_BASE_NUM) < 0 ){perror("SPRINTF ERROR :: S2 --case b\n");exit( EXIT_FAILURE );}// open file and append the dataif( ! (fp = fopen(log_name, "a")) ) // S2 -- case a{perror("FOPEN() ERROR whne log_cnt == 0");exit( EXIT_FAILURE );} if( fwrite(log_recv_arr, 1, log_recv_size, fp) != log_recv_size ){perror("FWRIRE ERROR in log_cnt == 0");exit( EXIT_FAILURE );} if( fclose(fp) ){perror("FLOSE() ERROR near line 187");exit( EXIT_FAILURE );} // update log_sizeif( ! (stat(log_name, &statbuf)) ){log_size = (long) statbuf.st_size;} printf("%s written = %ld\n\n", log_name, log_size); // No need to update the log_cnt as log_cnt == LOG_CNT_MAX//========================== RENAME MECHANISM ========================================//================================================== ==================================/*if( ! (stat(log_name_old, &statbuf)) ){log_size = (long) statbuf.st_size;}printf("File %s exists with size = %ld bytes\n", log_name, log_size);printf("// code yet to be written\n\n");*/} } // for( ... ) loopreturn 0;} // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^// R . E. N. A. M. E F. I. L. E. S// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~/*char temp_oldname[LOG_NAME_SIZE];char temp_newname[LOG_NAME_SIZE]; for( int i = log_cnt; i <= 0; --i ){if( sprintf(temp_oldname, LOG_NAME, i) < 0 ){perror("SPRINTF ERROR oldname :: S2 --case b\n");exit( EXIT_FAILURE );} if( sprintf(temp_newname, LOG_NAME, (i + 1) ) < 0 ){perror("SPRINTF ERROR newname :: S2 --case b\n");exit( EXIT_FAILURE );} printf("i = %d\n", i );printf("temp_oldname = %s\n", temp_oldname);printf("temp_newname = %s\n", temp_newname); printf("---------------------------------------------------------------------------------\n\n");system("ls");if( rename(temp_oldname, temp_newname) < 0 ){perror("RENAME ERROR :: S2 --case b");exit( EXIT_FAILURE );}system("ls");printf("---------------------------------------------------------------------------------\n\n");}// create 0.logif( sprintf(log_name, LOG_NAME, 0) < 0 ){perror("SPRINTF ERROR :: S2 --case b\n");exit( EXIT_FAILURE );}// open file and append the dataif( ! (fp = fopen(log_name, "a")) ) // S2 -- case a{perror("FOPEN() ERROR whne log_cnt == 0");exit( EXIT_FAILURE );} if( fwrite(log_recv_arr, 1, log_recv_size, fp) != log_recv_size ){perror("FWRIRE ERROR in log_cnt == 0");exit( EXIT_FAILURE );} if( fclose(fp) ){perror("FLOSE() ERROR near line 187");exit( EXIT_FAILURE );} // update log_sizeif( ! (stat(log_name, &statbuf)) ){log_size = (long) statbuf.st_size;} printf("%s written = %ld\n\n", log_name, log_size); // update the log_cntif( log_size >= LOG_SIZE ){++log_cnt;printf("log_cnt = %d\n", log_cnt);if( sprintf(log_name, LOG_NAME, log_cnt) < 0 ){perror("SPRINTF ERROR :: S2 --case b (END) \n");exit( EXIT_FAILURE );}}} // S2 <-- case b }*/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^// R . E. N. A. M. E F. I. L. E. S// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~ -- www.lispmachine.wordpress.commy email is @ the above blogcheck the "About Myself" page 解决方案 On 11 Aug, 07:46, arnuld <[email protected]: I have created a program which creates and renames files. I havedescribed everything in comments. *All I have is thecod-duplication. function like fopen, sprint and fwrite are being calledagain and again.I know to remove code-duplication I have to make functions and passarguments to them but I am not able to think of a way doing it. Can youpost some example for me, out of this code:<snip waffly comments> <snip code> you have a 600-line main function!!!! As a rule of thumb start to ask yourself if the function could besplitat say 10-20 lines. A 50 line function isn''t always wrong (eg. bigswitchstatement) but an alarm bell should be ringing. Step 1 write a test program that verifies your program is correct.Perhaps base it on this skeleton /* runs a test on the loggerthe log directory contains the in files before the testthe data from the data directory is readthe log directory should containing the same files as the outdirectory*/void run_log_test (const char *test_name){char test_dir_in [80];char test_dir_out [80];sprintf (test_dir_in, "test%s/in", test_name);sprintf (test_dir_dat, "test%s/data", test_name);sprintf (test_dir_out, "test%s/out", test_name); clear_log_directory();copy (test_dir_in, log);read_data (test_dir_dat);match_dir (log, test_dir_out); /* calls assert if any filesdon''t match */} void test_logger(){run_log_test ("1");run_log_test ("2");run_log_test ("3");} it should be designed so you don''t have to check databy hand- the program does it all for you. Write some tests that verify it behaves correctly for variousscenarios. eg. no 0.log short input (no file roll-over)0.log present short inputmedium input (rolls over to 1.log)long input (less than log max files created)very long input (files have to be deleted)anything else that might stress your program step 2 run the testsstep 3 identify short bits of repetitive code.create functions from the repeated code.call the functions where the code was repeated. step 4 run the test At the moment your code is so tangled its hard to pick outsimple bits of repetitive code. I''d "wrapper" calls like these if( sprintf(log_name, LOG_NAME, log_cnt) < 0 ){perror("SPRINTF ERROR -- near line 217");exit( EXIT_FAILURE );} void make_name (char *log_name, int log_cnt){if( sprintf(log_name, LOG_NAME, log_cnt) < 0 ){perror("SPRINTF ERROR -- near line 217");exit( EXIT_FAILURE );}} which doesn''t save you much but you call them a lot.Similarly fopen(), fwrite(), fclose(). As a rule of thumb if you find yourself using block commentslike //================================================== =======================*===========//========================== RENAME MECHANISM ======================================== then that is *begging* to be turned into a function. Evenif it only appears once it will simplify you main. This seems to appear a few times // open file and append the data if( ! (fp = fopen(log_name, "a")) ) // S2 -- case a { perror("FOPEN() ERROR whne log_cnt == 0"); exit( EXIT_FAILURE ); } if( fwrite(log_recv_arr, 1, log_recv_size, fp) != log_recv_size ) { perror("FWRIRE ERROR in log_cnt == 0"); exit( EXIT_FAILURE ); } if( fclose(fp) ) { perror("FLOSE() ERROR near line 187"); exit( EXIT_FAILURE ); } // update log_size if( ! (stat(log_name, &statbuf)) ) { log_size = (long) statbuf.st_size; } printf("%s written = %ld\n\n", log_name, log_size); // update the log_cnt if( (log_size + log_recv_size) >= LOG_SIZE ) { ++log_cnt; } Try to identify higher level funtionality. The following code isuncompiled.int main (void){FILE *stream;get_log_stream(stream); /* TBD */process_log_data(stream);return 0;} void process_log_data(FILE *stream){int log_cnt = 0;int i;FILE *curr_log; while (more_stuff){if (!log_file_exists(0))create_log(0); curr_log = open_log(0); if (store_records (curr_log, stream) == STREAM_EMPTY)return; /* current log full- move to next log */fclose(curr_log); /* rename logs */for (i = log_cnt; i >= 0 i--)rename_log (i, i + 1); log_cnt++; /* TBD handle too many log files */}}/* store recored in the current log until either- stream exhauseted- log full*/ Store_result store_records (curr_log, stream){/* TBD */} /* primitives */int log_file_exists (int n){FILE *f;make_name(n)if ((f = fopen(make_name(n), "w") == NULL)return FALSE;fclose(f)return TRUE;} char *make_name(int n){static name[80];sprintf (name, LOG_NAME, n);return name;}still rather messy but I probably did it the oppositeway to you. You wrote pages of code and then thought"how do I modularise this?". I thought "what is the programtrying to do it and what functions whould make iteasy for me to write it". I quickly realise I want to open files, rename files etc. So at the moment process_log_data represents the guts of the program.The log renmae loop should probably go into a functionand the handling of too many logs.--Nick KeighleyOn 2008-08-11, Nick Keighley <ni******************@hotmail.comwrote:I''d "wrapper" calls like theseif( sprintf(log_name, LOG_NAME, log_cnt) < 0 ){ perror("SPRINTF ERROR -- near line 217"); exit( EXIT_FAILURE );}void make_name (char *log_name, int log_cnt){ if( sprintf(log_name, LOG_NAME, log_cnt) < 0 ) { perror("SPRINTF ERROR -- near line 217"); exit( EXIT_FAILURE ); }}which doesn''t save you much but you call them a lot.Similarly fopen(), fwrite(), fclose(). What *would* save him a lot, if the code is designed to always displayan error message and exit, would be to have a macro/function combination: /* Start */ #ifdef DEBUG#define DBG(msg) _err(msg, "DEBUG", __func__, 0)#else#define DBG(msg)#endif#define ERR(msg) _err(msg, "ERROR", __func__, 0)#define DIE(msg) _err(msg, "FATAL", __func__, 1)void _err(const char *error_msg,const char *severity,const char *caller,char bool_terminate){if(error_msg != NULL)fprintf(stderr, "%s: %s: %s\n", severity, caller, error_msg);if(bool_terminate)exit(EXIT_FAILURE);} /* End */ For most projects, I can put that verbatim into a header file, and fromthere almost all of my error-checking can be reduced to something like: if((buff = malloc(sizeof buff)) == NULL)DIE("Out of memory!"); Then if I decided not to terminate, but to change tactics and attemptusing a pre-allocated buffer, or a file, or whatever, it''s a simplematter to change DIE to an ERR or DBG, which won''t terminate theprogram, and then insert my recovery code.On a related note, it''s generally bad code design to terminate aprogram on error, unless the error in question is, for example, afailure to open a critical configuration file. Depending how importantstability is (or how volatile your environment is!), you can use stdinor stdout in lieu of a failed file access, use static buffers (or diskfiles) in lieu of failed memory allocation, and in many cases, you canskip over sections of code entirely without critically hurting programflow. If you prompt the user in these cases, he''ll likely be very impressed,and relieved that any work the program was in the middle of was notlost. Having said that, don''t go too far: having your program output"Printing contents of program memory - please take page to anothercomputer, run the program with the --recover flag, and type it all in"is NOT recommended! arnuld wrote:>I have created a program which creates and renames files. I havedescribed everything in comments. All I have is thecod-duplication. function like fopen, sprint and fwrite are beingcalled again and again.I know to remove code-duplication I have to make functions andpass arguments to them but I am not able to think of a way doingit. Can you post some example for me, out of this code:Throw it away. Write simple code, with short functions. Such as: int main(int argc, char **argv) {if (initialize(...)) {if (readdata(...)) {if (writedata(...)) {if (goodclose(...)) return 0;}}}return EXIT_FAILURE;} Now you have to write the functions referenced, and set up theparameters passed. You also have to add the necessary #includes,and appropriate data objects. You can make temporary function totest things, such as: int initialize(...) {puts("Initializing");return 1;} and test things. The idea is to start compiling and testing assoon as possible, then revise to make it do what you want. Alsonote how easy it is to separate things out into separate sourcefiles that do useful things. --[mail]: Chuck F (cbfalconer at maineline dot net)[page]: <http://cbfalconer.home.att.net>Try the download section. 这篇关于如何删除代码重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-27 21:12