通过使用无限循环避免重复行,是好还是坏?

问题描述 投票:1回答:4

我和K.N.一起学习C. King's C:一种现代方法,存在一个问题(Ch.06 - Prog.Project#4),它要求读者编写一个程序,根据交易计算经纪人的佣金,直到交易金额为0。

这是作者的实现:

float commission, value;

  printf("Enter value of trade: ");
  scanf("%f", &value);

  while (value != 0.0f) {
    if (value < 2500.00f)
      commission = 30.00f + .017f * value;
    else if (value < 6250.00f)
      commission = 56.00f + .0066f * value;
    else if (value < 20000.00f)
      commission = 76.00f + .0034f * value;
    else if (value < 50000.00f)
      commission = 100.00f + .0022f * value;
    else if (value < 500000.00f)
      commission = 155.00f + .0011f * value;
    else
      commission = 255.00f + .0009f * value;

    if (commission < 39.00f)
      commission = 39.00f;

    printf("Commission: $%.2f\n\n", commission);

    printf("Enter value of trade: ");
    scanf("%f", &value);
  }

但我想的不是两次写printf和scanf,而是使用无限的for循环,如下所示:

float value, commission;

for (;;) {
    printf("Enter value of trade: ");
    scanf("%f", &value);
    if (value == 0)
        break;

    if (value < 2500)
        commission = 30.00f + 0.017 * value;
    else if (value < 6250)
        commission = 56.00f + 0.0066 * value;
    else if (value < 20000)
        commission = 76.00f + 0.0034 * value;
    else if (value < 50000)
        commission = 100.00f + 0.0022 * value;
    else if (value < 500000)
        commission = 155.00f + 0.0011 * value;
    else
        commission = 255.00f + 0.0009 * value;

    if (commission < 39.00f)
        commission = 39.00f;

    printf("Commission: %.2f\n", commission);
}

我的问题是,考虑到行数和避免重复是一个良好和必要的习惯,或者这是算法设计方法的一个坏方法?

提前致谢!

c loops
4个回答
6
投票

不要重复自己。 DRY vs. WET

考虑到代码需要重新工作

// weak
printf("Enter value of trade: ");  
scanf("%f", &value);

// better
printf("Enter value of trade: ");  
fflush(stdout);   // Insure text is printed before scanning
if (scanf("%f", &value) != 1) Handle_Error();

代码的维护者是否愿意在1或2个地方更新?

用户I / O通常受益于辅助函数,并且具有明确的非重复编码循环条件。

int read_double(const char *prompt, double *y, ) {
  printf("%s", prompt);  
  fflush(stdout);
  int count = scanf("%f", y);
  return count; 
}

while (read_double("Enter value of trade: ", &value) == 1) {
  if (value == 0)
  ...
  printf("Commission: %.2f\n", commission);
}

整个if()else if(),......也可以使用re-work。也许struct对于OP来说太新了,但关键在于代码的发展以及易于维护的编码是一个非常有价值的目标。

  const struct {
    double value;
    double commission_base;
    double commission_rate;
  } tier[] = { 
    { 2500.00, 30.00, 0.017 }, 
    { 6250.00, 56.00, 0.0066 },
    { 20000.00, 76.00, 0.0034 }, 
    { 50000.00, 100.00, 0.0022 },
    { 500000.00, 155.00, 0.0011 }, 
    { DBL_MAX, 255.00, 0.0009 } };
  int n = sizeof tier / sizeof tier[0];
  double commission = 0.0;
  for (int i = 0; i < n; i++) {
    if (value < tier[i].value) {
      commission = tier[i].commission_base + tier[i].commission_rate * value;
      break;
    }
  }
  #define COMMISSION_MIN 39.00
  if (commission < COMMISSION_MIN) {
    commission = COMMISSION_MIN;
  }

3
投票

一条规则是不要重复自己。与任何规则一样,可能存在例外情况,但如果您没有充分理由采取其他方式,则应该注意它。

它背后的基本原理并不是真正打字懒惰,更重要的是,如果你必须改变代码,你必须要注意不要忘记重复代码的一次出现。

出于这个原因,即使在你的例子中它与品味的关系不远,我绝对会优先考虑代码不重复的第二个版本。这里的一个具体原因是你真的应该测试scanf的返回值(如果用户错误地键入了符号的alpha,会怎样?)。如果是第二个版本,则只需修复一次问题。在第一个版本中,如果你在写完第一个版本之后那么长时间,或者更糟糕的是如果其他人必须修复它,则存在忘记一个实例的风险。


1
投票

使用无限循环来完成此任务在技术上是有效的。但是,建议的代码更清晰,因为跳出循环的条件是循环类型中固有的。 different loop types允许您更有效地完成不同的任务。 “for”循环可以增加或减少变量的值,而无需在循环内为此编写代码。 while循环只是运行一个检查,这就是你正在做的事情。


1
投票

你应该听从其他响应者关于不使用浮动钱的建议。也就是说,这是一种避免使用无限循环的方法(仍然使用你的浮动命名法,但你应该适当地改变它):

float value = 1.0;
while ( value != 0.0f ) {
   // prompt for input

   // get input

   if ( value > 0.0f ) {
      // handle the input and output resultshere
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.