Прошу оценить код 2

Прошу поюзать и оценить код. Это продолжение моей темы http://code-live.ru/forum/cpp/285/ . Разобрал все комментарии и вот что получилось.
Защиту от дурака все таки решил сделать запросом на ввод цифр (по моему эффект получился на 95%). Единственный бок (это то, что я нашел) это ввод цифры и за ней букв, но сброс некорректного ввода не дает программе уйти в бесконечный цикл, а переходит по цифре в выбранный пункт меню либо делает расчет с этой цифрой. Приходится либо выбирать заново пункт меню, либо делать перерасчет. В принципе можно в менюшках сделать выбор не числовой, а буквенный тогда switch будет обрабатывать цифровой ввод как default... В общем ЖДУ комментарии, как всегда принимаю все камни :).

   // вызов меню
#include <iostream>
#include <string>
#include <cstdlib>

/******************** --------- ПРОТОТИПЫ ФУНКЦИЙ ----------- ******************************/
void month_menu();      // меню месяцы
int slct_month();       // выбор месяца
void account_menu();        // меню типы рассчетов
double slct_account();  // рассчеты

double Gas();   // рассчет газа
double Light(); // рассчет света
double Water(); // рассчет вода
double Sum_account(double, double, double); // расчет суммы
/*************************************************************************************/
namespace my        // для видимости переменных 
{
    int m;  // ввод месяца
    const std::string months[] =
{"январь", "февраль", "март", "апрель", "май", "июнь",
"июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"};
}

using namespace my;

int main(void)
{
    setlocale(LC_ALL, "Russian");
    m = slct_month();
    if (0 == m){
        system("cls");
        std::cout << "До свидания :(\n\n";
        return 0;
    }   
    account_menu();
    double account;
    account = slct_account();
    if (0 == account){
        system("cls");
        std::cout << "До свидания :(\n\n";
        return 0;
    }

    return 0;
}

