【问题标题】:Fizzbuzz program in CC 中的 Fizzbuzz 程序
【发布时间】:2015-06-16 23:03:26
【问题描述】:

好的,这确实不是一个 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' 是一个 int。 我的问题是,我可以应用任何类型的转换来将“i”转换为字符串吗?

编辑:我应该提一下,我真正要问的是这个 fizzbuzz 测试是否可以使用单个 print 语句来完成。没有什么特别的原因我希望它是一个单独的打印语句,除了好奇它是否可以完成。

EDIT2:问题已回答,这是我的实现:

#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

【问题讨论】:

  • 为什么不直接使用%d
  • 那我该如何打印字符串呢?
  • printfs 分开并使用ifs。这样更容易,也减少了混乱。
  • 三元运算符 = 面试失败。
  • 对我来说听起来更像codegolf.stackexchange.com ...

标签: c fizzbuzz


【解决方案1】:

编辑 抱歉...我刚刚意识到这个线程是针对 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;
}

【讨论】:

    【解决方案2】:

    您可以通过将字符串文字作为格式字符串 传递来简化 args 到 printf,而不是使用 %s 来打印它们。这利用了您知道"fizz""buzz" 中没有% 字符这一事实。 It's guaranteed to be safe to pass unused args to 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);
        }
    }
    

    有条件地确定要传递的 args 然后进行一次调用,而不是用不同的 args 写出相同的函数调用,这可能是一种很好的风格,并且可能是更好的 asm。如果您要传递的大多数参数在不同的分支中都是相同的,这可能会很好,但这里不是这种情况。

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

    gcc 和clang compile this into asm that works the way the source doesprintf 总是有两个参数(在rdirsi 寄存器中),但有时格式字符串不使用第二个参数。将 -O3 更改为 -Os 以使 gcc 使用 div 而不是乘法逆元。

    他们不会展开循环以匹配模模式,或将模强度降低为向下计数器,或任何聪明的like you'd do in a hand-written asm FizzBuzz

    有关编写紧凑型 FizzBu​​zz 的巧妙方法,请参阅CodeGolf.SE,其中%s%s%.d 格式字符串有条件地获取空字符串。 %.d 指定精度为 0。非零整数正常打印,但 0 打印为空字符串。

    【讨论】:

      【解决方案3】:

      您尝试将所有逻辑都放在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);
      }
      

      附录:只需一个 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

      【讨论】:

      • 我忘了提到的是,提出这个问题的全部目的是找到一种方法,只使用 一个 打印语句来完成整个事情。我不是 CS 新手,只是 C 语言新手。我可以很好地按照您提到的方式进行 fizzbuzz 测试。我也可以使用 two 打印语句很容易地做到这一点。问题是它是否可以只用一个来完成。
      • 我还应该提一下,我想只使用一个打印语句来做这件事并没有什么深刻的原因,只是我的好奇心!
      • @SilverSlash 更新了一种可能的解决方案(我不推荐,但是嘿,无论如何,我们现阶段只是在进行实验)
      • 太棒了!我确实想到了这一点,但我只是希望有一些演员可以轻松进行转换。不过谢谢!
      • 您使用单个 printf 的解决方案不起作用:第二个参数未作为 int 传递。未定义的行为。
      【解决方案4】:

      建议您可以使用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函数,对于这个程序来说是不必要的,你可以使用标准的%s格式printf
      猜你喜欢
      • 2021-08-09
      • 2018-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多