21

(18 відповідей, залишених у C++)

raxp, я Вам дякую, але як створювати ProgressBar, я вже розібрала, основна моя проблема в тому, що невдається поєднати процес копіювання та заповнення ProgressBar.

22

(18 відповідей, залишених у C++)

Я вже зробила його не глобальним, але від цього моя проблема не вирішилась: ProgressBar все рівно не заповнюється і вікно, де знаходиться ProgressBar, вісить, поки не натисну хрестик.

23

(18 відповідей, залишених у C++)

Мені вдалось зробити, щоб було видно ProgressBar, але тепер вікно постійно відкрите і ProgressBar не заповнюється.

Прихований текст
/*Завдання 1. Створити програму для копіювання файлів,
програма повинна міcтити діалогове вікно з кнопкою Open,
що відкриває стандартний діалог вибору файлів та кнопкою SaveAs,
що відкриває стандартний діалог збереження файлу.
Після чого повинно запускатись копіювання файлу в окремому потоці.

Додатково. Відображати процес копіювання кожного файлу на окремому індикаторі процесу.
Передбачити неможливість повторного копіювання файлу, що вже копіюється.
*/

#include <windows.h>
#include <tchar.h>
#include <CommCtrl.h>
#include "resource.h"
#pragma warning (disable:4996)

struct CopyFileName
{
    wchar_t first_file[MAX_PATH];
    wchar_t second_file[MAX_PATH];
};

HWND hNoModeless;
HWND hProgressBar;

DWORD CALLBACK CopyProgressRoutine(LARGE_INTEGER liTotalFileSize,
                                   LARGE_INTEGER liTotalBytesTransferred,
                                   LARGE_INTEGER liStreamSize,
                                   LARGE_INTEGER liStreamBytesTransferred,
                                   DWORD dwStreamNumber,
                                   DWORD dwCallbackReason,
                                   HANDLE hSourceFile,
                                   HANDLE hDestinationFile,
                                   LPVOID lpvData)
{
    HWND lpProgressCtrl = (HWND)lpvData;

    SendMessage(lpProgressCtrl, PBM_SETPOS, (liTotalBytesTransferred.QuadPart / liTotalFileSize.QuadPart * 100), 0);
    SendMessage(lpProgressCtrl, PBM_STEPIT, 0, 0);

    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!IsDialogMessage(hNoModeless, &msg))
        {
            //TranslateMessage(&msg); - обробка даних від клавіатури
            DispatchMessage(&msg);
        }
    }

    return PROGRESS_CONTINUE;
}

BOOL CALLBACK ModelessDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        /*hProgressBar = CreateWindow(PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE, 20, 60, 350, 30, hWnd, NULL, GetModuleHandle(NULL), NULL);
        SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
        SendMessage(hProgressBar, PBM_SETSTEP, 1, 0);
        SendMessage(hProgressBar, PBM_SETPOS, 0, 0);*/
        ShowWindow(hProgressBar, SW_SHOW);
        return 1;

    case WM_CLOSE:
        DestroyWindow(hWnd);
        hNoModeless = nullptr;
        hProgressBar = nullptr;
        return 1;
    }

    return 0;
}

DWORD WINAPI CopyThread(PVOID pvParam)
{
    CopyFileName* temp_files = (CopyFileName*)pvParam;

    //Create modeless dialog
    hNoModeless = CreateDialog(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG2), GetDlgItem(NULL, IDD_DIALOG1), ModelessDlgProc);
    ShowWindow(hNoModeless, SW_SHOW);
    //--------------------
    
    //Init ProgressBar
    hProgressBar = CreateWindow(PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE, 20, 60, 350, 30, hNoModeless, NULL, GetModuleHandle(NULL), NULL);
    SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
    SendMessage(hProgressBar, PBM_SETSTEP, 1, 0);
    SendMessage(hProgressBar, PBM_SETPOS, 0, 0);
    //--------------------

    CopyFileEx(temp_files->first_file, temp_files->second_file, CopyProgressRoutine, &hProgressBar, FALSE, COPY_FILE_FAIL_IF_EXISTS);
    
    return 0;
}

BOOL CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static OPENFILENAME ofn;
    static wchar_t file[MAX_PATH] = L"\0";
    static wchar_t buff[MAX_PATH] = L"\0";
    static DWORD dwFileSize = 0, bytesToRead = 0, bytesRead = 0;
    CopyFileName* files_name = new CopyFileName;

    switch (uMsg)
    {
    case WM_INITDIALOG:

        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = hWnd;
        ofn.lpstrFile = file;
        ofn.lpstrFilter = L"All\0*.*\0";
        ofn.nFilterIndex = 1;
        ofn.nMaxFile = MAX_PATH;

        return 1;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDC_OPEN:
            if (GetOpenFileName(&ofn))
            {
                if (lstrcmp(ofn.lpstrFile, buff) == 0)
                    MessageBox(NULL, L"This file is copying", L"Error", MB_OK|MB_ICONERROR);
                else
                    lstrcpy(buff, ofn.lpstrFile);
                break;
            }

        case IDC_SAVE_AS:
            if (GetSaveFileName(&ofn))
            {
                lstrcpy(files_name->second_file, ofn.lpstrFile);
                lstrcpy(files_name->first_file, buff);
                CreateThread(NULL, 0, CopyThread, files_name, NULL, NULL);
                break;
            }
        }
        return 1;

    case WM_CLOSE:
        EndDialog(hWnd, 0);
        return 1;
    }
    delete files_name;
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR nCmd, int nCmdShow)
{
    INITCOMMONCONTROLSEX cc;
    cc.dwSize = sizeof(INITCOMMONCONTROLSEX);
    cc.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&cc);
    
    DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);

    return 0;
}

24

(18 відповідей, залишених у C++)

Задача: Створити програму для копіювання файлів,
програма повинна міcтити діалогове вікно з кнопкою Open,
що відкриває стандартний діалог вибору файлів та кнопкою SaveAs,
що відкриває стандартний діалог збереження файлу.
Після чого повинно запускатись копіювання файлу в окремому потоці.

Додатково. Відображати процес копіювання кожного файлу на окремому індикаторі процесу.
Передбачити неможливість повторного копіювання файлу, що вже копіюється.

Ось те, що я зробила:

Прихований текст
#include <windows.h>
#include <tchar.h>
#include <CommCtrl.h>
#include "resource.h"
#pragma warning (disable:4996)

HWND hNoModeless;
HWND hProgressBar;

struct CopyFileName
{
    wchar_t first_file[MAX_PATH];
    wchar_t second_file[MAX_PATH];
};

DWORD CALLBACK CopyProgressRoutine(LARGE_INTEGER liTotalFileSize,
                                   LARGE_INTEGER liTotalBytesTransferred,
                                   LARGE_INTEGER liStreamSize,
                                   LARGE_INTEGER liStreamBytesTransferred,
                                   DWORD dwStreamNumber,
                                   DWORD dwCallbackReason,
                                   HANDLE hSourceFile,
                                   HANDLE hDestinationFile,
                                   LPVOID lpvData)
{
    HWND lpProgressCtrl = (HWND)lpvData;

    SendMessage(lpProgressCtrl, PBM_SETPOS, (liTotalBytesTransferred.QuadPart / liTotalFileSize.QuadPart * 100), 0);
    SendMessage(lpProgressCtrl, PBM_STEPIT, 0, 0);
    return PROGRESS_CONTINUE;
}

BOOL CALLBACK ModelessDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        hProgressBar = CreateWindow(PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE | PBS_SMOOTH, 100, 20, 300, 30, hNoModeless, NULL, GetModuleHandle(NULL), NULL);
        SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
        SendMessage(hProgressBar, PBM_SETSTEP, 1, 0);
        SendMessage(hProgressBar, PBM_SETPOS, 0, 0);
        return 1;

    case WM_CLOSE:
        DestroyWindow(hWnd);
        hNoModeless = nullptr;
        hProgressBar = nullptr;
        return 1;
    }
    return 0;
}

DWORD WINAPI CopyThread(PVOID pvParam)
{
    CopyFileName* temp_files = (CopyFileName*)pvParam;

    hNoModeless = CreateDialog(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_DIALOG2), NULL, ModelessDlgProc);
    ShowWindow(hNoModeless, SW_SHOW);
        
    CopyFileEx(temp_files->first_file, temp_files->second_file, CopyProgressRoutine, &hProgressBar, FALSE, COPY_FILE_FAIL_IF_EXISTS);
    
    return 0;
}

BOOL CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static OPENFILENAME ofn;
    static wchar_t file[MAX_PATH] = L"\0";
    static wchar_t buff[MAX_PATH] = L"\0";
    static DWORD dwFileSize = 0, bytesToRead = 0, bytesRead = 0;
    CopyFileName* files_name = new CopyFileName;

    switch (uMsg)
    {
    case WM_INITDIALOG:
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = hWnd;
        ofn.lpstrFile = file;
        ofn.lpstrFilter = L"All\0*.*\0";
        ofn.nFilterIndex = 1;
        ofn.nMaxFile = MAX_PATH;

        return 1;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDC_OPEN:
            if (GetOpenFileName(&ofn))
            {
                if (lstrcmp(ofn.lpstrFile, buff) == 0)
                    MessageBox(NULL, L"This file is copying", L"Error", MB_OK|MB_ICONERROR);
                else
                    lstrcpy(buff, ofn.lpstrFile);
                break;
            }

        case IDC_SAVE_AS:
            if (GetSaveFileName(&ofn))
            {
                lstrcpy(files_name->second_file, ofn.lpstrFile);
                lstrcpy(files_name->first_file, buff);
                CreateThread(NULL, 0, CopyThread, files_name, NULL, NULL);
                break;
            }
        }
        return 1;

    case WM_CLOSE:
        EndDialog(hWnd, 0);
        return 1;
    }
    delete files_name;
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR nCmd, int nCmdShow)
{
    INITCOMMONCONTROLSEX cc;
    cc.dwSize = sizeof(INITCOMMONCONTROLSEX);
    cc.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&cc);
    
    DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
    return 0;
}

