如何删除代码重复 [英] how to remove code duplication

查看:56
本文介绍了如何删除代码重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个创建和重命名文件的程序。我有

描述了评论中的所有内容。我所拥有的只是

cod-duplication。像fopen,sprint和fwrite这样的函数被一次又一次地称为



我知道删除代码重复我必须创建函数并传递

他们的参数,但我无法想到这样做的方式。你可以给我发b
给我一些例子吗,这个代码:



/ *记录程序:

*一个程序将从stdin获取输入并将其放入日志文件中。

*使用C99(可能存在GNU-Linux / UNIX特定扩展)

*

* VERSION 1.0

*

如果stdin的输入超过
LOG_SIZE然后我们将日期写入第二个文件。文件命名约定是%d.log,

例如1.log,2.log,3.log等


我们有3个场景:


1)如果我们已经有0。 log和(新传入数据+ sizeof(0.log))小于

LOG_SIZE然后我们将数据写入0.log。否则我们将转到scenerio

数字2.

2)如果我们有0.log填充大小LOG_SIZE,那么我们将它重命名为1.log和

创建一个新文件0.log并将新数据输入其中。因此最大的数字

最旧的是文件。


3)如果我们点击LOG_CNT_MAX,日志文件的数量应保持小于LOG_CNT_MAX

然后我们将删除最旧的文件,将文件重命名为新数字并创建

a新文件来写入数据。例如如果LOG_CNT_MAX = 3并且我们有0.log,1.log,2.log

填充了LOG_SIZE的数据,那么我们将不会创建3.log但我们将删除2.log

并将1.log分别重命名为2.log并将0.log重命名为1.log并创建一个新的0.log以

写入数据。


是我记录系统的基本概念。

* /


#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是LOG_NAME的大小以字节为单位


* LOG_CNT_MAX是系统上保存的最大日志文件数


* LOG_SIZE的大小是日志文件。


* LOG_INPUT_MAX也是客户端日志应该发送的最大输入。

*如果日志输入超过LOG_INPUT_MAX ,那就意味着我们没有日志文件

*但是系统错误或某些SPAMMER的恶意。所以拒绝宝宝来支付你的系统; *

*


*如果你坚持使用这个文件作为在main()中运行的单独程序然后确保

LOG_CNT_MAX和i在主要循环中是完整的和谐

*

*

* /

int main(void)

