View Full Version : [C++] funzione che ritorna vector<?>
trallallero
03-01-2008, 15:45
Sto cominciando ad usare STL solo adesso e mi servirebbe (se possibile) creare una
funzione che ritorna un vector<tipo> dove tipo può essere
(per adesso) un int o double
si può e, se si, come si fa ?
grazie
Fai una funzione template ;)
template <class T>
vector<T> funzione();
trallallero
03-01-2008, 16:33
Fai una funzione template ;)
template <class T>
vector<T> funzione();
così semplice ? :eek:
EDIT:
ho googlato questo:
vector "unknown type" return function c++
ed è uscito l'impossibile :D
grazie
Certo ;)
Dopo per richiamarla:
vector<int> v = funzione<int>();
vector<double> v = funzione<double>();
trallallero
03-01-2008, 16:38
Certo ;)
Dopo per richiamarla:
vector<int> v = funzione<int>();
vector<double> v = funzione<double>();
infatti, già prevedevo una richiesta di aiuto per la chiamata alla funzione
vabbè grazie di nuovo.
Certo che è potente 'sto STL ... anche se in certe occasioni preferisco ancora usare funzioni C tipo strstr, strchr etc
anche se in certe occasioni preferisco ancora usare funzioni C tipo strstr, strchr etc
Male...le string funzionano alla grande per fare quelle cose ;)
trallallero
04-01-2008, 08:28
Male...le string funzionano alla grande per fare quelle cose ;)
'nsomma ... o forse sono io che non avendo molta dimestichezza con l'STL (e poca paziena :D) preferisco usare le low-level ones
quello che non mi piace è che le varie find tornano sempre un indice e mai un char pointer quindi, trovato per esempio il valore, devi fare una substr illeggibile,
A sto punto meglio un return strstr(...)
è anche vero che certe volte ti semplificano la vita come per esempio in quest trim che ho fatto
string Util::trimString( const string& s )
{
unsigned int begin = s.find_first_not_of(' ');
unsigned int end = s.find_last_not_of (' ');
return s.substr( begin, end-begin+1);
}
senza STL sarebbe sicuramente più illeggibile
Appunto...basta lavorare esclusivamente con le string e sei a posto...poi se devi usare qualche libreria che ha come parametri char * basta convertire con c_str().
trallallero
04-01-2008, 09:04
Appunto...basta lavorare esclusivamente con le string e sei a posto...poi se devi usare qualche libreria che ha come parametri char * basta convertire con c_str().
scusa se insisto ma a questo punto vorrei sapere come faresti questa funzione senza l'uso di un rapido strchr.
È una funzione che cerca una stringa delimitata da certi caratteri in una stringa sorgente. Ho usato sia string che funzioni C
All'inizio pSrc era di tipo string& poi ho sbroccato (non ricordo perchè ma per colpa di 'ste string) ed ho messo char*
string LLUtils::GetDelimitedString( const char* pSrc, int LeftDelimiter, int RightDelimiter )
{
LogL.Write( LogLib::LOGLIB_DEBUG_FLOW_MSG, LOGLIB_FIX_ARGS, 0, "" );
if (pSrc) // so the caller can avoid checking
{
char* start = strchr( pSrc, LeftDelimiter );
if (start) // left delimiter was found
{
while(*(++start) == ' ')
; // skip left spaces
char* end = strchr( start, RightDelimiter );
if (end) // right delimiter was found
{
while(*(--end) == ' ')
; // skip right spaces
string s(pSrc); // create the string to be returned
s.substr( (start - pSrc) );
return s.substr( (start - pSrc), (end - start + 1) );
}
}
}
return "";
}
////////////////////////////////////////////////////////////////////
variabilepippo
04-01-2008, 09:14
scusa se insisto ma a questo punto vorrei sapere come faresti questa funzione senza l'uso di un rapido strchr.
Potresti determinare gli indici da passare a tuastringa.substr con i metodi find e rfind della classe string. :)
Vediamo:
string LLUtils::GetDelimitedString( const string &src, int LeftDelimiter, int RightDelimiter )
{
LogL.Write( LogLib::LOGLIB_DEBUG_FLOW_MSG, LOGLIB_FIX_ARGS, 0, "" );
string result = "";
size_t left = src.find_first_of(LeftDelimiter);
size_t right = src.find_last_of(RightDelimiter);
if(left != str::npos && right != str::npos)
{
result = Util::trimString(src.substr(left, right));
}
return result;
}
Se ho capito bene ;)
trallallero
04-01-2008, 09:40
Potresti determinare gli indici da passare a tuastringa.substr con i metodi find e rfind della classe string. :)
...
Se ho capito bene ;)
ecco, come volevasi dimostrare ... Cionci hai capito bene anzi, benissimo :D
Praticamente ci ho litigato per un pò, poi ho optato per ciò che conosco benissimo per non perdere tempo prezioso e invece era fattibilissimo.
vabbè, grazie ancora :)
trallallero
04-01-2008, 09:57
beh, visto che orami è una disputa (amichevole e costruttiva - per me almeno) tra STL e C functions, vorrei proporvi un'altra ... gara :D
(ed è quì che mi serviva una funzione che torna vector<type>)
ho una stringa di questo formato "x < y" dove x è un valore minimo e y quello massimo.
La funzione torna un vector di interi dal minimo al massimo.
Quindi se il minimo è 1 e il massimo 5, torna
1 2 3 4 5
Calcolando che il tutto deve essere il più veloce possibile (sto lavorando ad un progetto per la comunicazione tra un carro armato e vari operatori) l'ho fatta così
(io avrei fatto a meno anche del lento vector e fatto tutto con un array di int :stordita: )
vector<int> LLUtils::GetMinToMaxValues( string& s, int Separator )
{
vector<int> v;
int Min = atoi( s.c_str() ); // 1st value, atoi stops at first non digit char
int Max = atoi( strchr(s.c_str(), Separator) + 1 ); // 2nd value, atoi from char after Separator
for ( int i = Min; i <= Max; ++i )
v.push_back(i); // creates the list
return v;
}
Certo che anche la tua non va male...ma quando posso tento di non mischiare C e C++.
Il codice sotto in teoria non necessita del parametro separator...sempre che il separatore fra i numeri non sia composto da diversi caratteri con spazi nel mezzo...
Quindi a seconda delle specifiche del problema la tua potrebbe andare meglio di quella che ho scritto sotto. Se il formato è sempre quello che mi hai scritto "3 > 10" però va sempre bene.
vector<int> LLUtils::GetMinToMaxValues(const string& s)
{
int min, max;
string separator;
istringstream iss(s);
iss >> min >> separator >> min;
for ( int i = Min; i <= Max; ++i )
v.push_back(i); // creates the list
return v;
}
trallallero
04-01-2008, 10:30
Certo che anche la tua non va male...ma quando posso tento di non mischiare C e C++.
Il codice sotto in teoria non necessita del parametro separator...sempre che il separatore fra i numeri non sia composto da diversi caratteri con spazi nel mezzo...
Quindi a seconda delle specifiche del problema la tua potrebbe andare meglio di quella che ho scritto sotto. Se il formato è sempre quello che mi hai scritto "3 > 10" però va sempre bene.
vector<int> LLUtils::GetMinToMaxValues(const string& s)
{
int min, max;
string separator;
istringstream iss(s);
iss >> min >> separator >> min;
for ( int i = Min; i <= Max; ++i )
v.push_back(i); // creates the list
return v;
}
uhm ... figata come tecnica ma non andrebbe bene nei valori multipli.
Ho Min to Max, Min & Max, e valori multipli separati da |
Però grazie, interessante ;)
Fammi un esempio di valori multipli...
trallallero
04-01-2008, 10:41
Fammi un esempio di valori multipli...
non ne abbiamo ancora ma la settimana prossima arriveranno i dati di configurazione di un dispositivo radio che dovrà far parte della comunicazione.
Ma da quello che ho capito sono solo interi quindi la stringa potrebbe essere qualcosa come:
"1 | 3 | 12 | 45"
ovviamente possono essere 1 così come 10.000 ...
Pensavo di aver già fatto la funzione invece non la trovo ... mi sa che devo dormire un pò di più e lavorare un pò di meno ... :D
EDIT: ah ecco, avevo fatto qualcosa trovando degli esempi STL in internet:
bool LLElementHandler::GetFields( string & text, string & separators, list<string> &words )
{
LogL.Write( LogLib::LOGLIB_DEBUG_FLOW_MSG, LOGLIB_FIX_ARGS, 0, "" );
int n = text.length();
int start, stop;
start = text.find_first_not_of(separators);
while ((start >= 0) && (start < n))
{
stop = text.find_first_of(separators, start);
if ((stop < 0) || (stop > n))
stop = n;
words.push_back( text.substr(start, stop - start) );
start = text.find_first_not_of(separators, stop + 1);
}
return true;
}
però mi sa di lento ... :rolleyes:
Se sono separati da spazio e da un altro carattere:
#include <sstream>
#include <iostream>
#include <vector>
using namespace std;
vector<int> parse(const string &s)
{
istringstream iss(s);
vector<int> v;
string separator;
while (!iss.fail())
{
int tmp;
iss >> tmp;
if (!iss.fail()) v.push_back(tmp);
iss >> separator;
}
return v;
}
int main()
{
vector<int> v = parse("1 | 3 | 5 | 5");
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
cout << *it << " ";
cout << endl;
v = parse("1 < 5");
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
cout << *it << " ";
cout << endl;
return 0;
}
trallallero
04-01-2008, 11:23
in pratica se non da errore è un intero e lo copi in list, l'ultimo errore fa uscire.
Interessante ...
in C è più corto ed elegante :O
v.push_back(atoi(c));
while( c = strchr(c, Separator) )
v.push_back(atoi(++c));
scherzo ovviamente.
Insomma con 'sto STL se pò fà tutto ... mi devo solo abituare ad usarlo ... addio C :cry:
trallallero
04-01-2008, 12:34
ultimissima, lo giuro :stordita:
sto applicando ciò che m'hai scritto (template)
ma adesso che non so che tipo è, come faccio a estrapolare i dati ?
Ovviamente non posso più fare atoi, quindi ?
template <class T> vector<T> LLUtils::GetMinToMaxValues( string& s, int Separator )
{
vector<T> v;
int Min = atoi( s.c_str() );
int Max = atoi( strchr(s.c_str(), Separator) + 1 );
for ( int i = Min; i <= Max; ++i )
v.push_back(i);
return v;
}
trallallero
04-01-2008, 12:42
forse così ?
template <class T> vector<T> LLUtils::GetMinToMaxValues( string& s, int Separator )
{
vector<T> v;
T Min = s.find_first_not_of(Separator);
T Max = s.find_last_not_of (Separator);
for ( T i = Min; i <= Max; ++i )
v.push_back(i);
return v;
}
EDIT: 'zzo ho scritto ? :eek:
Questo è tutto un altro discorso :)
Allora devi sapere prima il tipo di dato...che tipi di dati puoi avere ?
trallallero
04-01-2008, 14:16
Questo è tutto un altro discorso :)
Allora devi sapere prima il tipo di dato...che tipi di dati puoi avere ?
ho lasciato perdere anche perchè mi dava un errore terribile il linker ...
il problema comunque è che non posso fare una lista da min a max proprio perchè non conosco il tipo di dato.
E comunque ho visto che il tipo dovrebbe essere solo int quindi uso solo int e taglio la testa al toro
Ma magari nelle altre funzioni dove estrapola solo i valori presenti nella lista si può fare
Se poi hai qualche mandrakata in mente sono quì :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.