在C语言中的Fizzbuzz程序

3

好的,这并不是一个纯粹的fizzbuzz问题,而是一个C语言问题。

我用C语言写了一些简单的代码来按要求打印出fizzbuzz。

#include <stdio.h>

int main(void)
{
    int n = 30;
    int i;
    for (i = 1; i<=n; i++)
        printf("%s\n", (i % 15) == 0 ? "fizzbuzz" : (i % 5) == 0 ? "buzz" : (i % 3) == 0 ? "fizz" : i);
}

现在,最后一个else语句显然不能工作,因为printf接受一个字符串而'i'是一个整数。我的问题是,有没有什么类型转换可以将'i'转换成一个字符串?
编辑:我应该提到,我真正想问的是是否可以使用单个打印语句完成这个fizzbuzz测试。除了好奇是否可以完成之外,没有特别的原因想要它成为单个打印语句。
编辑2:问题已解决,以下是我的实现:
#include <stdio.h>

int main(void)
{
    int i, n=30;        
    for (i = 1; i<=n; i++)
        printf((!(i%3) || !(i%5)) ? "%s\n" : "%d\n", !(i % 15) ? "fizzbuzz" : !(i % 5) ? "buzz" : !(i % 3) ? "fizz" : i);
}

http://codepad.org/DN7yBW99


3
为什么不直接使用“%d”? - haccks
1
那我该如何打印这些字符串呢? - Silver
3
printf 分开并使用 if,这样做更容易理解,同时也减少了混淆。 - Spikatrix
1
三元运算符的三重嵌套 = 面试失败。 - Potatoswatter
1
这更像是 http://codegolf.stackexchange.com ... - JensG
显示剩余4条评论
5个回答

6

你试图把所有的逻辑都放在 printf 调用中,这样做会让自己陷入困境。最好先以“慢”的方式编写,然后再寻找优化的方法。

for (i = 1; i <= n; i++) {
    if (i % 15 == 0)
        printf("fizzbuzz\n");
    else if (i % 5 == 0)
        printf("buzz\n");
    else if (i % 3 == 0)
        printf("fizz\n");
    else
        printf("%d\n", i);
}

Addendum: Do it with just one printf...

/* The following code is NOT recommended... */

int isFizz     = (i % 3 == 0      ) ? 1 : 0;
int isBuzz     = (i % 5 == 0      ) ? 1 : 0;
int isFizzBuzz = (isFizz && isBuzz) ? 1 : 0;

printf(
    (isFizz || isBuzz) ? "%s\n" : "%d\n",
    (
        isFizzBuzz ? "fizzbuzz" :
        isFizz     ? "fizz"     :
        isBuzz     ? "buzz"     :
        i
    )
);

http://codepad.org/LMr5WdIm


我忘了提到的是,问这个问题的整个意义在于找到一种只使用一个打印语句来完成整个过程的方法。 我对计算机科学并不陌生,只是对C语言不熟悉。我完全可以像你提到的那样轻松地完成“fizzbuzz”测试。我也可以使用两个打印语句很容易地完成它。问题是是否可以只使用一个语句完成。 - Silver
1
我还应该提到,没有深层次的原因让我只想使用一个打印语句来完成它,只是出于我的好奇心! - Silver
@SilverSlash 更新了一个可能的解决方案(虽然我不建议,但是嘿,我们现在只是在实验阶段) - Brian L
太好了!我确实想到过这个,但我只是希望有一些可以轻松进行转换的强制类型转换运算符。但还是谢谢! - Silver
你的解决方案只使用了一个printf,这是不可行的:第二个参数没有作为“int”传递。这会导致未定义的行为。 - chqrlie

1
你可以通过将字符串字面量作为格式字符串传递,而不是使用%s来打印它们,简化printf的args。这利用了你知道"fizz""buzz"中没有%字符的事实。将未使用的args传递给printf是安全的
为了使源代码可读性更高,将选择格式字符串的逻辑从printf()中提取出来,并存储在本地变量中。
#include <stdio.h>
int main(void)
{
    int n=30;        
    for (int i = 1; i<=n; i++) {
        int fizzy = (i % 3 == 0);
        int buzzy = (i % 5 == 0);

        const char *fmt = (fizzy && buzzy) ? "fizzbuzz\n" :
                          fizzy            ? "fizz\n"     :
                          buzzy            ? "buzz\n"     :
                          "%d\n";
        printf(fmt, i);
    }
}

有时候,为了编写更好的汇编代码,可以有选择地确定要传递的参数,然后进行一次函数调用,而不是多次调用相同的函数但传递不同的参数。如果在不同的分支中要传递的大部分参数都相同,这样做会很好,但本例并非如此。

通常最好只使用puts(隐式添加\n)或fputs来打印不需要格式化的常量字符串。编译器知道这一点,甚至在琐碎的情况下优化printf(“Hello World!\n”); printf(“%s \ n”,“Hello World!”)puts(“Hello World!”); 。 这个技巧意味着即使固定字符串打印仍然会调用更昂贵的printf。(除了可读性外,这是为什么在这种特定情况下它不是一个很好的选择的具体原因之一。)

gcc和clang将其编译成与源代码相同的汇编printf总是得到两个参数(在rdirsi寄存器中),但有时格式字符串不使用第二个参数。将-O3更改为-Os,使gcc使用div而不是乘法逆元。

他们没有展开循环以匹配模式,也没有将模数强制转换为递减计数器,或者进行任何聪明的优化,就像你在手写的汇编FizzBuzz中所做的那样

如果想要以一种狡猾的方式编写紧凑的FizzBuzz,请参见CodeGolf.SE,其中使用%s%s%.d格式字符串有条件地获得空字符串。 %.d 指定精度为 0。非零整数正常打印,但 0 打印为空字符串。


0

编辑 抱歉...我刚意识到这个主题是关于C语言解决方案的

递归实现:

vector<string> FizzBuzz::execute(int n) {

    if(n == 0)
        return vector<string>();

    auto push = n % 15 == 0 ? "fizzbuzz" :
                n % 3 == 0 ? "fizz" :
                n % 5 == 0 ? "buzz" :
                to_string(n);

    auto execution = execute(n-1);
    execution.push_back(push);
    return execution;
}

-1

如建议所述,您可以使用itoa();。以下是示例代码。

#include <stdio.h>
#include <stdlib.h>
int main(){
int num=23;
char snum[3];
itoa(num,snum,10);
printf("%s",snum);
}

itoa函数用于将int类型转换为string类型,其参数如下。

itoa(int num, char string [], int base);

第一个参数是您要转换的数字。第二个参数是您想要将转换后的字符串/ char 数组存储到的位置。最后,第三个参数是要转换的数字所在的基数。


itoa不是标准的C函数,在这个程序中也是不必要的,你可以使用printf的标准%s格式。 - user4815162342

-2
int n;
printf("input: ");
scanf("%d", &n);

for(int i = 0; i <= n; i++) {
    if(i % 3 == 0 && i % 5 == 0) 
        printf("FizzBuzz\n");
    else if(i % 3 == 0) 
        printf("Fizz\n");
    else if(i % 5 == 0)
        printf("Buzz\n");
    else 
        printf("%d\n", i);
}

return 0;

为什么要重新发布以前的答案? - NorbertM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接