C++ Fizz Buzz альтернативная версия
Я относительно новичок в переполнении стека (да, я чрезвычайно новичок в кодировании), и в настоящее время я работаю над измененной версией вопроса Fizz Buzz. Может ли кто-нибудь помочь мне понять, что я делаю не так? Я не могу найти ответ на переполнение стека. Используйте цикл while вместо цикла for, чтобы написать программу, которая выводит строковое представление чисел от 1 до n.
Но для кратных трех он должен вывести "Fizz" вместо числа, а для кратных пяти вывести "Buzz". Для чисел, кратных трем и пяти, выведите "FizzBuzz".
Пример:
n = 15,
Выход:
1
2
шипение
4
жужжание
шипение
7
8
шипение
жужжание
11
шипение
13
14
FizzBuzz
Мой код
#include <iostream>
using namespace std;
int n = 0;
{
cout << "Enter your number "; // Prompt for input
cin >> n; // Get the input.
for (int i = 1; i <= n; i++)
{
if ((i % 15) == 0)
cout << "FizzBuzz\n";
else if ((i % 3) == 0)
cout << "Fizz\n";
else if ((i % 5) == 0)
cout << "Buzz\n";
else
cout << i << "\n";
}
return 0;
}
Пока я получаю сообщение об ошибке для строки 4:
4:1: error: expected ',' or ';' before '{' token
8 ответов
Вы должны быть в состоянии сделать это одинаково хорошо с циклом for или while. Однако, это не то, почему ваша программа не работает. Как уже упоминалось ранее @EvilTeach, ваша программа в основном принимает ввод от stdin(через cin) за скобками ({}) в функции main().
Сигнатура функции в C/C++ определяется как:
return-type funcName(ArgType1 arg1, ... , ArgTypeN argN)
{
// cin goes here
// Your loop goes here
}
Для начала вам нужно переместить сундук в фигурные скобки {}. Это должно пройти мимо вашей ошибки компиляции. Как правило, рекомендуется также выводить подсказку, когда вы запрашиваете ввод. Как правило, если вы обращаетесь за помощью, всегда включайте все ошибки компиляции, которые вы получаете. Это помогает сосредоточиться на проблеме. Добро пожаловать в переполнение стека.
#include <iostream>
using namespace std;
int main ()
{
cout << "Enter your number "; // Prompt for input
cin >> n; // Get the input.
for (int i = 1; i <= n; i++)
{
if ((i % 15) == 0)
cout << "FizzBuzz\n";
else if ((i % 3) == 0)
cout << "Fizz\n";
else if ((i % 5) == 0)
cout << "Buzz\n";
else
cout << i << "\n";
}
return 0;
}
Наивное решение
for(int i = 1; i <= n; i++)
{
if(i % 15 == 0)
cout << "FizzBuzz\n";
else if(i % 3 == 0)
cout << "Fizz\n";
else if(i % 5 == 0)
cout << "Buzz\n";
else
cout << i << "\n";
}
Проблема с наивным решением: % 15 эквивалентно% 3 &&% 5.
Следовательно, нет смысла снова проверять то же условие.
Эффективный подход
for(int i = 1; i <= n; i++)
{
string d ="";
if(i % 3 == 0) d += "Fizz";
if(i % 5 == 0) d += "Buzz";
if(d == "") cout << i << "\n";
else cout<< d << "\n";
}
Проблема с указанным выше Эффективным решением: «%» - дорогостоящий оператор.
Сложность оператора '%' составляет O(n ^ 2)
Более эффективный подход
int c3 = 0;
int c5 = 0;
for(int i = 1; i <= n; i++)
{
c3++;
c5++;
string d = "";
if(c3 == 3)
{
d += "Fizz";
c3 = 0;
}
if(c5 == 5)
{
d += "Buzz";
c5 = 0;
}
if(d == "") cout << i << "\n";
else cout << d << "\n";
}
Можно уменьшить строку, используя тернарные операторы, а также комбинируя
cout
с
to_string
#include <iostream>
using namespace std;
int main() {
string str = "";
for (int i = 1; i < 100; i++) {
str = !(i % 3) ? "fizz" : "";
str += !(i % 5) ? "buzz" : "";
cout << (str == "" ? to_string(i) : str) << endl;
}
return 0;
}
#включают
использование пространства имен std;
интервал основной (){
целое число{0};
cout << "введите число" << "\n" ;
цин >> номер;
for(int я = 1; я <= число; я ++){
if(i % 3 == 0 && i % 5 == 0){
cout<< "FizzBuzz" << "\n" ;
}
else if (i % 3 == 0 ){
cout<< "Fizz" << "\n" ;
}
else if (i % 5 == 0){
cout<< "Buzz" << "\n";
}
else
cout<< i << "\n";
}}
Какая польза от кода, который может понять простой новичок? Это не способствует сохранению рабочего места, не показывает, что вы придурок, который знает больше, чем все остальные, и это НЕ УДОВОЛЬСТВИЕ. Итак, вот мой FizzBuzz, вдохновленный Дафф. Его все еще можно улучшить, например, нет использования исключений в качестве обычных возвратов, нет злоупотребления двухфазным поиском и ничего существенного не происходит во время компиляции, даже SFINAE, что, конечно, требуется в каждом современном приложении C++.
#include <iostream>
#include <string>
#include <algorithm>
// FizzBuzz using Duff's device
auto FizzBuzz( int n ){
auto s = std::string( "" );
switch( n % 15 ){
while( n >= 0 ){
case 14 : s = ", " + std::to_string( n-- ) + s;
case 13 : s = ", " + std::to_string( n-- ) + s;
case 12 : s = ( n--, ", Fizz" ) + s;
case 11 : s = ", " + std::to_string( n-- ) + s;
case 10 : s = ( n--, ", Buzz" ) + s;
case 9 : s = ( n--, ", Fizz" ) + s;
case 8 : s = ", " + std::to_string( n-- ) + s;
case 7 : s = ", " + std::to_string( n-- ) + s;
case 6 : s = ( n--, ", Fizz" ) + s;
case 5 : s = ( n--, ", Buzz" ) + s;
case 4 : s = ", " + std::to_string( n-- ) + s;
case 3 : s = ( n--, ", Fizz" ) + s;
case 2 : s = ", " + std::to_string( n-- ) + s;
case 1 : s = ", " + std::to_string( n-- ) + s;
case 0 : s = ( n--, ", FizzBuzz" ) + s;
}
}
return s.substr( std::min( 12, static_cast< int >( s.size() ) ) );
}
// test harnesses are severly overrated
#define check_equal( a, b ) check_equal_func( __FILE__, __LINE__, a, b )
template< typename A, typename B >
void check_equal_func( const char *file, int line, const A & a, const B & b ){
if( a != b ){
std::cout << file << ":" << line << " [" <<a << "] != [" << b << "]\n";
}
}
// test cases from https://catonmat.net/tools/generate-fizzbuzz-sequence
int main(int argc, char **argv){
check_equal( FizzBuzz( 0 ), "" );
check_equal( FizzBuzz( 1 ), "1" );
check_equal( FizzBuzz( 10 ), "1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz" );
check_equal( FizzBuzz( 100 ), "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" );
check_equal( "If you see no messages before this one ", "all tests were successfull." );
}
В FizzBuzz важна эффективность кода; более короткие коды кажутся более загадочными, но более крупные из них, как правило, имеют более низкую кривую обучения (менее читаемые). Я выбрал три способа кодирования этого и измерения их продолжительности; хорошо известно, что подобный код на C++ требует больше времени и памяти, чем написанные y C. Поэтому вам следует взглянуть на свой способ кодирования в зависимости от конечного назначения двоичных файлов и временных рамок, которые у вас есть для этого.
#include <iostream>
#include <chrono>
#include <cstring>
void runOne(int n, void (*fnc)(int));
void fizzbuzzAnsiC(int n);
void fizzbuzzAnsiC2(int n);
void fizzbuzzCpp(int n);
using namespace std;
using namespace std::chrono;
int main(int argc, char *argv[])
{ long iter = 100;
if (argc > 1)
iter = strtol(argv[1], nullptr, 10);
runOne(int(iter), fizzbuzzAnsiC2);
cout << endl << "==============" << endl;
runOne(int(iter), fizzbuzzAnsiC);
cout << endl << "==============" << endl;
runOne(int(iter), fizzbuzzCpp);
cout << endl << "==============" << endl;
return 0;
}
void runOne(int n, void (*fnc)(int))
{ high_resolution_clock::time_point t1 = high_resolution_clock::now();
fnc(n);
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = duration_cast<microseconds>( t2 - t1 ).count();
cerr << "Lasted: " << duration << " us" << endl;
}
static const char* cszFizz = "Fizz";
static const char* cszBuzz = "Buzz";
void fizzbuzzAnsiC(int n)
{ int i;
char szPrn[11];
char szNum[11]; //Suppose 9 digits number max (10e8-1)
char uMul;
for (i = 1; i <= n; ++i)
{ uMul = i%15 == 0;
strcpy(szPrn, uMul | (i%3==0) ? cszFizz : (i%5==0 ? cszBuzz : itoa(i, szNum, 10)));
if (uMul) strcat(szPrn, cszBuzz);
strcat(szPrn, "\n");
fwrite(szPrn, 1, strlen(szPrn), stdout);
}
}
void fizzbuzzAnsiC2(int n)
{ int i;
const char *messages[] = {"%i\n", "Fizz\n", "Buzz\n", "FizzBuzz\n"};
for (i = 1; i <= n; ++i)
printf(messages[((i % 3) == 0) + 2*((i % 5) == 0)], i); //printf takes longer then str* functions
}
void fizzbuzzCpp(int n)
{ for (int i = 1; i <= n; ++i)
{ bool uMul = i%15 == 0;
std::cout << (uMul | (i%3==0) ? cszFizz : (i%5==0 ? cszBuzz : std::to_string(i)));
if (uMul) std::cout << cszBuzz;
std::cout << std::endl;
}
}
По мере увеличения числа итераций fizzbuzzAnsiC2 становится менее эффективным. Функция fizzbuzzAnsiC всегда самая эффективная.
самая простая версия.
#include <iostream>
#include <string>
using namespace std;
int main(){
for(int i=1; i<=100; i++){
string output = "";
if(i%3 == 0) output += "fizz";
if(i%5 == 0) output += "buzz";
if(output == "") output = to_string(i);
cout << output <<endl;
}
}