Програма виконує копіювання файлів будь-якого типу (з цим я довго розбиралась, але вийшло :) ), але в мене виникла проблема з під'єднанням ProgressBar до процесу копіювання:
1. Взагалі не вдається відобразити його.

2. Потрібно окремий ProgressBar для кожного потоку. Це я намагаюсь зробити через немодальне вікно: врезультаті вікно з'являється - ProgressBar нема)), але саме вікно видно, поки триває процес копіювання.

Підкажіть як правильно з ним (ProgressBar) працювати, і що я не так роблю.

25

(2 відповідей, залишених у C++)

дякую, зрозуміла.

26

(2 відповідей, залишених у C++)

Маю код:

Прихований текст
#include <iostream>
#include <conio.h>

using namespace std;

class Unit
{
protected:
    double health;
    int damage;
public:
    Unit()
    {
        health = 100;
        damage = 30;
    }

    Unit(double health, int damage)
    {
        this->health = health;
        this->damage = damage;
    }

    virtual void Show() = 0;
};

class Marine : public Unit
{
public:

    Marine() : Unit(200, 35)
    {}

    virtual void Show() override
    {
        cout << "\nMarine: \n";
        cout << "\n\thealth: " << health << "\n";
        cout << "\n\tdamage: " << damage << "\n";
    }
};

class MadScientist : public Unit
{
public:

    MadScientist() : Unit(150, 40)
    {}

    virtual void Show() override
    {
        cout << "\nMad scientist: \n";
        cout << "\n\thealth: " << health << "\n";
        cout << "\n\tdamage: " << damage << "\n";
    }
};

class MilitaryDoctor : public Unit
{
public:

    MilitaryDoctor() : Unit()
    {}

    virtual void Show() override
    {
        cout << "\nMilitary doctor: \n";
        cout << "\n\thealth: " << health << "\n";
        cout << "\n\tdamage: " << damage << "\n";
    }
};

class Barrack
{
public:
    virtual Unit* CreateUnit() = 0;
};

class MilitaryBarrack : public Barrack
{

public:
    virtual Unit* CreateUnit() override
    {
        return new Marine;
    }
};

class ScientistBarrack : public Barrack
{
public:
    virtual Unit* CreateUnit() override
    {
        return new MadScientist;
    }
};

class MedicalBarrack : public Barrack
{
public:
    virtual Unit* CreateUnit() override
    {
        return new MilitaryDoctor;
    }
};

void PrintMenu()
{
    cout << "\n\tMenu\n";
    cout << "\n1 - Military barrack\n";
    cout << "\n2 - Scientist barrack\n";
    cout << "\n3 - Medical barrack\n";
    cout << "\nYour choice: ";
}

int main()
{
    Barrack *barrack = NULL;

    enum menu_items{ MILITARY = 1, SCIENTIST, MEDICAL };

    system("cls");
    PrintMenu();
    int user_choice;
    cin >> user_choice;
    switch (user_choice)
    {
    case MILITARY:
        barrack = new MilitaryBarrack;
        break;
    case SCIENTIST:
        barrack = new ScientistBarrack;
        break;
    case MEDICAL:
        barrack = new MedicalBarrack;
        break;
    default:
        cout << "\nWrong choice\n";
    }

    system("cls");
    Unit *unit = barrack->CreateUnit();
    unit->Show();

    return 0;
}