void month_menu()
{
    std::cout << "1. Январь 7. Июль\n"
         "2. Февраль    8. Август\n"
         "3. Март       9. Сентябрь\n"
         "4. Апрель 10. Октябрь\n"
         "5. Май        11. Ноябрь\n"
         "6. Июнь       12. Декабрь\n"
         "  0. Выход.\n\n";
}
int slct_month()
{
    std::cout << "Выберите месяц:\n\n";
    month_menu();
    int choice;
    int i = 0;
    while (!(std::cin >> choice)){  // проверка на ввод букв
        std::cin.clear();
        while (std::cin.get() != '\n')
            continue;
        std::cout << "\nПожалуйста введите число...\n\n" ;
    }
    while(choice != 0)
    {
        switch(choice)
        {
            case 1 : system("cls"); return 1; break;
            case 2 : system("cls"); return 2; break;
            case 3 : system("cls"); return 3; break;
            case 4 : system("cls"); return 4; break;
            case 5 : system("cls"); return 5; break;
            case 6 : system("cls"); return 6; break;
            case 7 : system("cls"); return 7; break;
            case 8 : system("cls"); return 8; break;
            case 9 : system("cls"); return 9; break;
            case 10 : system("cls"); return 10; break;
            case 11 : system("cls"); return 11; break;
            case 12 : system("cls"); return 12; break;
            default : system("cls"); std::cout << "Пожалуйста сделайте правильный выбор:\n\n";
        }
        month_menu();
        while (!(std::cin >> choice)){
            std::cin.clear();
            while (std::cin.get() != '\n')
                continue;
            std::cout << "\nПожалуйста введите число...\n\n" ;
        }
    }
    return 0;
}
void account_menu()
{
    std::cout << "Расчет оплаты коммунальных услуг за " << months[m - 1] << " месяц\n";
    std::cout << "\n1. Рассчет оплаты за газ\n"
        << "2. Рассчет оплаты за электричество\n"
        << "3. Рассчет оплаты за воду\n"
        << "4. Общая сумма к оплате за " << months[m - 1] << "\n"
        << "5. Выбор месяца\n"
        << "0. Выход\n\n";
}
double slct_account()
{
    int choice;
    double gas, light, water, sum_acc;
    gas = light = water = sum_acc = 0;
    while (!(std::cin >> choice)){      // проверка на ввод букв
        std::cin.clear();
        while (std::cin.get() != '\n')
            continue;
        std::cout << "\nПожалуйста введите число...\n\n" ;
    }
    while (choice != 0){
        switch(choice){
        case 1 : system("cls"); 
                 gas = Gas(); break;
        case 2 : system("cls");
                 light = Light(); break;
        case 3 : system("cls");
                 water = Water(); break;
        case 4 : system("cls");
                 sum_acc = Sum_account(gas, light, water);
                 if (0 == sum_acc){
                    std::cout << "Вы ничего не рассчитали.\n"
                    << "Повторите пожалуйста...\n\n";
                    break;              
                 }
                 std::cout << "Сумма рассчетов за "
                        << months[m - 1] << " : " << sum_acc
                        << "$" << std::endl;
                 std::cout << "<Enter>";
                 std::cin.get();
                 std::cin.get();
                 system("cls");
                 break;
        case 5 : system("cls"); // при выборе месяца сбрасываються все рассчеты
                 m = slct_month();
                 if (0 == m)
                    return 0;
                 gas = light = water = 0; break;
        default : system("cls");
                  std::cout << "Пожалуйста сделайте правильный выбор:\n\n";
        }
        account_menu();
        while (!(std::cin >> choice)){          // проверка на ввод букв
            std::cin.clear();
            while (std::cin.get() != '\n')
                continue;
            std::cout << "\nПожалуйста введите число...\n\n" ;
        }
    }

    return 0;
}
double Gas()
{
    double g;
    const double price1 = 0.7;
    int current1, previous1;
    do{     
        std::cout << "Рассчет стоимости газа за " << months[m - 1] << "\n\n";
        std::cout << "Введите текущее показание: ";
        while (!(std::cin >> current1)){            // проверка на ввод букв
                std::cin.clear();
                while (std::cin.get() != '\n')
                    continue;
                system("cls");
                std::cout << "Рассчет стоимости газа за " << months[m - 1] << "\n\n";
                std::cout << "Введите текущее показание: ";
            }
        std::cout << "Введите предыдущее показание: ";
        while (!(std::cin >> previous1)){       // проверка на ввод букв
                std::cin.clear();
                while (std::cin.get() != '\n')
                    continue;
                system("cls");
                std::cout << "Рассчет стоимости газа за " << months[m - 1] << "\n\n";
                std::cout << "Введите текущее показание: " << current1 << std::endl;
                std::cout << "Введите предыдущее показание: ";
            }
        if (current1 < previous1){      // проверка - первое показание должно быть > второго
            std::cout << "\nТекущее показание не может быть меньше чем предыдущее!!!\n"
                      << "Введите корректные показания...\n"
                      << "<Enter>\n";
            std::cin.get();
            std::cin.get();
            system("cls");
            }
    }while (current1 < previous1);
    g = (current1 - previous1) * price1;
    std::cin.get();
    std::cout << "Израсходовано: " << (current1 - previous1) << " м3" << std::endl;
    std::cout << "Сумма оплаты: " << g << "$" << std::endl;
    std::cout << "<Enter>" << std::endl;

    std::cin.get();
    system("cls");
    return g;
}
double Light()
{
    double l;
    const double price2 = 0.3;
    int current2, previous2;
    do{
        std::cout << "Рассчет стоимости электричества за " << months[m - 1] << "\n\n";
        std::cout << "Введите текущее показание: ";
        while (!(std::cin >> current2)){                // проверка на ввод букв
                std::cin.clear();
                while (std::cin.get() != '\n')
                    continue;
                system("cls");
                std::cout << "Рассчет стоимости электричества за " << months[m - 1] << "\n\n";
                std::cout << "Введите текущее показание: ";
            }
        std::cout << "Введите предыдущее показание: ";
        while (!(std::cin >> previous2)){           // проверка на ввод букв
                std::cin.clear();
                while (std::cin.get() != '\n')
                    continue;
            system("cls");
            std::cout << "Рассчет стоимости электричества за " << months[m - 1] << "\n\n";
            std::cout << "Введите текущее показание: " << current2 << std::endl;
            std::cout << "Введите предыдущее показание: ";
        }
        if (current2 < previous2){      // проверка - первое показание должно быть > второго
            std::cout << "\nТекущее показание не может быть меньше чем предыдущее!!!\n"
                      << "Введите корректные показания...\n"
                      << "<Enter>\n";
            std::cin.get();
            std::cin.get();
            system("cls");
            }
    }while (current2 < previous2);
    l = (current2 - previous2) * price2;
    std::cin.get();
    std::cout << "Израсходовано: " << (current2 - previous2) << " кВт" << std::endl;
    std::cout << "Сумма оплаты: " << l << "$" << std::endl;
    std::cout << "<Enter>" << std::endl;

    std::cin.get();
    system("cls");
    return l;
}
double Water()
{
    double w;
    const double price3 = 2.0;
    int current3, previous3;
    do{
        std::cout << "Рассчет стоимости воды за " << months[m - 1] << "\n\n";
        std::cout << "Введите текущее показание: ";
        while (!(std::cin >> current3)){                // проверка на ввод букв
                std::cin.clear();
                while (std::cin.get() != '\n')
                    continue;
                system("cls");
                std::cout << "Рассчет стоимости воды за " << months[m - 1] << "\n\n";
                std::cout << "Введите текущее показание: ";
            }
        std::cout << "Введите предыдущее показание: ";
        while (!(std::cin >> previous3)){           // проверка на ввод букв
                std::cin.clear();
                while (std::cin.get() != '\n')
                    continue;
                system("cls");
                std::cout << "Рассчет стоимости воды за " << months[m - 1] << "\n\n";
                std::cout << "Введите текущее показание: " << current3 << std::endl;
                std::cout << "Введите предыдущее показание: ";
            }
        if (current3 < previous3){      // проверка - первое показание должно быть > второго
            std::cout << "\nТекущее показание не может быть меньше чем предыдущее!!!\n"
                      << "Введите корректные показания...\n"
                      << "<Enter>\n";
            std::cin.get();
            std::cin.get();
            system("cls");
            }
    }while (current3 < previous3);
    w = (current3 - previous3) * price3;
    std::cin.get();
    std::cout << "Израсходовано: " << (current3 - previous3) << " м3" << std::endl;
    std::cout << "Сумма оплаты: " << w << "$" << std::endl;

    std::cin.get();
    system("cls");
    return w;
}
double Sum_account(double g, double l, double w)
{
    double sum = g + l + w;
    return sum;
}