{

// char log_arr [LOG_SIZE];

const char log_recv_arr [] =" Love \\\
";

char log_name [LOG_NAME_SIZE];

long log_size;

int log_cnt;

FILE * fp;

size_t log_recv_size;

int BACKUP;


/ *目录和文件操作变量* /

struct stat statbuf;


/ *初始化数组* /

memset(log_name,''\''',LOG_NAME_SIZE);

log_size = 0;

log_recv_size = strlen(log_recv_arr);

// printf(" INPUT IS:%s\\\
\ 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(&quo t; SPRINTF ERROR - (BEGIN PROGRAM)");

退出(EXIT_FAILURE);

}


if(! (stat(log_name,& statbuf)))

{

log_cnt = i;

}

else if(ENOENT == errno)

{

继续;

}

其他

{

perror(STAT ERROR);

退出(EXIT_FAILURE);

}

}


printf(" --- --- log_cnt =%d \ n",log_cnt);

if(log_cnt)

{

BACKUP = TRUE;

}

else

{

BACKUP = FALSE;

}

//我们有log_cnt,这意味着文件存在,所以我们可以找到它的大小

if(sprintf (log_name,LOG_NAME,log_cnt)< 0)

{

perror(" SNPRINTF ERROR - 搜索循环后);

退出(EXIT_FAILURE);

}


if(!(stat(log_name,& statbuf)))

{

log_size =(长)statbuf.st_size;

}

其他

{

log_size = 0;

}


printf("%s =%ld \ n",log_name,log_size);


/ * start记录* /

for(int i = 0;我!= 8; ++ i)

{

printf(" \\\
\\\
LOOP#%d \ n",i);


if(!log_cnt)// S1 - 开始

{

/ *这里有2个子案例:


1)0.log不存在,我们创建一个新的。


因为我们创建了一个新文件,因此我们确定新文件的大小

= = LOG_SIZE,所以在写入之前我们不需要任何检查。在创建文件后我们需要检查我们写了多少数据。


filesize == LOG_SIZE - 创建一个新的文件名,可能是1.log

filesize< LOG_SIZE - 再次输入

2)0.log存在,但是大小小于LOG_SIZE


(文件大小+接收数据)< = LOGSIZE - 写数据

ELSE - 创建一个新文件

* /

printf(" ---------- -----进入SCENERIO(1):: log_cnt == 0 ----------------- \ n \ n");


// log_size == 0表示我们没有备份文件,因此我们会做一个新的日志

//否则我们可以使用BACKUP标志

if (!log_size)// S1第一个案例

{

printf(输入第一个案例\ n);

printf(" ;文件不存在,创建一个新的\ n");


//将来,它将是一个函数:create_log_name(log_name);

if(sprintf(log_name,LOG_NAME,log_cnt)< 0)

{

perror(" SPRINTF ERROR - 217行附近);

退出(EXIT_FAILURE);

}


//在未来e,它将是一个函数:write_data(log_name);

if(NULL ==(fp = fopen(log_name," a")))

{

perror(FOPEN()EROR);

退出(EXIT_FAILURE);

}


if((fwrite(log_recv_arr,1,log_recv_size,fp))!= log_recv_size)

{

perror(" FWRITE()ERROR");

退出(EXIT_FAILURE);

}


if(fclose(fp))

{

perror(第219行附近的FLOSE()ERROR);

退出(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);


if(log_size LOG_SIZE)

{

perror(你这个蠢货......第一案(结束));

退出(EXIT_FAILURE);

}

} // S1第一种情况


else if((log_size + log_recv_size)< = LOG_SIZE)// S1 - 第二种情况

{

printf(输入第二案例\ n);

printf(" File exists\\\
;);

printf("%s size =%ld \ n",log_name,log_size);

/ *打开文件并附加数据* /

if(!(fp = fopen(log_name," 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);

}


/ * update log_size * /

if(! (stat(log_name,& statbuf)))

{

log_size =(long)statbuf.st_size;

}


printf("%s write =%ld \ n \ n",log_name,log_size);

} // S1< - 第二案例


else if((log_size + log_recv_size)LOG_SIZE)// S1 - 第三种情况

{

printf("输入第三种情况\ 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 - 开始

{


/ *进入这个条件意味着我们肯定确定0.log已经

填充或大小(新输入+大小为(0.log))是LOG_SIZE。


注意:首先我们将移动日志文件。我们将通过最终移动到达1.log。

我们将创建一个空的0.log文件,然后照常继续。


sinec ewe有新鲜感file,0.log,我们可以将所有数据都装入其中,因为上面的ENUM

常数,我们确信数据总是< = LOG_SIZE

* /


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:
< blockquote class =post_quotes>
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()。
< /blockquote>

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 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:


/* 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 than
LOG_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 than
LOG_SIZE then we will write the data to 0.log. otherwise we wil go to scenerio
number 2.
2) if we have 0.log filled with size LOG_SIZE, then we will rename it to 1.log and
create a new file 0.log and feed the new data into it. Hence largest the number
oldest is the file.

3) Number of log-files are to be kept less than LOG_CNT_MAX, if we hit the LOG_CNT_MAX
then we we will delete the oldest file, rename the files to new numbers and create
a new file to write data. e.g. if LOG_CNT_MAX = 3 and we have 0.log, 1.log, 2.log
filled with data of LOG_SIZE, then we will not create 3.log but we will delete 2.log
and rename 1.log to 2.log and 0.log to 1.log respectively and create a new 0.log to
write 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 sure
LOG_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 size
if( 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 file
is == LOG_SIZE, so we don''t need any check before writing to it. after
creating the file we need to check how much data we have written.

filesize == LOG_SIZE --create a new filename, probably 1.log
filesize < LOG_SIZE --go for input once more
2) 0.log exists but size is less than LOG_SIZE

(filesize + received data) <= LOGSIZE --write data
ELSE --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 flag
if( ! 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_size
if( ! (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 been
either 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 ENUM
constants 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.log
if( sprintf(log_name, LOG_NAME, LOG_BASE_NUM) < 0 )
{
perror("SPRINTF ERROR :: S2 --case b\n");
exit( EXIT_FAILURE );
}
// 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;
}

//========================== 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).log
2) Rename all files
3) create 0.log name
4) create 0.log file
5) 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.log
if( sprintf(log_name, LOG_NAME, LOG_BASE_NUM) < 0 )
{
perror("SPRINTF ERROR :: S2 --case b\n");
exit( EXIT_FAILURE );
}
// 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);

// 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( ... ) loop
return 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.log
if( sprintf(log_name, LOG_NAME, 0) < 0 )
{
perror("SPRINTF ERROR :: S2 --case b\n");
exit( EXIT_FAILURE );
}
// 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_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.com
my email is @ the above blog
check the "About Myself" page

解决方案

On 11 Aug, 07:46, arnuld <sunr...@invalid.addresswrote:

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:

<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 be
split
at say 10-20 lines. A 50 line function isn''t always wrong (eg. big
switch
statement) 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 logger
the log directory contains the in files before the test
the data from the data directory is read
the log directory should containing the same files as the out
directory
*/
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 files
don''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 data
by hand- the program does it all for you.

Write some tests that verify it behaves correctly for various
scenarios.

eg. no 0.log short input (no file roll-over)
0.log present short input
medium 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 tests
step 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 out
simple 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 comments
like

//
================================================== =======================*
===========

//========================== RENAME MECHANISM ========================================


then that is *begging* to be turned into a function. Even
if 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 is
uncompiled.
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 opposite
way to you. You wrote pages of code and then thought
"how do I modularise this?". I thought "what is the program
trying to do it and what functions whould make it
easy 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 function
and the handling of too many logs.
--
Nick Keighley


On 2008-08-11, Nick Keighley <ni******************@hotmail.comwrote:

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().

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 to 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:

>
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.


这篇关于如何删除代码重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