Мені необхідно переробити його згідно завдання:
Відредагувати ієрархію класів Барак: класи повинні викликати конструктор копії
при створенні юнітів та містити об`єкт юніта, як поле класу.

І, власне, сама проблема: я знаю, що таке конструктор копії, але правильно використати його у цій задачі в мене не виходить. Підкажіть де мені прописувати конструктори копії і де мають бути поля типу Unit?
Шось мене стопорить))

Направте, будь ласка.

27

(3 відповідей, залишених у C++)

Добре, але на майбутнє хотілося б дізнатись як.

28

(3 відповідей, залишених у C++)

Все ж, мабуть варто було б використати бази даних у моїй багатостраждальній курсовій, хоча ми цього ще не вчили. Мені підказали глянути в сторону sqlite, але не вдається це використати у Visual Studio. В туторіалі пише:
http://www.tutorialspoint.com/sqlite/sqlite_c_cpp.htm, але у Visual Studio це не працює (хоча із g++ на убунті компілюється нормально.) Ось як це можна зрозуміти? І як подружити із студією?

29

(7 відповідей, залишених у C++)

koala написав:

У вас ця жахлива структура, де в кожного працівника є свій власний департамент...

Це не у мене, а у завданні... Такі вимоги... Я вже з ними голову зламала: четвертий день сиджу і ніяк до толку привести не можу.

koala написав:

Ок, дивіться, що відбувається: ви передаєте в AddWorkerInDepartment(..., Worker worker) копію працівника (з копіями усіх його департаментів і посад, але то вже інша історія). Після чого пхаєте посилання на цю копію в departments[ i ].AddWorker(&worker), який зберігає посилання на цю копію в workers.push_back(worker). А далі AddWorkerInDepartment закінчується, worker випадає з області видимості і припиняє своє існування у яскравому спалаху деструктора. Але посилання на нього тепер зафіксоване в масиві workers, і коли до нього буде звертання - відбудеться... ну, власне, те, що відбувається у вас.

Я думала про деструктор, але ніяк не могла зрозуміти чому...

30

(7 відповідей, залишених у C++)

Ось з цієї функції:

Прихований текст
void AddWorker(Worker *&workers, int &number_workers, Department *&departments, int &number_departments)
{
    if (departments == NULL)
        departments = CreateDepartments(number_departments);
    
    if (workers == NULL)
        workers = CreateNewBaseWorker(number_workers, departments, number_departments);
    else
    {
        Worker *new_workers = new Worker[number_workers + 1];
        for (int i = 0; i < number_workers; ++i)
            new_workers[i] = workers[i];
        delete[]workers;
        workers = new_workers;
        workers[number_workers].InputWorker();
        AddWorkerInDepartment(departments, number_departments, workers[number_workers]);
        ++number_workers;
    }
    
}

31

(7 відповідей, залишених у C++)

Задача: Ведення особових справ робітників у відділі кадрів.

Маю ось такі основні класи:

Прихований текст
class Worker;

class Department
{
    string name;
    vector<Worker*> workers;
    string major_department_name;
    double amount_prize;
    string *positions;
    int number_positions;
public:
    Department() : workers(0)
    {
        name = "no name department";
        major_department_name = "no name";
        amount_prize = 0;
        positions = NULL;
        number_positions = 0;
    }

    Department(const Department &obj)
    {
        name = obj.name;
        major_department_name = obj.major_department_name;
        amount_prize = obj.amount_prize;

        if (!workers.empty())
            workers.clear();
        for (int i = 0; i < obj.workers.size(); ++i)
            workers.push_back(obj.workers[i]);

        number_positions = obj.number_positions;

        positions = obj.positions;
        
    }

    void SetName(string name)
    {
        if (ValidInputNameSurname(name))
            this->name = name;
    }

    string GetName()
    {
        return name;
    }

    void SetMajorDepartmentName(string major_name)
    {
        if (ValidInputNameSurname(name))
            major_department_name = major_name;
    }

    string GetMajorDepartmentName()
    {
        return major_department_name;
    }

    void AddWorker(Worker *worker)
    {
        workers.push_back(worker);
    }

    void DeleteWorkerFromDepartment(Worker *worker)
    {
        if (workers.empty())
            throw new Empty; //cout << "In department no workers\n";

        vector<Worker*>::iterator find_pos = find(workers.begin(), workers.end(), worker);

        if (find_pos != workers.end())
            workers.erase(find_pos);
    }

    int GetNumberWorkers()
    {
        return workers.size();
    }

    int GetNumberPositions()
    {
        return number_positions;
    }

    vector<Worker*>& GetListWorkers()
    {
        return workers;
    }

    void SetAmountPrize(double amount_prize)
    {
        if (ValidInputNumber(amount_prize))
            this->amount_prize = amount_prize;
    }

    double GetAmountPrize()
    {
        return amount_prize;
    }

    void AddPositions(string position_name)
    {
        if (positions == NULL)
        {
            number_positions = 1;

            positions = new string[number_positions];

            positions[number_positions - 1] = position_name;
        }
        else
        {
            string* temp_positions = new string[number_positions + 1];

            int k = 0;
            while (k < number_positions && positions[k] != position_name)
                ++k;
            if (k == number_positions)
            {
                for (int i = 0; i < number_positions; ++i)
                    temp_positions[i] = positions[i];
                temp_positions[number_positions] = position_name;

                delete[]positions;
                positions = temp_positions;
                ++number_positions;
            }
        }
    }

    void DeletePositions(string position_name)
    {
        if (positions == NULL)
            cout << "\nIn the department no any positions\n";
        else
        {
            int i = 0;
            while (i < number_positions && positions[i] != position_name)
                ++i;
            if (i < number_positions)
            {
                string* temp_positions = new string[number_positions - 1];

                for (int j = 0; j < i; ++j)
                    temp_positions[j] = positions[j];
                for (int j = i; j < number_positions - 1; ++j)
                    temp_positions[j] = positions[j + 1];

                delete[]positions;
                positions = temp_positions;
                --number_positions;
            }
        }
    }

    string GetPosition(int index)
    {
        --index;
        if (index < 0 || index >= number_positions)
            throw new WrongIndex;
        return positions[index];
    }

    void Show()
    {
        cout << "\nName: " << name << "\n";
        cout << "\nMajor department name: " << major_department_name << "\n";
        cout << "\nAmount prize: " << amount_prize << "\n";
        cout << "\nPositions:\n";
        for (int i = 0; i < number_positions; ++i)
            cout << "\n" << i + 1 << ")" << positions[i] << "\n";
    }

    void Input()
    {
        cin.ignore(255, '\n');
        string temp;

        cout << "\nDepartment name: ";
        getline(cin, temp);
        if (!ValidInputNameSurname(temp))
            throw new WrongInputNameSurname;
        name = temp;

        cout << "\nMajor department name: ";
        getline(cin, temp);
        if (!ValidInputNameSurname(temp))
            throw new WrongInputNameSurname;
        major_department_name = temp;

        cout << "\nAmount prize: ";
        cin >> temp;
        if (!IsValidDigit(temp))
            throw new IsNoValidDigits;
        double number = atof(temp.c_str());
        amount_prize = number;
    }

    ~Department()
    {

        if (positions != NULL)
        {
            delete[]positions;
            positions = NULL;
            number_positions = 0;
        }
    }
};

const int NUMBER_LAST_PROJECTS = 5;

class Worker : public Person
{
    static int account_number_salary;
    Department department;
    Position position;
    Project projects[NUMBER_LAST_PROJECTS];
    int current_number_projects;
    double experience;
    double total_projects_cost;
public:
    Worker() : position(), projects(), department()
    {
        Project temp_project;
        for (int i = 0; i < NUMBER_LAST_PROJECTS; ++i)
            projects[i] = temp_project;

        current_number_projects = 0;
        experience = 0;
        total_projects_cost = 0;
    }

    void Show()
    {
        cout << account_number_salary << setw(10) << name << setw(11) << surname << setw(9) << birthday << setw(15) << phone_number << setw(10);
        cout << department.GetName() << setw(10) << position.GetName() << setw(8) << experience << setw(8) << position.GetSalary() << "\n";
    }

    void ShowProjects()
    {
        if (current_number_projects != 0)
        {
            for (int i = 0; i < current_number_projects; ++i)
                projects[i].Show();
            cout << "\n";
        }
        else
            cout << "No projects\n";
    }

    static int GetAccountNumberSalary()
    {
        return account_number_salary;
    }

    void SetDepartment(Department department)
    {
        this->department = department;
    }

    Department GetDepartment()
    {
        return department;
    }

    void SetDepartmentName(string name)
    {
        department.SetName(name);
    }

    string GetDepartmentName()
    {
        return department.GetName();
    }

    void SetPosition(Position position)
    {
        this->position = position;
    }

    Position GetPosition()
    {
        return position;
    }

    void SetPositionName(string pos_name)
    {
        position.SetName(pos_name);
    }

    string GetPositionName()
    {
        return position.GetName();
    }

    double GetSalary()
    {
        return position.GetSalary();
    }

    void SetNewProject(Project project)
    {
        if (current_number_projects < NUMBER_LAST_PROJECTS)
        {
            projects[current_number_projects] = project;
            ++current_number_projects;
        }
        else if (current_number_projects == NUMBER_LAST_PROJECTS)
        {
            for (int i = 0; i < current_number_projects - 1; ++i)
                projects[i] = projects[i + 1];
            projects[current_number_projects - 1] = project;
        }
    }

    Project* GetProjects()
    {
        return projects;
    }

    void SetExperience(double experience)
    {
        if (!ValidInputNumber(experience))
            throw new IsNegativeNumber;
        this->experience = experience;
    }

    double GetExperience()
    {
        return experience;
    }

    double CountTotalProjectsCost()
    {
        for (int i = 0; i < current_number_projects; ++i)
            total_projects_cost += projects[i].GetProjectCost();

        return total_projects_cost;
    }

    void InputWorker()
    {
        cin.ignore(255, '\n');

        string temp;

        ++account_number_salary;
        cout << "Account number salary(ANS) assigned automaticaly: " << account_number_salary << "\n";

        cout << "Enter surname: ";
        getline(cin, temp);

        if (!ValidInputNameSurname(temp))
            throw new WrongInputNameSurname;
        surname = temp;

        cout << "Enter name: ";
        getline(cin, temp);

        if (!ValidInputNameSurname(temp))
            throw new WrongInputNameSurname;
        name = temp;

        cout << "Enter birthday (dd.mm.yyyy): ";
        getline(cin, temp);
        birthday = temp;

        cout << "Enter phone number: ";
        getline(cin, temp);
        if (!ValidInputPhoneNumber(temp))
            throw new WrongInputPhoneNumber;
        phone_number = temp;

        cout << "Enter education: ";
        getline(cin, temp);
        if (!ValidInputString(temp))
            throw new Empty;
        education = temp;

        Project temp_project;
        temp_project.Input();
        SetNewProject(temp_project);

        cout << "What experience: ";
        cin >> temp;
        if (!IsValidDigit(temp))
            throw new IsNoValidDigits;

        double temp_experience = atof(temp.c_str());
        experience = temp_experience;
    }

};

І ось основні функції, які задіяні, коли виникає помилка:

Прихований текст
Worker *CreateNewBaseWorker(int &number_workers, Department *&departments, int &number_departments)
{
    cout << "Enter the number of workers: ";
    cin >> number_workers;

    if (number_workers == 0)
        number_workers = 1;

    string dep_name, position_name;
    Worker *temp = new Worker[number_workers];
    for (int i = 0; i < number_workers; ++i)
    {
        temp[i].InputWorker();
        cout << "Department name: ";
        cin >> dep_name;
        cout << "Position name: ";
        cin >> position_name;
        temp[i].SetDepartmentName(dep_name);
        temp[i].SetPositionName(position_name);
        AddWorkerInDepartment(departments, number_departments, temp[i]);
    }

    return temp;
}

void AddWorkerInDepartment(Department *&departments, int &number_departments, Worker worker)
{
    if (departments == NULL)
    {
        AddDepartment(departments, number_departments);
        worker.SetDepartment(departments[number_departments - 1]);
        departments[number_departments - 1].AddWorker(&worker);
    }
    else
    {
        int i = 0;
        while (i < number_departments && departments[i].GetName() != worker.GetDepartmentName())
            ++i;
        if (i < number_departments)
        {
            departments[i].AddWorker(&worker);
            worker.SetDepartment(departments[i]);
        }
        else
        {
            AddDepartment(departments, number_departments);
            worker.SetDepartment(departments[i]);
            departments[i].AddWorker(&worker);
        }

    }
}

І, власне, сама проблема: при створенні масиву працівників заповнення масиву відбуваєть нормально, але програма видає помилку при виході із функції AddWorkerInDepartment, тобто вже коли все встановлено.
Ось саме повідомлення:

Прихований текст

http://i.imgur.com/ebMnrm0.png

В чому може бути проблема?

32

(16 відповідей, залишених у C++)

koala, я Вам дякую за пояснення, але мені не зовсім зрозуміло як бути в моєму випадку...
Тобто, можна зробити щоб у класі Підрозділ був масив об'єктів Працівник, а у класі Працівник достатньо лише назву підрозділу типу string?

33

(16 відповідей, залишених у C++)

Я розумію, як воно виглядає, але є завдання (у файлі), яке мушу дотримати і виконати *PARDON*

34

(16 відповідей, залишених у C++)

Зробила ось так:

class Worker;

class Department
{
    string name;
    Worker *&workers;
    int number_workers;
    string major_department_name;
    double amount_prize;
    string *positions;
    int number_positions;
};
class Worker : public Person
{
    int account_number_salary;
    Department department;
    Position position;
    Project projects[NUMBER_LAST_PROJECTS];
    int current_number_projects;
    double experience;
    double total_projects_cost;
};

Але тоді виникають запитання:
1. Як працювати з масивом працівників, якщо його фактично ще не існує?
2. Як його ініціалізувати у конструкторі по-замовчуванню? Чи цього робити взагалі не потрібно?
У класі Department конструктор має вигляд:

Department()
    {
        name = "no name department";
        workers = NULL;
        number_workers = 0;
        major_department_name = "no name";
        amount_prize = 0;
        positions = NULL;
        number_positions = 0;
    }


І видає помилку: "Department::Department()" provides no initializer for: reference member Department::workers"    .
Поясніть, будь ласка, як тут бути.

35

(16 відповідей, залишених у C++)

P.Y. написав:

А в Department ми не можемо використовувати тип Worker, бо він ще не оголошений.

Можна попередньо оголосити клас, який буде описано згодом:

class Worker; //оголошення без опису

class Department
    {
    //десь тут використовуємо посилання на Worker
    };

class Worker
   {
   //опис класу
   }

Не працює, на жаль.
Зробила ось так:

Прихований текст
class Department;

class Worker: public Person
{
    int account_number_salary;
    Department department;
    Position position;
    Project projects[NUMBER_LAST_PROJECTS];
    int current_number_projects;
    double experience;
    double total_projects_cost;
};

class Department
{
    string name;
    Worker *workers;
    int number_workers;
    string major_department_name;
    double amount_prize;
    string *positions;
    int number_positions;
};

Видає помилку:  'Worker::department' uses undefined class 'Department'.

Чи може я щось не так зробила?

Необхідно записати у файл об'єкти Worker (і, скоріше за все Department): (взаємозв'язок класів у темі - http://replace.org.ua/topic/6347/, як покращити - не знаю, згідно завдання може і ніяк)

class Person
{
protected:
    string surname;
    string name;
    string birthday;
    string city;
    string street;
    int house_number;
    int flat_number;
    string phone_number;
    string education;
};

class Worker: public Person
{
    int account_number_salary;
    Department department;
    Position position;
    Project projects[NUMBER_LAST_PROJECTS];
    int current_number_projects;
    double experience;
    double total_projects_cost;
};

class Department
{
    string name;
    Worker *workers;
    int number_workers;
    string major_department_name;
    double amount_prize;
    string *positions;
    int number_positions;
};

В попередньому варіанті задачі я зробила ось так:

Прихований текст
/* Предметна область - відділ кадрів фірми.
Розв'язувані задачі - облік співробітників. Реалізувати наступні сервіси:

-Заповнення бази даних
-Перегляд даних про всіх співробітників
-Доповнення бази даних новим співробітником
-Видалення із бази даних вказаного співробітника
-Упорядкування: співробітники по відділах, по посадах
-Пошук: всі дані про співробітника з певним ПІБ; як подзвонити співробітникові УУ
-Вибірка: співробітники відділу NN
-Обчислення: кількість співробітників у відділі NN; фонд заробітної плати по відділах
-Корекція: видалення зведень про звільненого співробітника;
переведення співробітника з відділу ХХ у відділ УУ
-Табличний звіт: список співробітників по відділах, підсумок - фонд зарплати кожного відділу
і загальний фонд по фірмі

Додаткові вимоги: ПІБ співробітника не повинні бути порожніми значеннями, а табельний номер співробітника
повинний бути унікальним.
Для обробки даних скористатися динамічним масивом покажчиків на структури відповідного типу.  */

#include <iostream>
#include <iomanip>
#include <fstream>
#include <windows.h>
#include <string>
#include <conio.h>

using namespace std;


struct PersonalInfo
{
    string surname;
    string name;
    string birthday;
    struct Adress
    {
        string city;
        string street;
        int house_number;
        int flat_number;
    } adress;
    string phone_number;
    string education;
};

struct Worker
{
    int ID;
    PersonalInfo personal;
    string department_name;
    string position;
    int salary;
    int experience;
    string work_status;
};

struct Department
{
    string dep_name;
    int funds;
    Worker *workers;
    int number_workers;
};

// Log info for easy debug
void log(string message)
{
    ofstream f("hr_department.log", ios::out | ios::app);
    f << message << "\n";
    f.close();
}


void createDepartments(Department *&departments, int &number_departments)
{
    if (number_departments == 0)
        number_departments = 1;
    departments = new Department[number_departments];
}

void addDepartment(Department *&departments, int &number_departments, string name_departments)
{
    if (departments == NULL)
    {
        createDepartments(departments, number_departments);
        departments[number_departments - 1].dep_name = name_departments;
        for (int i = 0; i < number_departments; ++i)
        {
            departments[i].number_workers = 1;
            for (int j = 0; j < departments[i].number_workers; ++j)
                departments[i].workers = new Worker[departments[i].number_workers];
        }
    }
    else
    {
        Department *new_departments = new Department[number_departments + 1];

        for (int i = 0; i < number_departments; ++i)
            new_departments[i] = departments[i];

        new_departments[number_departments].dep_name = name_departments;

        if (departments != NULL)
            delete[]departments;

        departments = new_departments;
        ++number_departments;
    }
}

void addWorkerInDepartment(Department *&departments, int &number_departments, Worker worker)
{ 
    if (departments == NULL)
    {
        addDepartment(departments, number_departments, worker.department_name);
        departments[number_departments - 1].workers[departments[number_departments - 1].number_workers - 1] = worker;
    }
    else
    {
        int i = 0;
        while (i < number_departments && departments[i].dep_name != worker.department_name)
            ++i;
        if (i < number_departments)
        {
            Worker *temp_workers = new Worker[departments[i].number_workers + 1];
            for (int j = 0; j < departments[i].number_workers; ++j)
                temp_workers[j] = departments[i].workers[j];
            temp_workers[departments[i].number_workers] = worker;
            delete[]departments[i].workers;
            departments[i].workers = temp_workers;
            ++departments[i].number_workers;
        }
        else
        {
            addDepartment(departments, number_departments, worker.department_name);
            departments[i].number_workers = 1;
            departments[i].workers = new Worker[departments[i].number_workers];
            departments[i].workers[departments[i].number_workers - 1] = worker;
        }

    }
}

void deleteWorkerFromTheDepartment(Department *&departments, int &number_departments, Worker worker)
{
    if (departments == NULL)
        cout << "Database is empty\n";
     else
    {
        int i = 0;
        while (i < number_departments && departments[i].dep_name != worker.department_name)
            ++i;
        if (i < number_departments)
        {
            int k = 0;
            while (k < departments[i].number_workers && departments[i].workers[k].ID != worker.ID)
                ++k;
           
            if (k < departments[i].number_workers)
            {
                Worker *temp_workers = new Worker[departments[i].number_workers - 1];
                for (int j = 0; j < k; ++j)
                    temp_workers[j] = departments[i].workers[j];
                for (int j = k; j < departments[i].number_workers - 1; ++j)
                    temp_workers[j] = departments[i].workers[j + 1];
                
                delete[]departments[i].workers;
                departments[i].workers = temp_workers;
                --departments[i].number_workers;
            }
        }
    }
}

bool SetWindow(int Width, int Height)
{
    _COORD coord;
    coord.X = Width;
    coord.Y = Height;

    _SMALL_RECT Rect;
    Rect.Top = 0;
    Rect.Left = 0;
    Rect.Bottom = Height - 1;
    Rect.Right = Width - 1;

    // Get handle of the standard output
    HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);
    if (Handle == NULL)
    {
        cout << "Failure in getting the handle\n" << GetLastError();
        return FALSE;
    }

    // Set screen buffer size to that specified in coord
    if (!SetConsoleScreenBufferSize(Handle, coord))
    {
        cout << "Failure in setting buffer size\n" << GetLastError();
        return FALSE;
    }

    // Set the window size to that specified in Rect
    if (!SetConsoleWindowInfo(Handle, TRUE, &Rect))
    {
        cout << "Failure in setting window size\n" << GetLastError();
        return FALSE;
    }

    return TRUE;
}

struct ITEM{
    int x;
    int y;
    string name_menu;
};

// global variable
enum key { UP = 72, DOWN = 80, ENTER = 13, ESCAPE = 27 };
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbInfo;
SMALL_RECT consolRect;

COORD curspos = { 0, 1 };
WORD workWindowAttributes = 95;
WORD inactiveItemAttributes = 71;
WORD activeItemAttributes = 207;

void gotoxy(int x, int y)
{
    COORD cursorPos = { x, y };
    SetConsoleCursorPosition(hStdOut, cursorPos);
    SetConsoleCursorPosition(hStdOut, { x, y });
}

void getCursorPosition()
{
    GetConsoleScreenBufferInfo(hStdOut, &csbInfo);
    curspos = csbInfo.dwCursorPosition;
}

void showCursor(bool visible)
{
    CONSOLE_CURSOR_INFO ccInfo;
    ccInfo.bVisible = visible;
    ccInfo.dwSize = 20;
    SetConsoleCursorInfo(hStdOut, &ccInfo);
}

//TODO: color text, move to keys in the menu

void writeToFile(string file_name, Worker *workers, int number_workers)
{
    ofstream f_out(file_name, ios_base::out | ios_base::binary);
    if (!f_out)
        cout << "Can not open file to write\n";

    f_out.write((char *)&number_workers, sizeof(number_workers));
    for (int i = 0; i < number_workers; ++i)
    {
        int ser = workers[i].salary;
        f_out.write((char *)&ser, sizeof(ser));

        ser = workers[i].personal.adress.house_number;
        f_out.write((char *)&ser, sizeof(ser));

        ser = workers[i].personal.adress.flat_number;
        f_out.write((char *)&ser, sizeof(ser));

        ser = workers[i].experience;
        f_out.write((char *)&ser, sizeof(ser));

        ser = workers[i].personal.surname.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].personal.surname.c_str(), ser);

        ser = workers[i].personal.name.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].personal.name.c_str(), ser);

        ser = workers[i].personal.birthday.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].personal.birthday.c_str(), ser);

        ser = workers[i].personal.phone_number.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].personal.phone_number.c_str(), ser);

        ser = workers[i].personal.education.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].personal.education.c_str(), ser);

        ser = workers[i].personal.adress.city.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].personal.adress.city.c_str(), ser);

        ser = workers[i].personal.adress.street.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].personal.adress.street.c_str(), ser);

        ser = workers[i].ID;
        f_out.write((char *)&ser, sizeof(ser));

        ser = workers[i].department_name.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].department_name.c_str(), ser);

        ser = workers[i].position.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].position.c_str(), ser);

        ser = workers[i].work_status.length();
        f_out.write((char *)&ser, sizeof(ser));
        f_out.write(workers[i].work_status.c_str(), ser);

    }
    cout << "Data is written in the file successfully\n";
    f_out.close();
}

void loadFromFile(string file_name, Worker *&workers, int &number_workers, Department *&departments, int &number_departments)
{
    ifstream f_in(file_name, ios_base::binary);

    if (!f_in)
        cout << "Can not open file to read\n";
    else
    { 
        f_in.read((char *)&number_workers, sizeof(number_workers));
        Worker *new_workers = new Worker[number_workers];
        char *temp_str;
        int ser;
        for (int i = 0; i < number_workers; ++i)
        {
            f_in.read((char *)&ser, sizeof(ser));
            new_workers[i].salary = ser;

            f_in.read((char *)&ser, sizeof(ser));
            new_workers[i].personal.adress.house_number = ser;

            f_in.read((char *)&ser, sizeof(ser));
            new_workers[i].personal.adress.flat_number = ser;
            
            f_in.read((char *)&ser, sizeof(ser));
            new_workers[i].experience = ser;          

            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].personal.surname.assign(temp_str);
            delete[]temp_str;

            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].personal.name.assign(temp_str);
            delete[]temp_str;

            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].personal.birthday.assign(temp_str);
            delete[]temp_str;

            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].personal.phone_number.assign(temp_str);
            delete[]temp_str;
            
            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].personal.education.assign(temp_str);
            delete[]temp_str;
            
            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].personal.adress.city.assign(temp_str);
            delete[]temp_str;
            
            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].personal.adress.street.assign(temp_str);
            delete[]temp_str;
            
            f_in.read((char *)&ser, sizeof(ser));
            new_workers[i].ID = ser;
                      
            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].department_name.assign(temp_str);
            delete[]temp_str;
            
            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].position.assign(temp_str);
            delete[]temp_str;
            
            f_in.read((char *)&ser, sizeof(ser));
            temp_str = new char[ser + 1];
            memset(temp_str, 0, ser + 1);
            f_in.read(temp_str, ser);
            new_workers[i].work_status.assign(temp_str);
            delete[]temp_str;

            addWorkerInDepartment(departments, number_departments, new_workers[i]);
        }
            workers = new_workers;
            cout << "Data loaded successfully\n";
    }
    
    f_in.close();
}

bool validInputPhoneNumber(const string phone)
{
    int i = 0;
    int phone_length = phone.length();
    while (i < phone_length)
    {
        if (!(isdigit(phone[i]) || phone[i] == '-'))
            return false;
        ++i;
    }
    return true;
}

bool validInputNameSurname(const string name)
{
    if (name == " ")
        return false;
    int i = 0;
    int name_length = name.length();
    while (i < name_length)
    {
        if (!(isalpha(name[i])))
            return false;
        ++i;
    }
    return true;

}

bool validInputString(const string str)
{
    if (str == " ")
        return false;
    return true;
}

bool validInputNumber(const int records)
{
    if (records >= 1)
        return true;
    else
        return false;
}

void getDayMonthYear(string str, int &day, int &month, int &year)
{
    int pos_day = str.find('.');

    if (pos_day != string::npos)
        for (int i = 0; i < pos_day; ++i)
            day = stoi(str);

    int pos_month = str.find('.', pos_day + 1);
    if (pos_month != string::npos)
        for (int i = pos_day + 1; i < pos_month; ++i)
            month = stoi(str);

    int length = str.length();
    for (int i = pos_month + 1; i <length; ++i)
        year = stoi(str);
}

bool isLeapYear(unsigned int year)
{
    return !(year % 400) || (!(year % 4) && (year % 100));
}

bool validBirthday(string str)
{
    if (str == "")
        return false;

    int i = 0;
    int length = str.length();
    while (i < length)
    {
        if (!(isdigit(str[i]) || '.'))
            return false;
        ++i;
    }
    
    int day, month, year;
    getDayMonthYear(str, day, month, year);
    
    if (year < 1 || month < 1 || day < 1)
        return false;

    if (month == 2)
    {
        if (isLeapYear(year))
        {
            if (day <= 29)
                return true;
        }
        else if (day <= 28)
            return true;
    }

    switch (month)
    {
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:
        if (day <= 31)
            return true;
        break;
    case 4: case 6: case 9: case 11:
        if (day <= 30)
            return true;
        break;
    }

    return false;
}

//TODO: VALID BIRTHDAY

void inputWorkerRecord(Worker &worker, int index)
{
    cin.ignore(255, '\n');

    do{
        cout << "Enter surname: ";
        getline(cin, worker.personal.surname);
    } while (!validInputNameSurname(worker.personal.surname));

    do{
        cout << "Enter name: ";
        getline(cin, worker.personal.name);
    } while (!validInputNameSurname(worker.personal.name));

    
    do{
        cout << "Enter birthday (dd.mm.yyyy): ";
        getline(cin, worker.personal.birthday);
    } while (!validBirthday(worker.personal.birthday));

    do{
        cout << "Enter city: ";
        getline(cin, worker.personal.adress.city);
    } while (!validInputString(worker.personal.adress.city));

    do{
        cout << "Enter street: ";
        getline(cin, worker.personal.adress.street);
    } while (!validInputString(worker.personal.adress.street));

    do{
        cout << "Enter the house number: ";
        cin >> worker.personal.adress.house_number;
    } while (!worker.personal.adress.house_number);

    do{
        cout << "Enter the flat number: ";
        cin >> worker.personal.adress.flat_number;
    } while (!worker.personal.adress.flat_number);

    cin.ignore(255, '\n');

    do{
        cout << "Enter phone number: ";
        getline(cin, worker.personal.phone_number);
    } while (!validInputPhoneNumber(worker.personal.phone_number));

    do{
        cout << "Enter education: ";
        getline(cin, worker.personal.education);
    } while (!validInputString(worker.personal.education));

    do{
        cout << "In which department works: ";
        getline(cin, worker.department_name);
    } while (!validInputString(worker.department_name));

    do{
        cout << "In which position: ";
        getline(cin, worker.position);
    } while (!validInputString(worker.position));

    do{
        cout << "What salary: ";
        cin >> worker.salary;
    } while (!validInputNumber(worker.salary));

    do{
        cout << "What experience: ";
        cin >> worker.experience;
    } while (!validInputNumber(worker.experience));

    cin.ignore(255, '\n');

    do{
        cout << "What is the status of work ( fired or work): ";
        getline(cin, worker.work_status);
    } while (!validInputString(worker.work_status));

    worker.ID = index +1;
}

Worker *createNewBaseWorker(int &number_workers, Department *&departments, int &number_departments)
{
    cout << "Enter the number of workers: ";
    cin >> number_workers;

    if (number_workers == 0)
        number_workers = 1;

    Worker *temp = new Worker[number_workers];
    for (int i = 0; i < number_workers; ++i)
    {
        inputWorkerRecord(temp[i], i);
        addWorkerInDepartment(departments, number_departments, temp[i]);
    }

    return temp;
}

int maxID(const Worker *workers, int &number_workers)
{
    int max = workers[0].ID;
    for (int i = 1; i < number_workers; ++i)
        if (workers[i].ID > max)
            max = workers[i].ID;

    return max;
}

void addRecord(Worker *&workers, int &number_workers, Department *&departments, int &number_departments)
{
    if (workers == NULL)
        workers = createNewBaseWorker(number_workers, departments, number_departments);
    else
    {
        Worker *new_workers = new Worker[number_workers + 1];
        for (int i = 0; i < number_workers; ++i)
            new_workers[i] = workers[i];
        delete[]workers;
        workers = new_workers;
        inputWorkerRecord(workers[number_workers], maxID(workers, number_workers));
        addWorkerInDepartment(departments, number_departments, workers[number_workers]);
        ++number_workers;
    }
}

void headPrintRecord()
{
    cout << "ID" << setw(8) << "Name " << setw(10) << "Surname " << setw(11) << "Birthday"<< setw(15) << "Phone number" << setw(8);
    cout << "City" << setw(12) << "Street" << setw(9) << "House" << setw(8) << "Flat" << setw(8);
    cout << "Depart." << setw(10) << "Position" << setw(8) << "Exper." << setw(8) << "Salary" << setw(15) << "Work status\n";
    cout << "----------------------------------------------------------------------------------------------------------------------------------\n";
}

void printRecord(const Worker worker)
{
    cout << worker.ID << setw(10) << worker.personal.name << setw(11) << worker.personal.surname << setw(9) << worker.personal.birthday << setw(15) << worker.personal.phone_number << setw(10);
    cout << worker.personal.adress.city << setw(12) << worker.personal.adress.street << setw(8) << worker.personal.adress.house_number << setw(6) << worker.personal.adress.flat_number << setw(10);
    cout << worker.department_name << setw(10) << worker.position << setw(8) << worker.experience << setw(8) << worker.salary << setw(10) << worker.work_status << "\n";
}

void showAllWorkers(const Worker *workers, int number_workers)
{
    if (workers == NULL)
        cout << "Database is empty\n";
    else
    {
        headPrintRecord();
        for (int i = 0; i < number_workers; ++i)
        {
            cout << workers[i].ID << setw(10) << workers[i].personal.name << setw(11) << workers[i].personal.surname  << setw(9)<< workers[i].personal.birthday << setw(15) << workers[i].personal.phone_number << setw(10);
            cout << workers[i].personal.adress.city << setw(12) << workers[i].personal.adress.street << setw(8) << workers[i].personal.adress.house_number << setw(6) << workers[i].personal.adress.flat_number << setw(10);
            cout << workers[i].department_name << setw(10) << workers[i].position << setw(8) << workers[i].experience << setw(8) << workers[i].salary << setw(10) << workers[i].work_status << "\n";
        }
    }
}

void quit(bool &exit, Worker *workers, int number_workers)
{
    char save_choice;
    cout << "Save changes? (Y/N): ";
    cin >> save_choice;
    if (tolower(save_choice) == 'y')
    {
        string file_name;
        cout << "Enter file name to save: ";
        cin >> file_name;
        writeToFile(file_name, workers, number_workers);
    }

    char exit_choice;
    cout << "Are you sure you want to exit? (Y/N): ";
    cin >> exit_choice;
    if (tolower(exit_choice) == 'y')
    {
        cout << "Bye!\n";
        exit = true;
    }
}

void deleteRecord(Worker *&workers, int &number_workers, int pos_record, Department *&departments, int number_departments)
{
    if (workers == NULL)
        cout << "Database is empty\n";
    else
    {
        --pos_record;
        if (pos_record < 0 || pos_record >= number_workers)
            cout << "Database doesn't have any record with this number\n";
        else
        {
            Worker *new_workers = new Worker[number_workers - 1];
            for (int i = 0; i < pos_record; ++i)
                new_workers[i] = workers[i];
            for (int i = pos_record; i < number_workers - 1; ++i)
                new_workers[i] = workers[i + 1];
            deleteWorkerFromTheDepartment(departments, number_departments, workers[pos_record]);
            delete[]workers;
            workers = new_workers;
            --number_workers;
            cout << "\n\tWORKER DELETED SUCCESSFULLY\n";
        }
    }
}

void printOnlyPhoneNumber(const Worker worker)
{
    cout << "\tID" << setw(10) << "Name" << setw(15) << setw(15) << "Surname" << setw(15) << "Phone number\n";
    cout << "--------------------------------------------------------------------------------------------\n";
    cout << "\t" << worker.ID << setw(10) << worker.personal.name << setw(15) << worker.personal.surname << setw(15) << worker.personal.phone_number << "\n";
}

void searchRecordBySurname(const Worker *workers, int number_workers, string search_key, char mod = 'a')
{
    if (workers == NULL)
        cout << "Database is empty\n";
    bool search = false;
    for (int i = 0; i < number_workers; ++i)
    {
        if (workers[i].personal.surname == search_key)
        {
            if (mod == 'a')
                printRecord(workers[i]);
            else
                printOnlyPhoneNumber(workers[i]);
            search = true;
        }
    }
    if (!search)
        cout << "Not found " << search_key << "!\n";
}

void sortRecordByDepartmnets(Department *departments, int number_departments)
{
    if (departments != NULL)
    {
        int pos_min;
        string min;
        Department temp_department;

        for (int i = 0; i < number_departments - 1; i++)
        {
            pos_min = i;
            min = departments[i].dep_name;
            for (int j = 1 + i; j < number_departments; j++)
            {
                if (departments[j].dep_name < min)
                {
                    min = departments[j].dep_name;
                    pos_min = j;
                }
            }
            temp_department = departments[pos_min];
            departments[pos_min] = departments[i];
            departments[i] = temp_department;
        }

        for (int i = 0; i < number_departments; ++i)
        {
            if (departments[i].number_workers != 0)
            {
                headPrintRecord();
                for (int j = 0; j < departments[i].number_workers; ++j)
                    printRecord(departments[i].workers[j]);
                cout << "\n";
            }
        }
    }
    else
        cout << "Database is empty\n";
}

void sortRecordByPosition(Worker *workers, int number_workers)
{
    if (workers != NULL)
    {
        int pos_min;
        string min;
        Worker temp_worker;

        for (int i = 0; i < number_workers - 1; i++)
        {
            pos_min = i;
            min = workers[i].position;
            for (int j = 1 + i; j < number_workers; j++)
            {
                if (workers[j].position < min)
                {
                    min = workers[j].position;
                    pos_min = j;
                }
            }
            temp_worker = workers[pos_min];
            workers[pos_min] = workers[i];
            workers[i] = temp_worker;
        }

        showAllWorkers(workers, number_workers);
    }
    else
        cout << "Database is empty\n";
}


void selectByDepartments(string select_name_department, Department *departments, int number_departments)
{
    if (departments != NULL)
    {
        int i = 0;
        while (i < number_departments && departments[i].dep_name != select_name_department)
            ++i;

        if (i < number_departments)
            showAllWorkers(departments[i].workers, departments[i].number_workers);
        else
            cout << "This department does not exist\n";
    }
}

void calculateNumberWorkers(const Department *departments, int number_departments)
{
    if (departments == NULL)
        cout << "Database is empty\n";
    else
    {
        cout << "\nDepartment name " << setw(20) << "Number of workers\n";
        cout << "-------------------------------------------------\n";
        for (int i = 0; i < number_departments; ++i)
            cout << departments[i].dep_name << setw(20) << departments[i].number_workers << "\n";
    }
}

void calculateTotalFundsbyDepartment(Department *&departments, int number_departments)
{
    if (departments == NULL)
        cout << "Database is empty\n";
    else
    {
        for (int i = 0; i < number_departments; ++i)
        {
            departments[i].funds = 0;
            for (int j = 0; j < departments[i].number_workers; ++j)
                departments[i].funds += departments[i].workers[j].salary;
        }

        cout << "\nDepartment name " << setw(25) << "Total funds by department\n";
        cout << "-------------------------------------------------\n";
        for (int i = 0; i < number_departments; ++i)
            cout << departments[i].dep_name << setw(30) << departments[i].funds << "\n";
    }
}

void deleteInfoByFiredWorker(Worker *&workers, int &number_workers, Department *&departments, int number_departments)
{
    if (workers == NULL)
        cout << "Database is empty\n";
    else
    {
        char user_delete_answer;
        cout << "Do you want delete all fired workers? (Y/N): ";
        cin >> user_delete_answer;
        if (tolower(user_delete_answer) == 'y')
        {
            for (int i = 0; i < number_workers; ++i)
                if (workers[i].work_status == "fired")
                    deleteRecord(workers, number_workers, i + 1, departments, number_departments);
        }
        else
        {
            int delete_worker_ID;
            cout << "Enter ID worker that you want to delete: ";
            cin >> delete_worker_ID;
            int i = 0;
            while (i < number_workers && workers[i].ID != delete_worker_ID)
                ++i;
            if (i < number_workers)
            {
                if (workers[i].work_status == "fired")
                    deleteRecord(workers, number_workers, i + 1, departments, number_departments);
                else
                {
                    cout << "A worker with this ID not fired\n";
                    cout << "Are you sure that you want to remove information about him?(Y/N): ";
                    cin >> user_delete_answer;
                    if (tolower(user_delete_answer) == 'y')
                        deleteRecord(workers, number_workers, i + 1, departments, number_departments);
                }
            }
            else
                cout << "A worker with this ID does not exist!\n";
        }
    }
}

void staffMove(Worker &worker, Department *&departments, int &number_departments)
{
    if (departments == NULL)
        cout << "Database is empty\n";
    else
    {
        string name_department;
        cout << "Enter the name of the department which should to transfer a worker: ";
        cin >> name_department;
        deleteWorkerFromTheDepartment(departments, number_departments, worker);
        worker.department_name = name_department;
        addWorkerInDepartment(departments, number_departments, worker);
        cout << "WORKER MOVED SUCCESSFULLY\n";
    }
}

void listWorkerByDepartment(Department *departments, int number_department)
{
    if (departments == NULL)
        cout << "Database is empty\n";
    else
    {
        for (int i = 0; i < number_department; ++i)
        {
            cout << "\n\t----------------" << departments[i].dep_name << "------------------\n\n";
            headPrintRecord();
            for (int j = 0; j < departments[i].number_workers; ++j)
                printRecord(departments[i].workers[j]);
            cout << "\n";
        }
    }
}

void totalFunds(Department *departments, int number_department)
{
    if (departments == NULL)
        cout << "Database is empty\n";
    else
    {
        calculateTotalFundsbyDepartment(departments, number_department);
        int total_funds = 0;
        for (int i = 0; i < number_department; ++i)
            total_funds += departments[i].funds;
 
        cout << "--------------------------------------------------------\n";
        cout << "\n\tTOTAL FUNDS: " << total_funds << "\n";
    }

}
enum menuitems {CREATE_DATABASE, LOAD_FROM_FILE, SHOW_ALL, ADD_WORKER,
            DELETE_WORKER, SEARCH_BY_SURNAME, SORT_BY_DEPARTMENT, SORT_BY_POSITION,
            SELECT_BY_DEPARTMENT,CALCULATE_NUMBER_OF_WORKERS, CALCULATE_TOTAL_FUNDS_DEPARTMENT, DELETE_INFO_BY_FIRED_WORKER,
            STAFF_MOVE, LIST_WORKER_BY_DEPARTMENT, TOTAL_FUNDS, EXIT};

const int NUMBER_MENU = 17;

ITEM menu[NUMBER_MENU] = {
                            {30, 13, "CREATE DATABASE" },
                            {30, 15, "LOAD DATABASE FROM FILE" },
                            {30, 17, "SHOW ALL WORKERS" },
                            {30, 19, "ADD WORKER" },
                            {30, 21, "DELETE WORKER"},
                            {30, 23, "SEARCH WORKER BY SURNAME"},
                            {30, 25, "SORT BY DEPARTMENTS"},
                            {30, 27, "SORT BY POSITION" },
                            {30, 29, "SELECT BY DEPARTMENT" },
                            {30, 31, "CALCULATE: NUMBER OF WORKERS IN DEPARTEMENT"},
                            {30, 33, "CALCULATE: TOTAL FUNDS BY DEPARTMENT"},
                            {30, 35, "EDIT: DELETE INFO BY FIRED WORKER"},
                            {30, 37, "EDIT: STAFF MOVE"},
                            {30, 39, "REPORT: LIST WORKERS BY DEPARTMENT"},
                            {30, 41, "REPORT: TOTAL FUNDS"},
                            {30, 43, "EXIT" } };


void itemMenu(int sel, bool activate)
{
    WORD itemAttributes;
    if (activate)
        itemAttributes = activeItemAttributes;
    else
        itemAttributes = inactiveItemAttributes;
    gotoxy(menu[sel].x, menu[sel].y);
    SetConsoleTextAttribute(hStdOut, itemAttributes);
    cout << menu[sel].name_menu;
}

bool menuAction(int sel, Worker *&workers, int &number_workers, Department *&departments, int &number_departments)
{
    showCursor(true);
    int user_choice;
    bool exit = false;
    string load_file_name;
    string search_surname;
    string select_departments_name; 

        switch (sel)
        {
        case CREATE_DATABASE:
            system("cls");
            if (workers == NULL)
                cout << "\tYou create a new database!\n";
            else
            {
                char user_answer_choice;
                cout << "When you create a new database possible loss of data. Save an existing base? (Y/N): \n";
                cin >> user_answer_choice;
                if (tolower(user_answer_choice) == 'y')
                {
                    string save_file_name;
                    cout << "Enter file name to save: ";
                    cin >> save_file_name;
                    writeToFile(save_file_name, workers, number_workers);
                }
            }
            workers = createNewBaseWorker(number_workers, departments, number_departments);
            cout << "Database created successfully\n";
            break;
        case SHOW_ALL:
            system("cls");
            cout << "\n\nNUMBER WORKERS: " << number_workers << "\n\n";
            showAllWorkers(workers, number_workers);
            break;
        case ADD_WORKER:
            system("cls");
            addRecord(workers, number_workers, departments, number_departments);
            cout << "\n\tWORKER ADDED SUCCESSFULLY\n";
            break;
        case DELETE_WORKER:
            system("cls");
            int pos_delete_worker;
            if (workers != NULL)
            {
                cout << "Enter the number of worker to delete of base: ";
                cin >> pos_delete_worker;
            }
            deleteRecord(workers, number_workers, pos_delete_worker, departments, number_departments);
            break;
        case SEARCH_BY_SURNAME:
            system("cls");
            cout << "Enter a surname of worker to find of base: ";
            cin >> search_surname;
            char user_search_answer;
            cout << "Print all info of worker (a) or only phone number (p)?: ";
            cin >> user_search_answer;
            searchRecordBySurname(workers, number_workers, search_surname, user_search_answer);
            break;
        case SORT_BY_DEPARTMENT:
            system("cls");
            sortRecordByDepartmnets(departments, number_departments);
            break;
        case SORT_BY_POSITION:
            system("cls");
            sortRecordByPosition(workers, number_workers);
            break;
        case SELECT_BY_DEPARTMENT:
            system("cls");
            cout << "Enter a departments name to select: ";
            cin >> select_departments_name;
            selectByDepartments(select_departments_name, departments, number_departments);
            break;
        case LOAD_FROM_FILE:
            system("cls");
            if (workers != NULL)
            {
                char user_choice;
                cout << "You will lose your data! Continue?(Y/N)";
                cin >> user_choice;
                if (tolower(user_choice) == 'y')
                {
                    char user_answer_choice;
                    cout << "Save an existing base ? (Y / N): ";
                    cin >> user_answer_choice;
                    if (tolower(user_answer_choice) == 'y')
                    {
                        string save_file_name;
                        cout << "Enter file name to save: ";
                        cin >> save_file_name;
                        writeToFile(save_file_name, workers, number_workers);
                    }
                    delete[]workers;
                    workers = NULL;
                    if (departments != NULL)
                    {
                        delete[]departments;
                        departments = NULL;
                    }
                }
            }
            else
                cout << " You will create a new database from the file\n";

            cout << "Enter file name to load: ";
            cin >> load_file_name;
            loadFromFile(load_file_name, workers, number_workers, departments, number_departments);
            break;
        case CALCULATE_NUMBER_OF_WORKERS:
            system("cls");
            calculateNumberWorkers(departments, number_departments);
            break;
        case CALCULATE_TOTAL_FUNDS_DEPARTMENT:
            system("cls");
            calculateTotalFundsbyDepartment(departments, number_departments);
            break;
        case  DELETE_INFO_BY_FIRED_WORKER:
            system("cls");
            deleteInfoByFiredWorker(workers, number_workers, departments, number_departments);
            break;
        case STAFF_MOVE:
            system("cls");
            int move_worker_number;
            cout << "Enter the number of worker to move him in the another department: ";
            cin >> move_worker_number;
            staffMove(workers[move_worker_number - 1], departments, number_departments);
            break;
        case LIST_WORKER_BY_DEPARTMENT:
            system("cls");
            listWorkerByDepartment(departments, number_departments);
            break;
        case TOTAL_FUNDS:
            system("cls");
            totalFunds(departments, number_departments);
            break;
        case EXIT:
            system("cls");
            quit(exit, workers, number_workers);
            break;
        }
        return exit;
}

void DrawMenu(Worker *workers, int number_workers, Department *departments, int number_departments)
{
    menuitems sel = CREATE_DATABASE; // Number of the current menu item
    SetConsoleTextAttribute(hStdOut, inactiveItemAttributes);
    system("cls");
    for (int i = 0; i < NUMBER_MENU; i++)
    {
        gotoxy(menu[i].x, menu[i].y);
        cout << menu[i].name_menu;
    }
    itemMenu(sel, true);
    showCursor(false);
    fflush(stdin);
    int iKey;
    bool exit = false;
    while (!exit)
    {
        if (_kbhit())
        {
            iKey = _getch();
            switch (iKey)
            {
            case DOWN:
                if (sel < NUMBER_MENU - 1) {
                    itemMenu(sel, false);
                    sel = (menuitems)(sel + 1);
                    itemMenu(sel, true);
                }
                else {
                    itemMenu(sel, false);
                    sel = CREATE_DATABASE;
                    itemMenu(sel, true);
                }
                showCursor(false);
                break;
            case UP:
                if (sel >0) {
                    itemMenu(sel, false);
                    sel = (menuitems)(sel - 1);
                    itemMenu(sel, true);
                }
                else {
                    itemMenu(sel, false);
                    sel = EXIT;
                    itemMenu(sel, true);
                }
                showCursor(false);
                break;
            case ENTER:
                gotoxy(curspos.X, curspos.Y);// Moves the cursor from the menu bar at the same position
                SetConsoleTextAttribute(hStdOut, workWindowAttributes);
                exit = menuAction(sel, workers, number_workers, departments, number_departments);
                _getch();
                if (!exit) DrawMenu(workers, number_workers, departments, number_departments);
                break;
            case ESCAPE:
                system("cls");
                quit(exit, workers, number_workers);
                getCursorPosition(); //program completion
            } // switch
        } // if (kbhit)
    } // while (!exit)
}

int main()
{
    int number_workers = 0, number_departments = 0;
    Worker *staff = NULL;
    Department *departments = NULL;

    SetConsoleTitle(L"MENU");
    GetConsoleScreenBufferInfo(hStdOut, &csbInfo);
    consolRect = csbInfo.srWindow; // coordinates of the corners console
    SetConsoleTextAttribute(hStdOut, workWindowAttributes);

    system("cls"); //set attributes of color workspace

    if (SetWindow(135, 50))
         DrawMenu(staff, number_workers, departments, number_departments);

    for (int i = 0; i < number_departments; ++i)
        delete[]departments[i].workers;
    delete[]departments;

    delete[]staff;

    return 0;
}

Здавалося, й тут нічого страшного, але... Ось дійшла до такого:

Прихований текст
void WriteToFile(ofstream &out)
    {
        out.write(reinterpret_cast<char*>(&account_number_salary), sizeof(account_number_salary));
        out.write(reinterpret_cast<char*>(surname.c_str), surname.length());
        out.write(reinterpret_cast<char*>(name.c_str), name.length());
        out.write(reinterpret_cast<char*>(birthday.c_str), birthday.length());
        out.write(reinterpret_cast<char*>(city.c_str), city.length());
        out.write(reinterpret_cast<char*>(street.c_str), street.length());
        out.write(reinterpret_cast<char*>(&house_number), sizeof(house_number));
        out.write(reinterpret_cast<char*>(&flat_number), sizeof(flat_number));
        out.write(reinterpret_cast<char*>(phone_number.c_str), phone_number.length());
        out.write(reinterpret_cast<char*>(education.c_str), education.length());
        out.write(reinterpret_cast<char*>(&experience), sizeof(experience));
        out.write(reinterpret_cast<char*>(&total_projects_cost), sizeof(total_projects_cost));
        out.write(reinterpret_cast<char*>(position.GetName().c_str), position.GetName().length());
        out.write(reinterpret_cast<char*>(position.GetWorkingHours()), sizeof(position.GetWorkingHours()));
        out.write(reinterpret_cast<char*>(position.GetSalary()),sizeof(position.GetSalary()));
        out.write(reinterpret_cast<char*>(position.GetNumberWorkDuties()), sizeof(position.GetNumberWorkDuties()));

        for (int i = 0; i < position.GetNumberWorkDuties(); ++i)
            out.write(reinterpret_cast<char*>(position.GetWorkDutieByPosition(i + 1).c_str), position.GetWorkDutieByPosition(i + 1).length());

        out.write(reinterpret_cast<char*>(&current_number_projects), sizeof(current_number_projects));

        for (int i = 0; i < current_number_projects; ++i)
        {
            out.write(reinterpret_cast<char*>(projects[i].GetName().c_str), projects[i].GetName().length());
            out.write(reinterpret_cast<char*>(projects[i].GetDuration()), sizeof(projects[i].GetDuration()));
            out.write(reinterpret_cast<char*>(projects[i].GetWorkingHours()), sizeof(projects[i].GetWorkingHours()));
            out.write(reinterpret_cast<char*>(projects[i].GetProjectCost()), sizeof(projects[i].GetProjectCost()));
            out.write(reinterpret_cast<char*>(projects[i].GetNameCustomer().c_str), projects[i].GetNameCustomer().length());
        }

        out.write(reinterpret_cast<char*>(department.GetName().c_str),department.GetName().length());
        out.write(reinterpret_cast<char*>(department.GetMajorDepartmentName().c_str), department.GetMajorDepartmentName().length());
        out.write(reinterpret_cast<char*>(department.GetAmountPrize()), sizeof(department.GetAmountPrize()));
        //out.write(reinterpret_cast<char*>(department.GetNumberWorkers()), sizeof(department.GetNumberWorkers()));

        //for (int i = 0; i < department.GetNumberWorkers(); ++i)
        //    out.write(reinterpret_cast<char*>);
        out.write(reinterpret_cast<char*>(department.GetNumberPositions()), sizeof(department.GetNumberPositions()));
        for (int i = 0; i < department.GetNumberPositions(); ++i)
            out.write(reinterpret_cast<char*>(department.GetPosition(i + 1).c_str), department.GetPosition(i + 1).length());
    }

Проблеми, які виникли і не знаю з якого боку тепер підступитися:
1. Не можу серіалізувати поля типу double. Як з ними правильно поступити?
2. При записі у файл підрозділу, в кому є Worker, потрібно записати масив об'єктів Worker, які працюють у цьому підрозділі. А це виходить замкнене коло. Як????

37

(2 відповідей, залишених у C++)

Дивно, але, на жаль, про make_shared нам нічого не розповідали.

38

(2 відповідей, залишених у C++)

Задача: Створити клас SoftwareEngineer, що містить поля:
●    string name;
●    string position (Junior Developer, Developer, Senior Developer);
●    int salary;
●    string currentProject;
Описати інтерфейс класу по необхідності (Конструктори, аксесори та мутатори для полів, метод виводу інформації).
Свторити глобальні функції:
●     ShowData() - виводить інформацію про конкретного програміста;
●    ChangeData() - запитує у користувача дані та заповнює ними поля класу, використовуючи відповідні сеттери.
Функції повинні приймати та повертати shared_ptr<>.

Я реалізувала її так:

Прихований текст
#include <iostream>
#include <string>
#include <memory>

using namespace std;

class SoftwareEngineer
{
    string name;
    string position;
    int salary;
    string current_project;

    bool ValidInputString(string str)
    {
        if (str == "" || str == " ")
            return false;

        for (int i = 0; i < str.length(); ++i)
            if (!isalpha(str[i]))
                return false;

        return true;
    }

    bool IsValidDigit(int number)
    {
        if (number < 0)
            return false;

        string str = to_string(number);

        for (int i = 0; i < str.length(); ++i)
            if (!isdigit(str[i]))
                return false;

        return true;
    }
public:
    SoftwareEngineer()
    {
        name = "no name";
        position = "no position";
        salary = 0;
        current_project = "no project";
    }

    SoftwareEngineer(string name, string position, int salary, string current_project)
    {
        this->name = name;
        this->position = position;
        this->salary = salary;
        this->current_project = current_project;
    }

    void SetName(string name)
    {
        if (ValidInputString(name))
            this->name = name;
    }

    string GetName()
    {
        return name;
    }

    void SetPosition(string position)
    {
        if (ValidInputString(position))
            this->position = position;
    }

    string GetPosition()
    {
        return position;
    }

    void SetSalary(int salary)
    {
        if (IsValidDigit(salary))
            this->salary = salary;
    }

    int GetSalary()
    {
        return salary;
    }

    void SetCurrentProject(string current_project)
    {
        if (ValidInputString(current_project))
            this->current_project = current_project;
    }

    string GetCurrentProject()
    {
        return current_project;
    }

    void Show()
    {
        cout << "Name: " << name << "\n";
        cout << "Position: " << position << "\n";
        cout << "Salary: " << salary << "\n";
        cout << "Current project: " << current_project << "\n";
    }
};

void Input(shared_ptr<SoftwareEngineer> &software_engineer)
{
    string temp;
    cout << "\nName: ";
    getline(cin, temp);
    software_engineer->SetName(temp);

    cout << "\nPosition: ";
    getline(cin, temp);
    software_engineer->SetPosition(temp);

    int salary = 0;
    cout << "\nSalary: ";
    cin >> salary;
    software_engineer->SetSalary(salary);

    cin.ignore(256, '\n');
    cout << "\nCurrent project: ";
    getline(cin, temp);
    software_engineer->SetCurrentProject(temp);

}


shared_ptr<SoftwareEngineer> ShowData(shared_ptr<SoftwareEngineer> *software_engineers, int index_engineer, int number_engineers)
{
    --index_engineer;
    if (index_engineer < 0 || index_engineer >= number_engineers)
        cout << "\nSoftware engineer with such index doesn't exist\n";
    
    software_engineers[index_engineer]->Show();

    return software_engineers[index_engineer];
}

shared_ptr<SoftwareEngineer> ChangeData(shared_ptr<SoftwareEngineer> *software_engineers, int index_engineer, int number_engineers)
{
    --index_engineer;
    if (index_engineer < 0 || index_engineer >= number_engineers)
        cout << "\nSoftware engineer with such index doesn't exist\n";

    Input(software_engineers[index_engineer]);

    return software_engineers[index_engineer];
}

int main()
{
    const int NUMBER_ENGINEERS = 5;
    shared_ptr<SoftwareEngineer> software_engineers[NUMBER_ENGINEERS];

    for (int i = 0; i < NUMBER_ENGINEERS; ++i)
    {
        cout << "\nEnter the information about " << i+1 <<" software engineer:\n";
        Input(software_engineers[i]);
        system("cls");
    }

    cout << "\nEnter the index of the engineer, the information about which you show: ";
    int pos_engineer;
    cin >> pos_engineer;

    shared_ptr<SoftwareEngineer> show_engineer = ShowData(software_engineers, pos_engineer, NUMBER_ENGINEERS);

    system("cls");
    cout << "\nEnter the index of the engineer, the information about which you what change: ";
    cin >> pos_engineer;

    shared_ptr<SoftwareEngineer> change_engineer = ChangeData(software_engineers, pos_engineer, NUMBER_ENGINEERS);
    cout << "\n\tChange engineer:\n";
    change_engineer->Show();

    cout << "\n\tAll engineers: \n";
    for (int i = 0; i < NUMBER_ENGINEERS; ++i)
        software_engineers[i]->Show();

    return 0;
}

Але програма вилітає ось тут:

void SetName(string name)
    {
        if (ValidInputString(name))
            this->name = name;
    }

а точніше на рядку:

this->name = name;

В чому може бути проблема?

39

(16 відповідей, залишених у C++)

Задача - розробити програму "Відділ кадрів". Але в постановці задачі, є деякі речі, які мене бентежать.

Логічна структура даних
1. Інформаційний об’єкт "робітник". Помимо звичайних атрибутів є такий: Назва - "Підрозділ, де працює", а тип - Об’єкт типу "підрозділ".

2. Інформаційний об’єкт "підрозділ". Аналогічно, є певні атрибути і ось такий: Назва - Робітники підрозділу, а тип -
Структура даних з об’єктів типу "робітник".

От як це? Якщо ще на python можна зробити щось отаке:

Прихований текст
class Department(object):
    def __init__(self, name):
        self.name = name
        self.workers = []
 
    def get_name(self):
        return self.name
 
    def add_worker(self, worker):
        self.workers.append(worker)
 
    def get_workers(self):
        return self.workers
 
 
class Worker(object):
    def __init__(self, name, department):
        self.name = name
        self.department = department
        self.department.add_worker(self)
 
    def get_name(self):
        return self.name
 
    def get_department_name(self):
        return self.department.get_name()
 
managers = Department('manager')
major_manager = Worker('John', managers)
print major_manager.get_department_name()

то на С++ неможливо, бо масив (тут - self.workers = []) повинен бути якогось типу, чи навіть якщо вказівники, то вони якогось типу. А в Department ми не можемо використовувати тип Worker, бо він ще не оголошений. То як же вийти із цієї ситуації? Чи може завдання некоректно поставлене? Бо навіть з Python воно якось негарно виглядить як на мене.

40

(82 відповідей, залишених у Інше)

https://i.imgur.com/N81VEsW.png