我有遗留的C代码库,我在下面的样式中找到了很多函数实现。
char *DoStuff(char *inPtr, char *outPtr, char *error, long *amount)
{
*error = 0;
*amount = 0;
// Read bytes from inPtr and decode them as a long storing in amount
// before returning as a formatted string in outPtr.
return (outPtr);
}
使用DoStuff:
myOutPtr = DoStuff(myInPtr, myOutPtr, myError, &myAmount);
我觉得非常迟钝,当我需要实现类似的功能时,我最终会这样做:
long NewDoStuff(char *inPtr, char *error)
{
long amount = 0;
*error = 0;
// Read bytes from inPtr and decode them as a long storing in amount.
return amount;
}
使用NewDoStuff:
myAmount = NewDoStuff(myInPtr, myError);
myOutPtr += sprintf (myOutPtr, "%d", myAmount);
我不禁想知道顶级例子中是否有一些我缺少的东西,是否有充分的理由使用这种方法?
答案 0 :(得分:1)
这是C标准库样式。返回值用于辅助函数调用的链接。
此外,DoStuff
是更清洁的IMO。你真的应该使用snprintf
。缓冲区管理内部的更改不会影响您的代码。但是,NewDoStuff
已不再适用。
答案 1 :(得分:1)
一个优点是,如果您的代码中有很多次调用这些函数,那么一遍又一遍地重复sprintf
次调用将很快变得乏味。
此外,返回out指针使您可以执行以下操作:
DoOtherStuff(DoStuff(myInPtr, myOutPtr, myError, &myAmount), &myOther);
使用您的新方法,等效代码非常详细:
myAmount = DoNewStuff(myInPtr, myError);
myOutPtr += sprintf("%d", myAmount);
myOther = DoOtherStuff(myInPtr, myError);
myOutPtr += sprintf("%d", myOther);
答案 2 :(得分:0)
您提供的代码有点不清楚(例如,为什么要使用sprintf的结果添加myOutPtr。
然而,一般来说,你实际上描述的是将一个函数分解为一个函数的函数,该函数执行一个事务,一个代码执行其他操作(连接)。
将责任分为两个功能是一个好主意。但是,您可能希望为此连接和格式设置单独的功能,但实际上并不清楚。
此外,每次将函数调用分解为多个调用时,都会创建代码复制。代码复制永远不是一个好主意,所以你需要一个函数来做到这一点,你最终会(这是C)看起来像你的原始DoStuff。
所以我不确定你能做些什么呢。非OOP语言的一个限制是您必须发送大量参数(除非您使用了结构)。你可能无法避开巨大的界面。
答案 3 :(得分:0)
如果你在每次调用NewDoStuff之后都要进行sprintf调用,那么你就是在重复自己(因此违反了DRY原则)。当您意识到需要以不同方式对其进行格式化时,您需要在每个位置更改它而不仅仅是一个位置。
答案 4 :(得分:0)
根据经验,如果我的一个函数的接口超过110列,我强烈期待使用一个结构(如果我采用最好的方法)。我不想做的就是使用一个函数来完成5件事并将其分解为5个函数,除非函数中的某些功能不仅有用,而且需要它自己。
我赞成第一个功能,但我也很习惯标准的C风格。