C 语言的 Fizzbuzz 程序
Fizzbuzz program in C
好吧,这真的不像是一道 C 题,而是一道 fizzbuzz 题。
我用 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);
}
根据建议,您可以使用 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);
第一个参数是您要转换的数字。第二个参数是要将转换后的strong存入的string/char
数组。最后,第三个参数是要转换的数字所在的基数。
您尝试将所有逻辑放入 printf
调用的方式使您走投无路。最好先写成"slow"的方式,然后再想办法优化。
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
)
);
您可以将字符串文字 作为格式字符串 传递,而不是使用 %s
来打印它们,从而简化 printf 的参数。这利用了您知道 "fizz"
或 "buzz"
中没有 %
个字符这一事实。 It's guaranteed to be safe to pass unused args to printf.
为了使源代码可读,将逻辑从 printf()
本身提取到 select 格式字符串,并将其存储在局部变量中。
#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);
}
}
有条件地确定您要传递的参数然后进行一次调用,而不是用不同的参数写出相同的函数调用,这可能是一种很好的风格,并且可能会产生更好的 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 does:printf
总是得到两个参数(在 rdi
和 rsi
寄存器中),但有时格式字符串不使用第二个精氨酸。将 -O3
更改为 -Os
以使 gcc 使用 div
而不是乘法逆。
他们不会展开循环来匹配模数模式,或者将模数强度降低为递减计数器,或者任何聪明的东西 。
有关编写紧凑型 FizzBuzz 的迂回方式,请参阅 CodeGolf.SE,其中 %s%s%.d
格式字符串有条件地获取空字符串。 %.d
指定精度为 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;
}
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;
好吧,这真的不像是一道 C 题,而是一道 fizzbuzz 题。
我用 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);
}
根据建议,您可以使用 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);
第一个参数是您要转换的数字。第二个参数是要将转换后的strong存入的string/char
数组。最后,第三个参数是要转换的数字所在的基数。
您尝试将所有逻辑放入 printf
调用的方式使您走投无路。最好先写成"slow"的方式,然后再想办法优化。
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
)
);
您可以将字符串文字 作为格式字符串 传递,而不是使用 %s
来打印它们,从而简化 printf 的参数。这利用了您知道 "fizz"
或 "buzz"
中没有 %
个字符这一事实。 It's guaranteed to be safe to pass unused args to printf.
为了使源代码可读,将逻辑从 printf()
本身提取到 select 格式字符串,并将其存储在局部变量中。
#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);
}
}
有条件地确定您要传递的参数然后进行一次调用,而不是用不同的参数写出相同的函数调用,这可能是一种很好的风格,并且可能会产生更好的 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 does:printf
总是得到两个参数(在 rdi
和 rsi
寄存器中),但有时格式字符串不使用第二个精氨酸。将 -O3
更改为 -Os
以使 gcc 使用 div
而不是乘法逆。
他们不会展开循环来匹配模数模式,或者将模数强度降低为递减计数器,或者任何聪明的东西
有关编写紧凑型 FizzBuzz 的迂回方式,请参阅 CodeGolf.SE,其中 %s%s%.d
格式字符串有条件地获取空字符串。 %.d
指定精度为 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;
}
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;