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)