Лови кирпичи. ))

  1. Слово расчёт пишется с одной буквой С!
  2. Очень много дублирующегося кода.
  3. Неоправданное использование глобальной переменной m.
  4. Три точки выхода из функции main(). Да ещё и с кривой логикой работы функции. Оно прям-таки просится на переделку.
  5. Программа разбита на функции странным и нелогичным образом (с моей точки зрения).
  6. Логика работы программы на уровне смысловых блоков странновата (опять-таки с моей точки зрения).

Я немножко причесал твою программу. Тоже получился не идеал, но всё же, как мне кажется, поаккуратнее.

#include <iostream>
#include <iomanip>

using namespace std;

// Расценки за коммунальные услуги:

const double PRICE_GAS = 0.7;
const double PRICE_WATER = 2.0;
const double PRICE_ELECTRICITY = 0.3;

// Единицы измерения

const char *stere = "м3";
const char *kW = "кВт";

const char *months[] = {
    "январь", "февраль", "март", "апрель", "май", "июнь",
    "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"
};


typedef bool (CHECK_FUNC)(int);

bool is_positive(int num) {
    return num > 0;
}

bool is_natural(int num) {
    return num >= 0;
}

bool is_month(int num) {
    return num >= 0 && num <= 12;
}

bool is_choice(int num) {
    return num >= 0 && num <= 4;
}

