Печать текстов 99 бутылок пива

Я написал программу на C ++ для 99 бутылок пива, но это довольно грязно. Есть ли способ сделать это коротким, чистым и более легким для чтения?

/*
 * Write a program that prints out the entire lyrics to a full rendition of "99 bottles of beer"
 */

#include <iostream>

using namespace std;

int main (void)
{
    int bottle = 99;
    while (bottle > 0)
    {
        cout << bottle << " bottles of beer on the wall, "
             << bottle << " bottles of beer." << endl;

        bottle--;

        cout << "Take one down and pass it around, " << bottle << " "
             << "bottles of beer on the wall.\n" << endl;

        if (bottle == 1)
        {
            break;
        }

    }

    cout << "1 bottle of beer on the wall, 1 bottle of beer." << endl
         << "Take one down and pass it around, no more bottles of beer on the wall.\n" << endl
         << "No more bottles of beer on the wall, no more bottles of beer." << endl
         << "Go to the store and buy some more, 99 bottles of beer on the wall.";

    return 0;
}
35 голосов | спросил Amession 14 PM00000020000002331 2014, 14:58:23

6 ответов


32

Несколько коротких комментариев:

Не используйте пространство имен std:

Это плохо по нескольким причинам, но вкратце: у вас могут быть конфликты имен большие , если вы using namespace std;. Для получения дополнительной информации: Почему использование namespaec std считается плохой практикой?

Условия разрыва:

хорошо выглядишь здесь:

while (bottle > 0) 
{
    //print the lyrics
    if (bottle == 1) 
    {
         break;
    }
}

Это может быть намного проще:

while (bottle > 1)
{
     //print the lyrics
}

Нейминг:

bottle - это имя дерьма для счетчика. Сделайте это bottleCount, leftBottles или что-нибудь еще, но не назовите его bottle. Потому что это не бутылка ...

ответил Vogel612 14 PM00000030000001031 2014, 15:19:10
17

В дополнение к комментариям в других ответах я рекомендую вам создать функцию для печати предложений на экране.

Что-то вроде

while (bottles > 0)
{
    printLyrics(bottles);
    bottles--;
}

В этом случае вам нужно обработать специальный случай, когда у вас останется одна бутылка.

void printLyrics (int bottles)
{
    if (bottles == 1)
    {
        printLastLyrics ();
    }
    else
    {
        printOtherLyrics (bottles);
    }
}

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

ответил mariosangiorgio 14 PM00000030000000331 2014, 15:50:03
16

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

#include <iostream>

template<int N>
struct song {
    inline static void sing() {
        std::cout << N << " bottles of beer on the wall, "
            << N << " bottles of beer.\nTake one down, pass it around, "
            << N - 1 << " bottles of beer on the wall.\n\n";
        song<N - 1>::sing();
    }
};

template<>
struct song<1> {
    inline static void sing() {
        std::cout << "1 bottle of beer on the wall, 1 bottle of beer.\n"
            << "Take it down and pass it around, no more bottles of beer on the wall.\n\n"
            << "No more bottles of beer on the wall, no more bottles of beer.\n"
            << "Go to the store and buy some more, 99 bottles of beer on the wall.\n";
    }
};

template<>
struct song<2> {
    inline static void sing() {
        std::cout << "2 bottles of beer on the wall, "
            << "2 bottles of beer.\nTake one down, pass it around, "
            << "1 bottle of beer on the wall.\n\n";
        song<1>::sing();
    }
};

int main() {
    song<99>::sing();
    return 0;
}

Хотя упорядочение шаблонов (сначала общий шаблон, затем специализация для 1 и, наконец, специализация для 2), может показаться странным и случайным, это на самом деле необходимо. Общий случай должен прийти к любой специализации. Специализация для 2 использует специализацию для 1, поэтому она должна следовать за ней. В противном случае специализация для 2 будет пытаться использовать общий шаблон для 1, а только после он сделал бы это шаблон для 1, что делает это недействительным.

К сожалению, по крайней мере, поскольку я написал код, это не уменьшает размер кода. OTOH, я считаю, что он, по крайней мере, правильно исправит грамматику.

ответил Jerry Coffin 15 AM00000090000003631 2014, 09:37:36
14

Не требуется код:

Фактически вы можете удалить это:

if (bottle == 1)
{
    break;
}

Вы находитесь в цикле while, чтобы ваш цикл продолжался так долго bottle больше, чем 0.
Поэтому я предполагаю, что вы ввели этот код для последней бутылки.
Вам просто нужно изменить:

while (bottle > 0)

to

while (bottle > 1)

для того же результата.

Именование:

Пока у вас не так много вызовов var => Мне нравится, что вы уже указываете на бутылку.
Тем не менее, я думаю, что bottleCount может быть лучшим именем var.

Пока цикл:

