Sistem de depanare a aplicatiilor in limbajul C-plus-plus
From linux360
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)