int get_number(CHECK_FUNC *check = NULL) {
    int num = 0;
    bool fail = false;

    do {
        fail = false;
        cin >> num;
        if (cin.fail()) {
            fail = true;
            cin.clear();
            cin.sync();
        }
        else {
            if (check != NULL) {
                fail = !check(num);
            }
        }
        if (fail) {
            cout << "*** Введено некорректное значение. Повторите ввод." << endl;
        }
    } while (fail);
    return num;
}


int checkout_month() {
    for (int i = 0; i < 6; i++) {
        cout << setw(2) << right << (i+1) << ". " << setw(15) << left << months[i] <<
            setw(8) << right << (i+7) << ". " << setw(15) << left << months[i+6] << endl;
    }
    cout << "\nУкажите номер расчётного месяца от 1 до 12 или 0 для выхода: ";
    return get_number(is_month);
}

double calc_cost(const double price, const char *unit_name) {
    int curr, prev;
    bool fail = false;
    do {
        cout << "\nВведите текущее показание:    ";
        curr = get_number(is_positive);
        cout << "Введите предыдущее показание: ";
        prev = get_number(is_positive);
        fail = prev > curr;
        if (fail) {
            cout << "*** Текущее показание не может быть меньше чем предыдущее!!!\n"
                "*** Введите корректные показания...\n";
        }
    } while (fail);

    int consumption = curr - prev;
    double cost =  static_cast<double>(consumption) * price;

    cout << "\nИзрасходовано:  " << consumption << " " << unit_name << endl
         << "Сумма к оплате: " << "$" << cost << endl;
    return cost;
}

double sum_ary(const double *ary, int size) {
    double sum = 0.0;
    for (int i = 0; i < size; i++)
        sum += ary[i];
    return sum;
}

const int UTILITIES_QTY = 3;

void calc_public_utilities() {
    const char *month;
    month = months[checkout_month() - 1];
    cout << "\nРасчётный месяц: " << month << endl;
    double costs[UTILITIES_QTY] = { 0.0, 0.0, 0.0 };
    int choice;
    do {
        cout << "\n"
            "Начисления за " << month << "\n"
            "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
            << setw(20) << "Газ" << "$ " << costs[0] << endl
            << setw(20) << "Электроэнергия" << "$ " << costs[1] << endl
            << setw(20) << "Вода" << "$ " << costs[2] << endl
            <<  "------------------------------\n"
            << setw(20) << "Итого" << "$ " << sum_ary(costs, UTILITIES_QTY) << endl
            << "\n"
            "1. Расчёт оплаты за газ\n"
            "2. Расчёт оплаты за электричество\n"
            "3. Расчёт оплаты за воду\n"
            "4. Выбор месяца\n"
            "0. Выход\n\n"
            "Ваш выбор: ";
        choice = get_number(is_choice);
        switch (choice) {
        case 1:
            costs[0] = calc_cost(PRICE_GAS, stere);
            break;
        case 2:
            costs[1] = calc_cost(PRICE_ELECTRICITY, kW);
            break;
        case 3:
            costs[2] = calc_cost(PRICE_WATER, stere);
            break;
        case 4:
            month = months[checkout_month() - 1];
            cout << "\nРасчётный месяц: " << month << endl;
            for (int i = 0; i < UTILITIES_QTY; i++) {
                costs[i] = 0.0;
            }
            break;
        }
    } while (choice != 0);

}

int main() {

    setlocale(LC_CTYPE, "Russian");

    cout << "*** Калькулятор оплаты коммунальных услуг ***\n\n";

    calc_public_utilities();

    system("pause");
    return 0;
}

Если ещё немножко пофантазировать на данную тему, то можно сделать класс, который содержит информацию по платежу за одну коммунальную услугу: код услуги (газ, электричество, вода), цена за единицу (цены у нас растут с удручающей регулярностью), наименование единицы измерения, расчётный месяц и год, текущее и предыдущее значения счётчика, наименование единицы измерения (возможно как код, а не строка).

При этом можно и код данной программы сделать ещё более аккуратным, и, при желании, достаточно просто будет доработать программу так, что бы она хранила на диске файл данных с предыдущими расчётами.

Слово расчёт пишется с одной буквой С!

Здесь стопроцентный дефолт ;)))

