//---------------------------------------------------------------------------- // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : StringUtils.cpp Data : 02.12.13 Versione : 1.4a1 // Contenuto : Implementazione delle funzioni di utilità per le stringhe. // // // // Modifiche : 20.01.13 DS Creazione modulo. // 02.12.13 DS Agg. FromString per Vector3d, Point3d e Point3d+W. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "/EgtDEv/Include/EgnStringUtils.h" using namespace std ; //---------------------------------------------------------------------------- bool FromString( const std::string& sVal, Vector3d& vtVal) { STRVECTOR vsParams ; // divido la stringa in parametri Tokenize( sVal, ",", vsParams) ; // devono essere 3 parametri : x, y, z if ( vsParams.size() != 3) return false ; // recupero il punto return ( FromString( vsParams[0], vtVal.x) && FromString( vsParams[1], vtVal.y) && FromString( vsParams[2], vtVal.z)) ; } //---------------------------------------------------------------------------- bool FromString( const std::string& sVal, Point3d& ptVal) { STRVECTOR vsParams ; // divido la stringa in parametri Tokenize( sVal, ",", vsParams) ; // devono essere 3 parametri : x, y, z if ( vsParams.size() != 3) return false ; // recupero il punto return ( FromString( vsParams[0], ptVal.x) && FromString( vsParams[1], ptVal.y) && FromString( vsParams[2], ptVal.z)) ; } //---------------------------------------------------------------------------- bool FromString( const std::string& sVal, Point3d& ptVal, double& dW) { STRVECTOR vsParams ; // divido la stringa in parametri Tokenize( sVal, ",", vsParams) ; // devono essere 4 parametri : x, y, z, w if ( vsParams.size() != 4) return false ; // recupero il punto return ( FromString( vsParams[0], ptVal.x) && FromString( vsParams[1], ptVal.y) && FromString( vsParams[2], ptVal.z) && FromString( vsParams[3], dW)) ; } //---------------------------------------------------------------------------- const string ToString( int nVal, int nPrec) { int nErr ; int nLen ; char szBuff[24] ; // eseguo conversione nErr = _itoa_s( nVal, szBuff, 10) ; // se errore, ritorno stringa opportuna if ( nErr != 0) { _ASSERT( 0) ; return "#Error" ; } // verifico lunghezza minima if ( ( nLen = (int) strlen( szBuff)) >= nPrec) return szBuff ; // porto la stringa alla minima lunghezza string sBuff( szBuff) ; sBuff.insert( 0, ( nPrec - nLen), '0') ; return sBuff ; } //---------------------------------------------------------------------------- const string ToString( double dVal, int nPrec) { const double BIG_NUMBER = 1e10 ; const int BIG_DIGITNBR = 10 ; const int MAX_PREC = 12 ; char szBuff[24] ; char szDest[32] ; char* pBuff ; char* pDest ; int nErr ; int nDecimal ; int nSign ; int nExp ; int nTmp ; // verifico la precisione nPrec = min( nPrec, MAX_PREC) ; // converto la mantissa if ( fabs( dVal) < BIG_NUMBER) nErr = _fcvt_s( szBuff, dVal, nPrec, &nDecimal, &nSign) ; else nErr = _ecvt_s( szBuff, dVal, BIG_DIGITNBR + nPrec, &nDecimal, &nSign) ; // se errore, ritorno stringa opportuna if ( nErr != 0) { _ASSERT( 0) ; return "#Error" ; } // se buffer vuoto, risultato è numero 0 if ( szBuff[0] == '\0') return "0" ; // verifica per forma esponenziale if ( nDecimal > BIG_DIGITNBR) { nExp = nDecimal - 1 ; nDecimal = 1 ; } else nExp = 0 ; // puntatori a inizio stringhe pBuff = szBuff ; pDest = szDest ; // eventuale inserimento segno '-' if ( nSign != 0) { *pDest = '-' ; pDest ++ ; } ; // gestione decimali dopo 0 if ( nDecimal <= 0) { *pDest = '0' ; pDest ++ ; *pDest = '.' ; pDest ++ ; for ( ; nDecimal < 0 ; nDecimal ++) { *pDest = '0' ; pDest ++ ; } nDecimal -- ; } // gestione cifre e . while ( *pBuff != '\0') { if ( *pBuff == '#') // NAN, INFINITY, INDEFINITE _ASSERT( 0) ; if ( nDecimal == 0) { *pDest = '.' ; pDest ++ ; } nDecimal -- ; *pDest = *pBuff ; pDest ++ ; pBuff ++ ; } *pDest = '\0' ; // se inserito un punto decimale tolgo i trailing zero if ( nDecimal < 0) { pDest -- ; while ( *pDest == '0') { *pDest = '\0' ; pDest -- ; } if ( *pDest == '.') *pDest = '\0' ; else pDest ++ ; } // aggiungo eventuale esponente (sempre compreso tra 9 e 308) if ( nExp > 0) { *pDest = 'e' ; pDest ++ ; nTmp = nExp ; if ( nTmp >= 100) { *pDest = '0' + ( nTmp / 100) ; pDest ++ ; nTmp = nTmp % 100 ; } if ( nTmp >= 10 || nExp >= 100) { *pDest = '0' + ( nTmp / 10) ; pDest ++ ; nTmp = nTmp % 10 ; } *pDest = '0' + nTmp ; pDest ++ ; *pDest = '\0' ; } if ( szDest[0] == '-' && szDest[1] == '0' && szDest[2] == '\0') return "0" ; else return szDest ; } //---------------------------------------------------------------------------- void Split( const string& sString, const string& sSeparator, bool bFirstVsLast, string& sFirst, string& sLast) { string::size_type iPos ; // cerco il separatore iPos = ( bFirstVsLast ? sString.find( sSeparator) : sString.rfind( sSeparator)) ; // se trovato if ( iPos != string::npos) { if ( iPos > 0) sFirst = sString.substr( 0, iPos) ; else sFirst.clear() ; if ( ( iPos + 1) < sString.length()) sLast = sString.substr( iPos + 1) ; else sLast.clear() ; } // altrimenti else { sFirst = sString ; sLast.clear() ; } } //---------------------------------------------------------------------------- bool Tokenize( const string& sString, const string& sSeparators, STRVECTOR& vsTokens) { string::size_type iPosStart ; string::size_type iPosEnd ; // pulisco il risultato vsTokens.clear() ; // parto dall'inizio iPosStart = ( sString.empty() ? string::npos : 0) ; // mentre esiste un nuovo inizio di token while ( iPosStart != string::npos) { // cerco il primo separatore iPosEnd = sString.find_first_of( sSeparators, iPosStart) ; // aggiungo il token al vettore vsTokens.push_back( sString.substr( iPosStart, iPosEnd - iPosStart)) ; // cerco l'inizio di un nuovo token iPosStart = sString.find_first_not_of( sSeparators, iPosEnd) ; } return true ; } //---------------------------------------------------------------------------- bool Tokenize( const string& sString, const string& sSeparators, const string& sAtomStarts, const string& sAtomEnds, STRVECTOR& vsTokens) { string::size_type iPosStart ; string::size_type iPosEnd ; string::size_type iAtomStart ; string::size_type iAtomEnd ; // i separatori devono essere diversi da inizio e fine di atomi if ( sAtomStarts.find_first_of( sSeparators) != string::npos || sAtomEnds.find_first_of( sSeparators) != string::npos) return false ; // parto dall'inizio iPosStart = ( sString.empty() ? string::npos : 0) ; // mentre esiste un nuovo inizio di token while ( iPosStart != string::npos) { // eventuale inizio e fine di parte atomica iAtomStart = sString.find_first_of( sAtomStarts, iPosStart) ; iAtomEnd = sString.find_first_of( sAtomEnds, iAtomStart) ; // cerco il primo separatore iPosEnd = sString.find_first_of( sSeparators, iPosStart) ; // se separatore è nella parte atomica, lo ricerco dopo la sua fine if ( iAtomStart != string::npos && iPosEnd != string::npos && iPosEnd > iAtomStart && iPosEnd < iAtomEnd) iPosEnd = sString.find_first_of( sSeparators, iAtomEnd) ; // aggiungo il token al vettore vsTokens.push_back( sString.substr( iPosStart, iPosEnd - iPosStart)) ; // cerco l'inizio di un nuovo token iPosStart = sString.find_first_not_of( sSeparators, iPosEnd) ; } return true ; } //---------------------------------------------------------------------------- int ReplaceString( std::string& sString, const std::string& sOld, const std::string& sNew) { int nSubs ; size_t pos ; nSubs = 0 ; pos = 0 ; while ( ( pos = sString.find( sOld, pos)) != std::string::npos) { sString.replace( pos, sOld.length(), sNew) ; pos += sNew.length() ; nSubs ++ ; } return nSubs ; }