首页 > 解决方案 > 打印 3、5 和两者的倍数的 C 程序,专业风格建议

问题描述

我编写了我的第一个简单的 C 程序,它打印 3 、 5 以及 3 和 5 的倍数,而不是数字,从 1 到 100。它有效。

我知道这个程序可以用数百万种不同的方式编写。专业的 C 程序员将如何实施最佳实践?作为一个完美主义者,我正在尝试实现最高的最佳标准,主要是指针和专业的函数实现和预处理器。

#include <stdio.h>

void findMultiples(int n);


int main() {
    
    findMultiples(100);
    
    return 0;
}

void findMultiples(int n){
    for (int i = 1; i <= n; i++)
        if (i % 15 == 0){
            printf("Multiple of 3 and 5\n");
        }
        else if (i % 5 == 0){
            printf("Multiple of 5\n");
        }
        else if (i % 3 == 0){
            printf("Multiple of 3\n");
        }
        else{
            printf("%d\n", i);
        }
}

标签: cmodulo

解决方案


这基本上是Fizzbuzz,如果它可被 5 和 3 整除,则应打印 FizzBu​​zz,如果可被 5 整除但不能被 3 整除,则应打印 Fizz,如果可被 3 但不能被 5 整除,则应打印 Buzz。

TL;博士

没有“正确”的方法可以做到这一点。不管你怎么做,你都会破坏一些最佳实践。

长解释

笔记!

我是那种喜欢灵活方法来实现最佳实践和代码标准的程序员。这没有对错,但下面的整个文字都被我的个性所着色。我几乎将此测试视为“您能理解何时跳过最佳实践”,而其他人则将其视为“即使在棘手的情况下,您也能弄清楚如何遵循最佳实践”。没有一个比另一个更正确。

这个问题旨在非常容易理解,但要“很好”地做到这一点非常棘手。在此示例中您经常会遇到的一件事是重复代码。您可以很容易地构建它,但通常以可读性为代价。

如果我要设计一个符合您要求的代码,我会对您提供的解决方案非常满意,然后继续处理下一个问题。真的不值得花很多时间在上面。这也是雇主在给您进行此测试时会考虑的事情。您是否花费数小时和数天来确保您的代码遵循所有“最佳实践”,即使收益微不足道,或者您是否创建了有效且可读的代码,并且一旦足够好就继续前进?

我见过的一些示例可以避免首先检查它是否可以被两个数字整除,然后分别检查它们是否连接字符串。像这样的伪:

string str = ""
if n % 5 = 0: str += "Fizz"
if n % 3 = 0: str += "Buzz"
print str

看起来不错,对吧?好吧,把它翻译成真正的 C 语言,字符串处理非常混乱。

char str[9] = "";
if(n%5 == 0) strcat(str, "Fizz");
if(n%3 == 0) strcat(str, "Buzz");
puts(str);

不过看起来也不算太糟糕。但这真的值得吗?如果您想将“Fizz”和“Buzz”更改为更长的名称怎么办?然后你需要确保它str有更多的空间,这很容易忘记并且可能导致难以追踪的错误。我并不是说这段代码非常危险,但这里的底线是你的推理方式。这种风险真的非常值得为避免一些代码重复而付出努力吗?

有些人将条件重构为函数,例如bool dividable_by_15(int n)因为“在单独的函数中分解功能很好”。有些人甚至会做到这一点:

bool dividable_by(int n, int d) { return (n%d) == 0; }
bool dividable_by_3(int n) { return dividable_by(n, 3); }
bool dividable_by_5(int n) { return dividable_by(n, 5); }
bool dividable_by_15(int n) { return dividable_by_3(n) && dividable_by_5(n); }

但在这种情况下真的需要吗?我不这么认为,但我不会说选择是 100% 显而易见的,而且它还取决于您使用的语言。但在大多数情况下,我会说这是一个非常明显的过度工程案例。

这个测试不是看你是否能遵循所有的最佳实践。这更像是一个性格测试。一些雇主希望你做各种各样的事情,而另一些雇主则更喜欢你可以在它应该做的时候让代码保持原样。

对于您的代码,我实际上只有一个反对意见,那就是您省略了 for 循环的大括号。我永远不会那样做,除非身体是一条简单的线。但是,我会省略 if 语句的大括号。有些人会同意最后一个,有些人不会。那些即使对于单个语句也总是使用大括号的人经常使用这样的论点,即如果您需要在正文中添加额外的语句,它会降低错误的风险。另一个论点是一致性,即你总是应该努力在任何地方做同样的事情。在我看来,这些因素不值得多加几行,但是嘿,那就是我。你做你。

for (int i = 1; i <= n; i++) {
    if (i % 15 == 0)
         printf("Multiple of 3 and 5\n");
    else if (i % 5 == 0)
        printf("Multiple of 5\n");
    else if (i % 3 == 0)
        printf("Multiple of 3\n");
    else
        printf("%d\n", i);
}

这对我来说看起来好多了。我什至会考虑将 if 作为一个衬垫:

    if      (i % 15 == 0) printf("Multiple of 3 and 5\n");
    else if (i % 5 == 0)  printf("Multiple of 5\n");
    else if (i % 3 == 0)  printf("Multiple of 3\n");
    else                  printf("%d\n", i);

我也会考虑提取换行符,如下所示:

    if      (i % 15 == 0) printf("Multiple of 3 and 5");
    else if (i % 5 == 0)  printf("Multiple of 5");
    else if (i % 3 == 0)  printf("Multiple of 3");
    else                  printf("%d", i);
    printf("\n");

由于它只是一个新行,您可以更改printf("\n")为 just puts("")

但是-事情就是这样-在我看来,我已经在这个问题上花费了很多精力。:)

作为一个完美主义者,我正在努力实现最高的最佳标准

我读到的一句话完美地回答了这个问题:“盲目遵循最佳实践不是最佳实践”

“最佳实践”旨在提供一种非常简单的方法来实现某些目标。如果您的代码在没有遵循最佳实践的情况下实现了该目的,为什么要更改它?特别是如果它更好地实现了这个目的。


推荐阅读