Очень много дублирующегося кода.

Ты прав и по сути этот дублирующийся код можно уместить в двух функциях на проверку букв и на ввод корректных значений. Если так сделать и в функцию double Sum_account добавить такую красивую табличку, которая подогнана манипуляторами, то код уменьшиться раза в полтора.

Неоправданное использование глобальной переменной m.

Для видимости переменных во всем коде я объявил свое пространство имен... ??? Если можешь объясни пожалуйста в чем подвох. Это как-то влияет на производительность?

Три точки выхода из функции main(). Да ещё и с кривой логикой работы функции. Оно прям-таки просится на переделку.

Здесь тоже если можешь объясни. В чем проблема если три выхода? Допустим можно зациклить код в функции

 main() {
 double account;
 do{
     m = slct_month();
     if (0 == m)
         break;
     account_menu();   
     account = slct_account(); 
}while (m != 0 && account != 0);
    system("cls");
    std::cout << "До свидания :(\n\n";
  return 0;
}

Программа разбита на функции странным и нелогичным образом (с моей точки зрения).
Логика работы программы на уровне смысловых блоков странновата (опять-таки с моей точки зрения).

Функции пытался разбить по функционалу: меню, выбор и расчет. Как можно более ограничил объявление и инициализацию переменных в функциях. Упор на расчетную часть пока не делал, так-как пытался добиться функциональности и корректного ввода пользователя.
На данном этапе осваиваю функции, до классов остался один шаг (по моей книге) так что классы для меня пока непаханая целина :)))
Спасибо, Череп, за как всегда исчерпывающие комментарии. Ответь пожалуйста на вопрос о глобальной переменной и на неоднократный выход из функции main().
TO BE CONTINUED...

Некоторые возможности C++ рекомендуется использовать только в случаях крайней необходимости: глобальные переменные, оператор goto, макросы (хотя это фича препроцессора...), множественное наследование и пр. В большинстве случаев это связано не с производительностью, а с качеством написания программного кода.

Качественный код прост для понимания, отладки, модификации, поддержки. На начальном этапе освоения программирования эти вещи кажутся второстепенными. Но... чем дальше в лес — тем толще партизаны. Важность качества кода люди обычно начинают понимать после 30-40 часов отладки программки на полторы тысячи строк, которая почти всегда работает правильно.

Глобальные переменные плохи тем, что порождают побочные эффекты работы функций. В идеале, функция — это «чёрный ящик»: на вход подали чётко определённые данные, на выходе получили чётко определённый результат. Но если функция в результате своей работы неявно изменяет что-то вне себя (глобальные переменные), то это сразу становится потенциальным источником ошибок, которые, к тому же, достаточно трудно локализуются. А своё пространство имён, в данном случае, это даже не подстеленная соломка, а так... промокашка.

Многократные точки выхода из функции — это тоже неаккуратность, затрудняющая отладку. В идеале, опять-таки, функция должна иметь одну точку входа и одну точку выхода (в конце функции). Но лично я считаю, что функция может иметь несколько точек выхода, но только при условии строгой логической обоснованности. Например, для корректной работы функции требуется, что бы аргументы удовлетворяли определённым условиям, иначе функция будет завершаться с ошибкой. Проверки условий с выходом с ошибкой могут быть в начале функции, дабы избежать нескольких вложенных if'ов, но совершенно нежелательны из середины функции.

В твоём случае, если брать первый вариант ф-ции main(), ты запутался в собственной логике работы программы. Ф-ция slct_account() всегда заканчивает работу с кодом 0 (кстати, почему тип возвращаемого результат double?). Учитывая это, и изменив условие в первом if на обратное, получим совершенно вменяемый код:

int main(void)
{
    setlocale(LC_ALL, "Russian");
    m = slct_month();
    if (0 != m){
        account_menu();
        slct_account();
    }
    system("cls");
    std::cout << "До свидания :(\n\n";

    return 0;
}

Во втором варианте, с зацикливанием, вообще ничего не получится: переменная account всегда будет равна 0, следовательно вторая часть условного выражения всегда false, следовательно всё выражение будет false. И вообще не понятно зачем этот цикл нужен: цикл с подобным смыслом у тебя уже реализован в slct_account().

