Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Program rysujący menu (początki w programowaniu C++)

Ostatnio zmodyfikowano 2013-02-05 11:20
Autor Wiadomość
Katoda
Temat założony przez niniejszego użytkownika
[C++] Program rysujący menu (początki w programowaniu C++)
» 2013-02-05 10:47:33
Witam. Niedawno zacząłem się interesować programowaniem w c++ i chciałbym zasięgnąć waszej opinii w sprawie mojego prostego programu. Chciałbym usłyszeć opinie w sprawie optymalizacji kodu tzn. czy coś da się zrobić w nim lepiej.  Funkcje ClearScreen i ChangeCursorStatus znalazłem w internecie (nie potrafiłbym za Chiny takich funkcji napisać) reszta jest moja. Kod jest trochę długi, ale chyba nie trudny w zrozumieniu.

ps. zdaję sobie sprawę, że po wybraniu opcji "O programie" nic się nie dzieje
ps2. w funkcji rysującej menu mógłbym użyć funkcji typu "gotoxy" zamiast ClearScreen - wyeliminowałoby to efekt mrugania tekstu w przypadku szybkiego naciskania klawiszy strzałek

C/C++
#include <iostream>
#include <conio.h>
#include <Windows.h>
#include <string>

using namespace std;

/*================================================*/

void ChangeCursorStatus( bool Visible );
void ClearScreen();
void draw_menu_( int menu_position );
void menu_( int menu_position );

/*================================================*/

int main()
{
    unsigned max_menu = 4;
    char c_key = 0;
    int menu_position = 0;
    bool app_exit = false;
   
    ChangeCursorStatus( false );
   
   
    do // zaczyna sie petla rysujaca menu
    {
        draw_menu_( menu_position ); // rysuje menu
        c_key = _getch(); // sprawdza wcisniecie klawisza
       
        switch( c_key ) // reaguje odpowiednio na nacisniecie klawisza (patrz nizej)
        {
        case 'P': // jesli nacisnieto strzalke w dol to przesun aktywna pozycje w menu o 1 w dol,
            // jezeli aktywna opcja jest ostatnia pozycja w menu nie robi nic
            {
                if( menu_position != max_menu ) menu_position += 1;
               
                break;
            }
        case 'H': // to samo tylko ze strzalka w gore, jesli aktywna opcja jest 1sza opcja - nie robi nic
            {
                if( menu_position != 0 ) menu_position -= 1;
               
                break;
            }
        case '\r': // reaguje na nacisniecie klawisza enter w zaleznosci od aktywnej opcji w menu
            {
                if( menu_position == 3 ) app_exit = true; // konczy petle = konczy program
               
                if( menu_position == 2 ) menu_( 3 );
               
                if( menu_position == 1 ) menu_( 2 );
               
                if( menu_position == 0 ) menu_( 1 );
               
                break;
            }
            default: break;
        }
       
       
    } while( app_exit == false );
   
    return 0;
}

/* ==========================================================================================*/
/* ====================================== funkcje ===========================================*/
/* ==========================================================================================*/

void ChangeCursorStatus( bool Visible ) // funkcja usuwajaca migajacy kursor
{
    CONSOLE_CURSOR_INFO * c = new CONSOLE_CURSOR_INFO;
    HANDLE h = GetStdHandle( STD_OUTPUT_HANDLE );
   
    if( Visible )
    {
        c->bVisible = TRUE;
        c->dwSize = 0;
    }
    else
    {
        c->bVisible = FALSE;
        c->dwSize = 1;
    }
   
    SetConsoleCursorInfo( h, c );
}


/*===================================================================================*/

void ClearScreen() // funkcja czyszczaca ekran
{
   
    HANDLE hStdOut;
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    DWORD count;
    DWORD cellCount;
    COORD homeCoords = { 0, 0 };
   
    hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
    if( hStdOut == INVALID_HANDLE_VALUE ) return;
   
    if( !GetConsoleScreenBufferInfo( hStdOut, & csbi ) ) return;
   
    cellCount = csbi.dwSize.X * csbi.dwSize.Y;
   
    if( !FillConsoleOutputCharacter(
    hStdOut,
    ( TCHAR ) ' ',
    cellCount,
    homeCoords,
    & count
    ) ) return;
   
    if( !FillConsoleOutputAttribute(
    hStdOut,
    csbi.wAttributes,
    cellCount,
    homeCoords,
    & count
    ) ) return;
   
    SetConsoleCursorPosition( hStdOut, homeCoords );
}

/*===================================================================================*/

void draw_menu_( int menu_position ) // funkcja rysujaca menu
{
    string menu_item[ 5 ]; // ilosc pozycji w menu
    menu_item[ 0 ] = "Pozycja w menu nr 1"; // poszczegolne opcje menu
    menu_item[ 1 ] = "Pozycja w menu nr 2";
    menu_item[ 2 ] = "Pozycja w menu nr 3";
    menu_item[ 3 ] = "Wyjscie z programu\n";
    menu_item[ 4 ] = "O programie";
   
    ClearScreen(); // czysci ekran przed narysowaniem menu
    cout << "\n\n";
    for( int i = 0; i < 5; i++ ) // rysuje menu
    {
        if( i == menu_position ) cout << "\t>>\t"; // rysuje symbol >> na aktywnej pozycji w menu
       
        if( i != menu_position ) cout << "\t\t"; // na nieaktywnych pozycjach rysuje biale znaki (tabulatory)
       
        cout << menu_item[ i ] << endl;
    }
}

/*===================================================================================*/

void menu_( int menu_position ) // funkcja ukazujaca przykladowy efekt wywolania menu
{
    ClearScreen();
    cout << "\n\n\n\t\tWitaj w menu nr " << menu_position << " !";
    _getch();
}
P-75759
Monika90
» 2013-02-05 11:06:35
Tak na pierwszy rzut oka, to tak:
Funkcja ChangeCursorStatus alokuje pamięć, ale jej nie zwalnia, to się nazywa memory leak,
w ogóle w tym przypadku nie ma sensu używać new, wystarczy zwykła zmienna automatyczna.

Używanie w warunkach wyrażeń postaci cośtam == true albo app_exit == false jest bez sensu,
lepiej jest po prostu !app_exit

W funkcji draw_menu_ (po co znak podkreślenia na końcu?) tablicę stringów można zainicjalizować od razu, o tak: string a[3] = { "abc", "123", xyz" };
A zamiast sprawdzać czy (i != menu_position) wystarczyło użyć else.
P-75760
Katoda
Temat założony przez niniejszego użytkownika
» 2013-02-05 11:20:35
Co do funkcji ChangeCursorStatus to nie jest moja funkcja i kompletnie jej nie rozumiem, dlatego jej nie zmieniałem. Co do nazwy funkcji to tak - kreska na dole jest niepotrzebna :) To pozostałość po starej nazwie tej funkcji i jakoś tak zostało. Co do uwag dotyczących tablic i !app_exit postaram się do nich stosować na przyszłość :) Jeżeli chodzi o to else to też masz rację :) Dzięki !
P-75761
« 1 »
  Strona 1 z 1