Программа 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 с помощью одного заявления печати. Нет особой причины, по которой я хочу, чтобы это было одно печатное заявление, кроме любопытства относительно того, можно ли это сделать.

РЕДАКТИРОВАТЬ 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

5 ответов

Решение

Вы загнали себя в угол тем, как вы пытались поместить всю логику в 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

Вы можете упростить аргументы для printf, передавая строковые литералы как строку формата, а не используя %s распечатать их. Это использует тот факт, что вы знаете, что нет % персонажи в "fizz" или же "buzz", Гарантированно безопасно передавать неиспользованные аргументы в 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);
    }
}

Это может быть хорошим стилем и, возможно, улучшением asm, чтобы условно определить аргументы, которые вы собираетесь передать, и затем сделать один вызов вместо того, чтобы записывать один и тот же вызов функции с разными аргументами. Это может быть хорошо, если большинство аргументов, которые вы собираетесь передать, одинаковы в разных ветвях, что здесь не так.

Обычно лучше просто использовать puts (неявный \n добавлено) или fputs печатать постоянные строки, которые не нуждаются в форматировании. Компиляторы знают это и даже оптимизируют printf("Hello World!\n"); или же printf("%s\n", "Hello World!") в puts("Hello World!"); в тривиальных случаях. Этот трюк означает, что даже распечатки с фиксированной строкой все еще делают вызов более дорогим printf, (Помимо читабельности, это одна из конкретных причин, почему это не лучший выбор в данном конкретном случае.)

gcc и clang компилируют это в asm, который работает так, как это делает исходный код: printf всегда получает два аргумента (в rdi а также rsi регистры), но иногда строка формата не использует 2-й аргумент. + Изменить -O3 в -Os использовать gcc div вместо мультипликативного обратного.

Они не развертывают цикл, чтобы соответствовать шаблону по модулю, или уменьшают силу по модулю до счетчиков вниз, или что-нибудь умное, как вы сделали бы в рукописном асме FizzBuzz.

Изощренный способ написания компактного FizzBuzz см. В CodeGolf.SE, где %s%s%.d строка формата условно получает пустые строки. %.d is определяет точность 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;
}

Как и предполагалось, вы можете использовать itoa();, Пример кода ниже.

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

Итоа используется для преобразования int к stringпараметры следующие.

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

Первый параметр - это число, которое вы конвертируете. Вторым параметром является строка /char Массив, в который вы хотите сохранить преобразованный файл. И наконец, третий параметр - это база, в которой преобразуется число.

      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;
Другие вопросы по тегам