Резюме. Логику работы программы надо продумывать до, а не во время кодирования.

Череп, ты понимаешь, завершить программу из функции я не могу, так-как программа завершается в главном файле. Имеется две функции, в меню которых можно завершить программу, и именно они передают в main() true или false, ну а там где два значения там и начинается лес с партизанами:)))
На счет глобальных переменных: получается получив значениеm из функции slct_month() , мне нужно передавать ее по цепочке из main() в slct_account() а из slct_account() во все остальные.
Хорошо, а если объявить переменную m с модификатором static? Мне же нужно чтобы она была видна во всех функциях?
Я тут учитывая замечания переписал код: убрал повторы и вставил твой цикл в main(). Посмотри пожалуйста.

// вызов меню
#include <iostream>
#include <string>
#include <cstdlib>
#include <iomanip>
#include <cmath>

/*************************** --------- ПРОТОТИПЫ ФУНКЦИЙ ----------- *************************************/
void month_menu();      // меню месяцы
void account_menu();        // меню типы рассчетов
int input_choice();     // для проверки на не числовой ввод
int slct_month();       // выбор месяца
int slct_account(); // рассчеты
int input_readout(std::string type_calc);   // ввод показаний

double Gas();   // рассчет газа
double Light(); // рассчет света
double Water(); // рассчет вода
double Sum_account(double, double, double); // расчет суммы
/*********************************************************************************************************/
 static int m;  // ввод месяца
static std::string months[] =
{"январь", "февраль", "март", "апрель", "май", "июнь",
"июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"};
static std::string type_calc[] = {"газа", "электричества", "воды"};

/***********************************---------КОНСТАНТЫ ---------********************************************/
const double price1 = 0.7254;           // цена на газ
const double price2 = 0.2802;           // цена на воду
const double price3 = 3.41;             // цена на свет

using namespace my;

int main(void)
{
    setlocale(LC_ALL, "Russian");
    int account;
    m = slct_month();
    if (0 != m){    
        account_menu();
        account = slct_account();
    }
    system("cls");
    std::cout << "До свидания :(\n\n";
    return 0;
}