Ну, это не имеет большого значения, но ради вас, используйте for-loop.
Вы не забудьте затем вычесть его.

for (int bottleCount=99; bottleCount > 1; bottleCount--)

Резюме:

Пока я не кодер c ++, он ищет хорошее. Если вы действительно хотите получить высокий балл, вы можете использовать рекурсию для цикла for.

ответил chillworld 14 PM00000030000000231 2014, 15:20:02
8

Ошибки вывода

У вас есть ошибка плюрализации:

  

2 бутылки пива на стене, 2 бутылки пива.
  Возьмите один и пропустите его, 1 бутылку s пива на стене.

Кроме того, принято завершать вывод программы с помощью новой строки. Ваш конец заканчивается всего лишь периодом.

Структура и разложение проблемы

У вас есть специальный случай для однобуквенного стиха. Возможно, это может быть немного обобщено.

Как показано выше, основная задача состоит в том, чтобы получить плюрализацию и капитализацию в точности. Одной из возможных стратегий было бы рассматривать это как проблему интернационализации .

Однако было бы интереснее и поучительно подходить к нему как к программированию на C ++. Поэтому я считаю, что идея, которая умеет печатать себя с правильной плюрализацией и капитализацией, была бы хорошей идеей.

Предлагаемое решение

#include <iostream>

class BeerWall {
  public:
    BeerWall(unsigned n=99) : n(n), capitalizeNext(false) {}

    BeerWall &consume(int bottles=1) {
        n -= bottles;
        return *this;
    }

    BeerWall &buy(int bottles=1) {
        // Not to be confused with barfing it up.
        return consume(-bottles);
    }

    BeerWall &capitalize(bool cap=true) {
        capitalizeNext = cap;
        return *this;
    }

    unsigned remaining() const {
        return n;
    }

    friend std::ostream &operator<<(std::ostream &os, BeerWall& b) {
        switch (b.n) {
          case 0:
            os << (b.capitalizeNext ? "No more bottles" : "no more bottles");
            break;
          case 1:
            os << "1 bottle";
            break;
          default:
            os << b.n << " bottles";
        }
        b.capitalizeNext = false;
        return os;
    }

  private:
    unsigned n;
    bool capitalizeNext;
};

int main(void)
{
    BeerWall bw;
    do
    {
        std::cout << bw.capitalize() << " of beer on the wall, "
                  << bw << " of beer.\n";

        if (!bw.remaining()) break;

        std::cout << "Take one down and pass it around, "
                  << bw.consume() << " of beer on the wall.\n" << std::endl;
    } while (true);

    std::cout << "Go to the store and buy some more, "
              << bw.buy(99) << " of beer on the wall." << std::endl;
}
ответил 200_success 14 PM000000100000004631 2014, 22:41:46
5

Chillworld ссылается на это решение, я немного расширюсь.

ваш код:

int main (void)
{
    int bottle = 99;
    while (bottle > 0)
    {
        cout << bottle << " bottles of beer on the wall, "
             << bottle << " bottles of beer." << endl;

        bottle--;

        cout << "Take one down and pass it around, " << bottle << " "
             << "bottles of beer on the wall.\n" << endl;

        if (bottle == 1)
        {
            break;
        }
    }

    cout << "1 bottle of beer on the wall, 1 bottle of beer." << endl
         << "Take one down and pass it around, no more bottles of beer on the wall.\n" << endl
         << "No more bottles of beer on the wall, no more bottles of beer." << endl
         << "Go to the store and buy some more, 99 bottles of beer on the wall.";
    return 0;
} 

Все говорили о том, что оператор while не настроен эффективно, а блок if не нужен.

, если вы установите оператор while, чтобы сказать while (bottle > 1), и удалите блок кода if, это будет выглядеть так.

int main (void)
{
    int bottle = 99;
    while (bottleCount > 1)
    {
        std::cout << bottleCount << " bottles of beer on the wall, "
             << bottleCount << " bottles of beer." << std::endl;

        bottleCount--;

        std::cout << "Take one down and pass it around, " << bottleCount << " "
             << "bottles of beer on the wall.\n" << std::endl;
    }

    std::cout << "1 bottle of beer on the wall, 1 bottle of beer." << std::endl
         << "Take one down and pass it around, no more bottles of beer on the wall.\n" << std::endl
         << "No more bottles of beer on the wall, no more bottles of beer." << std::endl
         << "Go to the store and buy some more, 99 bottles of beer on the wall.\n";
    return 0;
} 

К сожалению, у вас все еще есть вопрос о множественной форме бутылки, когда вы попадаете в одну бутылку слева, я бы предположил, что после 98 бутылок пива понадобилось бы чудо науки, чтобы даже петь последний стих.

ответил Malachi 15 PM00000060000005331 2014, 18:02:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132