Personal tools

Sistem de depanare a aplicatiilor in limbajul C-plus-plus

From linux360

Revision as of 00:31, 11 February 2006 by 211.222.231.73 (talk)
Jump to: navigation, search

Mesaje intr-o consola

Sa presupunem ca la un moment dat avem nevoie sa obtinem valorile unor variabile care nu se pot afla prin breakpoints; de exemplu într-o funcţie de reîmprospatare a unei ferestre, care se apelează într-un ciclu infinit. Aceste valori le putem afla prin două modalitaţi: scrierea lor intr-un fişier de log sau afişarea lor intr-o consolă. Fiecare dintre cele două are avantaje şi dezavantaje.


consolă - avantaje (faţă de log):

  • mesajele se pot urmări În timpul rulării programului
  • nu necesită spaţiu suplimentar pe Hard Disk Drive (HDD)


consolă - dezavantaje (faţă de log):

  • consumă resurse suplimentare


  • Crearea consolei

- kdsconsole.h

/***************************************************************************
*   Copyright (C) 2005 Radu Bolovan                                       *
*   radubolovan@dainet.ro                                                 *
*                                                                         *
*   This is free software; you can redistribute it and/or modify it       *
*   under the terms of the GNU General Public License as published by     *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/
#ifndef KDSCONSOLE_H
#define KDSCONSOLE_H

#include <qtextedit.h>

class QTimer;

class KDSConsole : public QTextEdit
{
    Q_OBJECT
public:
    /* constructor */
    KDSConsole( QWidget *parent = 0, const char *strLogFileName = 0 );

    /* destructor */
    ~KDSConsole();

    /* activare salvare automata intr-un fisier */
    void enableAutoSave( bool bEnable, int nTime = 2000 );

    /* seteaza fisierul in care sa salveze */
    void setLogFileName( QString strLogFileName );

public slots:
    /* salveaza in fisier */
    void saveToLogFile();

protected:
    /* se apeleaza DOAR cand se apasa butonul drept al mouse-ului
     * ----- vezi kdsconsole.cpp -----
    */
    void contentsMousePressEvent( QMouseEvent *event );

protected:
    /* numele fisierului in care se salveaza */
    char *m_strLogFileName;

    /* timer-ul */
    QTimer *m_pTimer;
};

extern KDSConsole *g_pConsole;

#endif

- kdsconsole.cpp

#include "kdsconsole.h"

#include <qtimer.h>
#include <qaction.h>
#include <qevent.h>
#include <qpopupmenu.h>

KDSConsole *g_pConsole = NULL;

KDSConsole::KDSConsole( QWidget *parent, const char *strLogFileName )
: QTextEdit( parent )
{
    /* nu trebuie sa se editeze */
    setReadOnly( true );

    /* aliniez textul la stanga */
    setAlignment ( Qt::AlignLeft );

    /* daca consola se creaza de sine statatoare
     * (intr-o alta fereastra decat a aplicatiei, sau a unei clase a aplicatiei)
     * setez dimensiunile ferestrei
    */
    if( !parent )
        setMinimumSize( 640, 150 );

    /* setez numele fisierul in care se va scrie
     * strLogFileName este numele fisierului
    */
    if( strLogFileName )
    {
        m_strLogFileName = new char [ strlen( strLogFileName ) + 1 ];
        strcpy( m_strLogFileName, strLogFileName );
    }
    else
        m_strLogFileName = NULL;

    /* setez un ceas pentru optiunea de auto salvare */
    m_pTimer = new QTimer( this );
    connect( m_pTimer, SIGNAL( timeout() ), this, SLOT( saveToLogFile() ) );

    setMouseTracking( true );
}

KDSConsole::~KDSConsole()
{
    /* daca exista un fisier atasat, ii sterg numele din memorie */
    if( m_strLogFileName )
    {
        delete []m_strLogFileName;
        m_strLogFileName = NULL;
    }
}

void KDSConsole::enableAutoSave( bool bEnable, int nTime )
{
    if( bEnable )
        m_pTimer->start( nTime );
    else
        m_pTimer->stop();
}

void KDSConsole::setLogFileName( QString strLogFileName )
{
    unsigned int nLength = strLogFileName.length() + 1;

    /* daca exista deja un fisier atasat si daca numele lui este mai mic decat cel curent,
     * el (numele) trebuie realocat dinamic
    */
    if( m_strLogFileName )
    {
        if( strlen( m_strLogFileName ) < nLength )
        {
            delete []m_strLogFileName;
            m_strLogFileName = new char[ nLength ];
            }
    }
    else
        m_strLogFileName = new char[ nLength ];

    unsigned int nIndex;

    /* copiez numele fisierului curent "in" cel al clasei */
    for( nIndex = 0; nIndex < nLength - 1; nIndex++ )
        m_strLogFileName[ nIndex ] = strLogFileName.at( nIndex ).latin1();
    m_strLogFileName[ nIndex ] = '\0';
}