void month_menu()       // меню выбора месяцев
{
    using namespace std;
    for (int i = 0; i < 6; ++i)
         cout << setw(2) << right << (i+1) << ". " << setw(10) << left << months[i]
                   << setw(8) << right << (i+7) << ". " << setw(15) << left << months[i+6] << endl;
    cout << setw(20) << right << "0. выход\n\n";
}
int slct_month()        // функция для выбора месяца
{
    std::cout << std::setw(21) << std::right << "Выберите месяц:\n\n";
    month_menu();
    int choice;
    choice = input_choice();
    while(choice != 0)
    {
        switch(choice)
        {
            case 1 : system("cls"); return 1; break;
            case 2 : system("cls"); return 2; break;
            case 3 : system("cls"); return 3; break;
            case 4 : system("cls"); return 4; break;
            case 5 : system("cls"); return 5; break;
            case 6 : system("cls"); return 6; break;
            case 7 : system("cls"); return 7; break;
            case 8 : system("cls"); return 8; break;
            case 9 : system("cls"); return 9; break;
            case 10 : system("cls"); return 10; break;
            case 11 : system("cls"); return 11; break;
            case 12 : system("cls"); return 12; break;
            default : system("cls"); std::cout << "Пожалуйста сделайте правильный выбор:\n\n";
        }
        month_menu();
        choice = input_choice();
    }
    return 0;
}
void account_menu()         // меню расчетов
{
    std::cout << "Расчет оплаты коммунальных услуг за " << months[m - 1] << " месяц\n";
    std::cout << "\n1. Рассчет оплаты за газ\n"
              << "2. Рассчет оплаты за электричество\n"
              << "3. Рассчет оплаты за воду\n"
              << "4. Общая сумма к оплате за " << months[m - 1] << "\n"
              << "5. Выбор месяца\n"
              << "0. Выход\n\n";
}
int slct_account()      // выбор вида расчета, вывод общей суммы, выбор месяца, выход
{
    int choice;
    double gas, light, water, sum_acc;
    gas = light = water = sum_acc = 0;
    choice = input_choice();
    while (choice != 0){
        switch(choice){
        case 1 : system("cls"); 
                 gas = Gas(); break;
        case 2 : system("cls");
                 light = Light(); break;
        case 3 : system("cls");
                 water = Water(); break;
        case 4 : system("cls");
                 sum_acc = Sum_account(gas, light, water);
                 if (0 == sum_acc){
                    std::cout << "Вы ничего не рассчитали.\n"
                              << "Повторите пожалуйста...\n\n";
                    break;              
                 }
                 std::cout << "Сумма рассчетов за " << months[m - 1] << std::endl << std::endl <<                            
                "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
                << std::setw(20) << std::left << "Газ" << "$ " << gas << std::endl
                << std::setw(20) << "Электроэнергия" << "$ " << light << std::endl
                << std::setw(20) << "Вода" << "$ " << water << std::endl
                <<  "------------------------------\n"
                << std::setw(20) << "Итого" << "$ " << sum_acc << std::endl;
                 std::cout << "\n<Enter>";
                 std::cin.get();
                 std::cin.get();
                 system("cls");
                 break;
        case 5 : system("cls"); // при выборе месяца сбрасываються все рассчеты
                 m = slct_month();
                 if (0 == m)
                    return 0;
                 gas = light = water = 0; break;
        default : system("cls");
                  std::cout << "Пожалуйста сделайте правильный выбор:\n\n";
        }
        account_menu();
        choice = input_choice();
    }

    return 0;
}
int input_choice()          // функция проверки на ввод букв
{
    int choice;
    while (!(std::cin >> choice)){
            std::cin.clear();
            while (std::cin.get() != '\n')
                continue;
            std::cout << "\nПожалуйста введите число...\n\n" ;
        }
    return choice;
}
double Gas()
{
    int difr;
    double g;
    difr = input_readout(type_calc[0]);
    g = difr * price1;
    std::cin.get();
    std::cout << "Израсходовано: " << difr << " м3" << std::endl;
    std::cout << "Сумма оплаты: " << g << "$" << std::endl;
    std::cout << "<Enter>" << std::endl;

    std::cin.get();
    system("cls");
    return g;
}
double Light()
{
    int difr;
    double l;
    difr = input_readout(type_calc[1]);
    l = difr * price2;
    std::cin.get();
    std::cout << "Израсходовано: " << difr << " кВт" << std::endl;
    std::cout << "Сумма оплаты: " << l << "$" << std::endl;
    std::cout << "<Enter>" << std::endl;

    std::cin.get();
    system("cls");
    return l;
}
double Water()
{
    int difr;
    double w;
    difr = input_readout(type_calc[2]);
    w = difr * price3;
    std::cin.get();
    std::cout << "Израсходовано: " << difr << " м3" << std::endl;
    std::cout << "Сумма оплаты: " << w << "$" << std::endl;

    std::cin.get();
    system("cls");
    return w;
}
int input_readout(std::string type)
{
    int current, previous, difr;
    do{     
        std::cout << "Рассчет стоимости " << type << " за " << months[m - 1] << "\n\n";
        std::cout << "Введите текущее показание: ";
        while (!(std::cin >> current)){         // проверка на ввод букв
                std::cin.clear();
                while (std::cin.get() != '\n')
                    continue;
                system("cls");
                std::cout << "Рассчет стоимости " << type << " за " << months[m - 1] << "\n\n";
                std::cout << "Введите текущее показание: ";
            }
        std::cout << "Введите предыдущее показание: ";
        while (!(std::cin >> previous)){        // проверка на ввод букв
                std::cin.clear();
                while (std::cin.get() != '\n')
                    continue;
                system("cls");
                std::cout << "Рассчет стоимости " << type << " за " << months[m - 1] << "\n\n";
                std::cout << "Введите текущее показание: " << current << std::endl;
                std::cout << "Введите предыдущее показание: ";
            }
        if (current < previous){        // проверка - первое показание должно быть > второго
            std::cout << "\nТекущее показание не может быть меньше чем предыдущее!!!\n"
                      << "Введите корректные показания...\n"
                      << "<Enter>\n";
            std::cin.get();
            std::cin.get();
            system("cls");
            }
    }while (current < previous);
    difr = current - previous;
    return difr;
}
double Sum_account(double g, double l, double w)
{
    double sum = g + l + w;
    return sum;
}

