Я создавал программу FizzBuzz на C++, в которой вы печатаете числа от 1 до 100 и заменяете кратные 3 на «Fizz», кратные 5 на «Buzz» и кратные 3 и 5 на «FizzBuzz».
Хотя при запуске кода я не получаю никаких ошибок, но цифры 6, 21, 36 и т. д. не заменяются на «Fizz», тогда как числа 10, 25, 40 и т. д. не заменяются на «Buzz».
Я не понимаю, почему это происходит.
Мой код приведен ниже:
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
for (int i = 1; i < 101; i++)
{
if ((i%3) == 0 && (i%5) == 0)
{
printf("FizzBuzz ");
i++;
}
else if ((i%3) == 0)
{
printf("Fizz ");
i++;
}
else if ((i%5) == 0)
{
printf("Buzz ");
i++;
}
printf("%d ", i);
}
return 0;
}
По моему мнению, ожидаемый результат должен быть (с использованием кода Geeks for Geeks):
[Running] cd "d:\Projects\VS Code\Jetlag\helloworld\" && g++ fzz.cpp -o fzz && "d:\Projects\VS Code\Jetlag\helloworld\"fzz
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
[Done] exited with code=0 in 6.043 seconds
Это точный результат, который я получаю:
[Running] cd "d:\Projects\VS Code\Jetlag\helloworld\" && g++ FizzBuzz.cpp -o FizzBuzz && "d:\Projects\VS Code\Jetlag\helloworld\"FizzBuzz
1 2 Fizz 4 Buzz 6 7 8 Fizz 10 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz 21 22 23 Fizz 25 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz 36 37 38 Fizz 40 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz 51 52 53 Fizz 55 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz 66 67 68 Fizz 70 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz 81 82 83 Fizz 85 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz 96 97 98 Fizz 100
[Done] exited with code=0 in 0.987 seconds
Как видно выше, некоторые числа не заменяются.
Любая помощь будет оценена по достоинству.
Я бы также сказал, что порядок оценки неправильный. Если все сделано правильно, вам никогда не придется явно писать «FizzBuzz».
Вы увеличиваете i
как в операторе цикла for
, так и в if
s. Также последний отпечаток самого номера должен находиться в ветке else
.
Добро пожаловать в Stack Overflow! Похоже, вам, возможно, придется научиться использовать отладчик для пошагового выполнения кода. С помощью хорошего отладчика вы можете выполнять программу построчно и видеть, где она отклоняется от ожидаемого. Это важный инструмент, если вы собираетесь заниматься программированием. Дальнейшее чтение: Как отлаживать небольшие программы и Руководство по отладке
Примечание: в C++ обычно рекомендуется не использовать ввод-вывод C (printf
).
@MarkRansom Я почти уверен, что цель FizzBuzz — стать инструментом обучения. Я не вижу цели вашего комментария. Он не ищет разъяснений, не дает указаний или иным образом помогает ОП. Это снисходительно.
@sweenish его часто используют в качестве быстрого теста на собеседовании, чтобы проверить, обладает ли кандидат базовым уровнем навыков программирования. Вот несколько примеров обсуждения этого: blog.codinghorror.com/why-cant-programmers-program blog.tdwright.co.uk/2022/07/14/…
В вашем коде есть несколько проблем:
Вы увеличиваете i
как в операторе цикла for
, так и под if
. Поскольку вам нужно увеличивать его на каждой итерации, подходящее место — это оператор for
.
Последняя печать самого номера должна находиться под блоком else
(после предыдущих if
/else if
): вам следует печатать сам номер только в том случае, если предыдущие случаи обрабатывались блоками if
/else if
(для «FizzBuzz», «Fizz» и «Базз») не удержались, и для этого нужен финальный else
(см. в исправленной версии ниже).
Хотя это может работать, не рекомендуется использовать ввод-вывод C в C++. Вместо этого вы можете использовать std::cout
от <iostream>
, который вы все равно #include
d. Еще более современный способ (из C++23) — использовать std::print.
Рекомендуется избегать using namespace std;
. См. здесь: В чем проблема с «использованием пространства имен std;»?.
Фиксированная версия:
#include <iostream>
int main()
{
for (int i = 1; i < 101; i++)
{
if (((i % 3) == 0) && ((i % 5) == 0)) {
std::cout << "FizzBuzz ";
}
else if ((i % 3) == 0) {
std::cout << "Fizz ";
}
else if ((i % 5) == 0) {
std::cout << "Buzz ";
}
else { // this block will be executed only if the previous cases did not hold
std::cout << i << " ";
}
}
}
или std::print, если доступен C++23
В @sweenish OP нет else, в фиксированном коде он есть
@sweenish Я отредактировал и попытался подчеркнуть тот факт, что его следует печатать в блоке else после предыдущих if
. Пожалуйста, не стесняйтесь перефразировать, если вы можете помочь лучше прояснить суть.
@Калет Я думал, что упоминание std::print
слишком сложно для этого поста, но я добавлю комментарий по этому поводу.
@wohlstad Я считаю это типобезопасным printf
@Caleth добавил комментарий по этому поводу.
@sweenish снова отредактировал и приложил все усилия, чтобы прояснить ситуацию.
Большое спасибо за понимание. Я попробую, но обычно std:cout
меня сбивает с толку, поэтому я избегаю его использования (даже не знаю, почему я включил <iostream>
). К тому же, мне больше привычна stdio
библиотека. Причина, по которой я увеличиваю i
в if
, заключается в том, чтобы пропустить это число, перейдя к следующему номеру после того, как будет напечатано «Fizz»/«Buzz»/«FizzBuzz». Это устраняет необходимость в утверждении else
.
@Redstoner824 рад помочь. Кстати, я не понимаю, как ваша попытка сохранить else
путем увеличения i
в if
s может быть правильно реализована без усложнения решения, и думаю, что использование else
здесь вполне естественно. Что касается использования printf
— решать вам, конечно, но многие эксперты по C++ рекомендуют его избегать. Вы можете посмотреть std::print, упомянутый в моем ответе, а также в другом ответе.
Ответ выше хорошо отвечает на вопрос. Я просто хотел предоставить альтернативную версию FizzBuzz.
#include <print>
int main() {
for (int i = 1; i < 101; ++i) {
if (i % 3 == 0) {
std::print("Fizz");
}
if (i % 5 == 0) {
std::print("Buzz");
}
if (i % 3 != 0 && i % 5 != 0) {
std::print("{}", i);
}
std::print("\n");
}
}
Выполняемые явные проверки в основном такие же, но эта версия позволяет избежать избыточной проверки случая «FizzBuzz» за счет постоянной проверки всех трех случаев. В этом решении также используется другой подход к ветвлению, в результате чего на одну «ветвь» меньше. Если производительность является главным показателем, это решение может быть не идеальным. Но самое интересное в FizzBuzz то, что есть много способов решить эту проблему.
std::print взят из C++23 и намного безопаснее, чем printf
. В противном случае я бы тоже рекомендовал std::cout
.
FizzBuzz действительно требует разных решений, и ваша демонстрация альтернативной логики будет полезна. +1.
Я обнаружил ошибку в своем коде. Мне пришлось поместить оператор printf
в блок else
и удалить приращение i
из оператора if
.
Это, конечно, мой способ решения FizzBuzz.
Окончательный код выглядит так:
#include <stdio.h>
int main()
{
for (int i = 1; i < 101; i++)
{
if ((i % 3) == 0 && (i % 5) == 0)
{
printf("FizzBuzz ");
}
else if ((i % 3) == 0)
{
printf("Fizz ");
}
else if ((i % 5) == 0)
{
printf("Buzz ");
}
else
{
printf("%d ", i);
}
}
}
Спасибо всем за помощь и быстрый ответ.
Совершенно нормально опубликовать ответ на свой вопрос. Но в данном случае я не вижу, что этот ответ добавляет к двум другим, уже опубликованным. Вы могли бы рассмотреть возможность принятия одного из них вместо публикации нового ответа. См.: Что мне делать, если кто-то отвечает на мой вопрос?.
Я чувствую, что этот ответ устраняет необходимость в <iostream>
или <print>
и основан исключительно на C I/O, который я изначально использовал, но я удалю этот ответ, если он покажется ненужным.
Я уже писал свое мнение по поводу использования printf
, но строгих правил против этого нет, так что решать вам. В любом случае спасибо, что приняли мой ответ.
Вы ++ слишком много раз.