void KDSConsole::saveToLogFile()
{
    /* daca nu exista un fisier atasat
     * atunci afisez un mesaj de eroare in consola
     * si ies din functie
     */
    if( !m_strLogFileName )
    {
        append( "I cannot find an attached file" );
        return;
    }

    FILE *file = fopen( m_strLogFileName, "w" );

    /* daca nu se poate crea fisierul cu numele dat,
     * afisez un mesaj in consola si ies din functie
    */
    if( !file )
    {
        QString strTmp = "I cannot create file " + (QString)m_strLogFileName;
        append( strTmp );
        return;
    }

    /* obtin textul din consola si il convertesc QString la char* */
    QString strTmp = text();
    int nLength = strTmp.length() + 1;
    char *strText = new char[ nLength ];
    int nIndex;
    for( nIndex = 0; nIndex < nLength - 1; nIndex++ )
        strText[ nIndex ] = strTmp.at( nIndex ).latin1();
    strText[ nIndex ] = '\0';

    /* scriu in fisier textul din consola */
    fprintf( file, "%s", strText );

    /* daca nu se poate inchide fisierul, se afiseaza un mesaj in consola */
    if( fclose( file ) == 0 )
         append( "Saved to log" );
    else
         append( "I couldn't close the file" );

    delete []strText;
}

void KDSConsole::contentsMousePressEvent( QMouseEvent *event )
{
    /* in cazul in care se apasa butonul drept al mouse-ului
     * se creaza un meniu
    */
    if( event->button() == Qt::RightButton )
    {
        QPopupMenu *menu = new QPopupMenu( this );
        menu->insertItem( tr( "Save to log file" ), this, SLOT( saveToLogFile() ) );
        menu->setMouseTracking( true );
        menu->exec( mapToGlobal( event->pos() ) );
    }
}

Dupa cum se vede am declarat şi definit o variabilă globală de tipul KDSConsole, externă - pentru a o putea apela din orice fişier. Pentru folosirea unui astfel de obiect (KDSConsole) voi mai adăuga incă două metode, faţă de cel obişnuit:

g_pConsole = new KDSConsole();
g_pConsole->setCaption( "KDSConsole" );
g_pConsole->show();

//ceva cod

g_pConsole->append( "Test in consola" ); //functia append() apartine clasei QTextEdit

//alt cod

g_pConsole->hide();
delete g_pConsole;
g_pConsole = NULL;

1) Funcţii statice ale unei clase:

- kdsutils.h

#ifndef KDSUTILS_H
#define KDSUTILS_H

#include "kdsconsole.h"

#include <qstring.h>

class KDSUtils
{
    public:
    KDSUtils(){;}
    ~KDSUtils(){;}

    static void initConsole(){ g_pConsole = new KDSConsole(); g_pConsole->setCaption( "KDSConsole" ); g_pConsole->Show(); }
    static void appendToConsole( QString str ){ if( g_pConsole ) g_pConsole->append( str ); }
    static void setConsoleFileName( QString str ){ if( g_pConsole ) g_pConsole->setLogFileName( str ); }
    static void setConsoleAutoSave( bool bEnable, int nTime ){ if( g_pConsole ) g_pConsole->enableAutoSave( bEnable, nTime ); }
    static void saveConsoleToFile() { if( g_pConsole ) g_pConsole->saveToLogFile(); }
    static void destroyConsole(){ if( g_pConsole ){ g_pConsole->hide(); delete g_pConsole; g_pConsole = NULL; } }
};
 
#endif

Acestea se pot apela (după cum se cunoaşte) prin:

KDSUtils::initConsole(); //numai la initializarea aplicatiei
KDSUtils::setConsoleFileName( "/home/Radu/kdsconsole.txt" );
KDSUtils::setConsoleAutoSave( true, 60000 ); // salveaza o data pe minut - 1000 milisecunde = o secunda

//ceva cod

KDSUtils::ippendToConsole( "Un text in consola" );

//alt cod

KDSUtils::destroyConsole(); //cand nu mai avem nevoie de consola

2) Macro-uri:

- kdsdefs.h

#ifndef KDSUTILS_H
#define KDSUTILS_H

#include "kdsconsole.h"

#define INIT_CONSOLE() KDSUtils::initConsole()
#define SET_CONSOLE_FILE_NAME( fileName ) KDSUtils::setConsoleFileName( fileName )
#define SET_CONSOLE_AUTOSAVE( enable, time ) KDSUtils::setConsoleAutoSave( enable, time )
#define SAVE_CONSOLE_TO_FILE() KDSUtils::saveConsoleToFile()
#define KDS_TRACE( string ) KDSUtils::appendToConsole( string )
#define DESTROY_CONSOLE() KDSUtils::destroyConsole()

#endif

Observatii:

1) Nu folosiţi mai mult de una dintre cele trei metode!!!

2) Acelaşi efect se poate obţine punând

printf( "Un text catre consola" );

oriunde in cod si rularea programului din consolă (KConsole)

3) Funcţia de adăugare a unui text în consolă se mai poate implementa astfel încat sa primească un numar nelimitat de parametrii şi să funcţioneze analog funcţiei sprintf().

--Radu Bolovan 01:32, 21 December 2005 (EET)