Спасибо за комментарии, в принципе все ясно, кроме глобальных переменных. Какая альтернатива?

Череп, просто бросилось в глаза. В году у тебя получается 13 месяцев.

bool is_month(int num) {
    return num >= 0 && num <= 12;
}

и еще вот в этом куске
/*****————-КОНСТАНТЫ ————-********/
const double price1 = 0.7254; // цена на газ
const double price2 = 0.2802; // цена на воду
const double price3 = 3.41; // цена на свет

using namespace std; а тут было (my) наверно опечатка=)

но у меня на вижуале 2012 выдает там ошибку=)

Ну я не запускал тут ничего, но по замыслу автора, он, вроде, свой namespace определил и намеренно задал его по-умолчанию.

Нет, selevit, в году у меня таки 12 месяцев )) «Нулевой» месяц используется как флаг выхода. Я просто не стал кардинально менять логику работы программы.

ну я запускал все работает нормально!!!=)

Просто я программу модернизировал, в которой были определенны переменные в области видимости my, а при модернизации переменные удалил (в чем скорее всего кроется ошибка у Анонима), а директиву оставил:)

Юрий, ты смотрел мой вариант твоей программы? Я же обошёлся без глобальных переменных.

Модификатор static здесь не нужен. Глобальная переменная с модификатором static так и останется глобальной. Здесь вопрос чисто принципиальный: используются или не используются глобальные переменные. Чем они нехороши — я уже писал.

Что можно сделать: изменить конструкцию (внутреннюю логику) программы и/или передавать информацию в функции через аргументы.

Имеется две функции, в меню которых можно завершить программу, и именно они передают в main() true или false, ну а там где два значения там и начинается лес с партизанами:)))

Партизаны начались даже раньше леса )) Когда программу можно завершить в нескольких местах (не вследствие ошибки, несовместимой с жизнью!), это уже указывает на недоработки в проектировании программы. Кстати о «true или false», ни одной переменной типа bool в программе нет ))

Несколько замечаний по последней версии кода:

  1. Функция input_readout() полностью унаследовала уродливость из предыдущей версии. Почему ты не стал в ней использовать ф-цию input_choice()? Забыл? Для ввода целых показаний счётчиков она вполне сгодится.
  2. В функциях slct_month() и slct_account() логичнее использовать цикл с постусловием вместо цикла с предусловием.
  3. Функции account_menu(), month_menu(), Sum_account() вообще не нужны в виде функций. Функция — это всё-таки логический блок, а не просто кусок кода. При реализации предыдущего пункта, account_menu() и month_menu() органично впишутся внутрь slct_account() и slct_month() соответственно.
  4. Крутой switch в slct_month() меня подкосил ещё в первой версии кода. Теперь он меня добил окончательно. Живучий оказался, собака ((
  5. РасСчёт — туда же ((
  6. Если есть возможность пользоваться конкатенацией строк на уровне компилятора, этим надо пользоваться. Например,
    std::cout << "\n1. Рассчет оплаты за газ\n"
              << "2. Рассчет оплаты за электричество\n"
              << "3. Рассчет оплаты за воду\n"
              << "4. Общая сумма к оплате за " << months[m - 1] << "\n"
              << "5. Выбор месяца\n"
              << "0. Выход\n\n";

лучше написать так:

    std::cout << "\n1. Расчет оплаты за газ\n"
              "2. Расчет оплаты за электричество\n"
              "3. Расчет оплаты за воду\n"
              "4. Общая сумма к оплате за " << months[m - 1] << "\n"
              "5. Выбор месяца\n"
              "0. Выход\n\n";

здесь экономится пять вызовов функций operator << ().

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.