Newsgroup: it.comp.lang.c++
Titolo: E' possibile ottenerlo solo con <cstring>?

Salve a tutti,
il mio intento è generare delle stringhe ottenute per concatenazione di una
stringa base, diciamo a questo punto una costante stringa, ed una variabile
intera o char, in modo da generare un set di stringhe.
Es.
string s="stringa";
string temp;
e vorrei ottenere qualcosa del genere
for(int j=0; j<30; j++)
    {
    /* Qui che ci metto ??*/
    std::cout<<temp<<endl;
    }
dove il mio output è qualcosa del genere
stringa1
stringa2
stringa3
...
...
stringa20
...
e cosi via.
Per fare questa cosa posso adoperare dei particolari metodi della libreria
<cstring>?
Devo utilizzare gli array e, lavorando con questi, fare un metodo che
effettui questa concatenazione?
Es.
Se s è l'array [s][t][r][i][n][g][a][\n]
int i=4;
ottenere l'array temp [s][t][r][i][n][g][a][4][\n]
e quindi la stringa in output è:
stringa4
Grazie a chiunque mi suggerirà un metodo.
Scusate l'ignoranza!!!
Sebastiano

 wrote in message
eXN%5.6384$5k3.2...@twister2.tin.it...


     }
eccoti un esempio che usa la funzione itoa in stdlib.h
#include <iostream>
#include <string>
#include <stdlib.h>
int main ()					
{
	std::string s = "stringa";
	for(int i = 0; i < 30; i++){
		char p[3];
		itoa(i,p,10);
		std::string q = s;
		std::string n = p;
		q += n;
		std::cout << q << std::endl;
	}
	return 0; // VC++ 5.0 warning...
}

e cosi via.
Puoi procedere tranquillamente cosi'.
#include<iostream>
#include<string>
#include<iostream>
#include<stdlib>
using namespace std;
int main()
    {
    string s="stringa";
    for(int j=0;j<200;j++)
        {
        char s2[10];
        string temp=s+itoa(j,s2,10);
        cout<<temp<<"\n";
        }
    cin.get();
    return 0;
    }
Il Ghenio
-----
E'più oscuro del crepuscolo, é più rosso del sangue,
in nome della pace e della giustizia faccio appello a
tutti i poteri più remoti dell'oscurità, perché mi
aiutino a distruggere i miei nemici e tutti coloro
che saranno tanto sciocchi da ostacolarmi. FULMINE ROSSO!!
(Slayers)
-----

         itoa( val_, buff, 10);
... Mi sembra che itoa non sia standard...
E mi sembra che Sebastiano avesse bisogno di utilizzare solo le funzioni di
cstring.
Domenico Barra

 }
Forse Sebastiano voleva utilizzare solo funzioni di cstring...
Domenico Barra

 effettui questa concatenazione?
Non l'ho provato, ma a meno di errori di battitura dovrebbe funzionare; nota
che mi appoggio alla funzione sprintf, che è standard, ma non so se per te
va bene...
///////////////////////////////////////////////
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const char *cat_num(const char *,int);
int main()
{
  const char init_string[30]="Stringa ";
  for(int x=1; x<100; ++x)
    cout<<cat_num(init_string, x)<<endl;
  return 0;
}
const char *cat_num(const char *s, int i)
{
   static char st_str[100];
   static char st_num[10]; //9 cifre
   strcpy(st_str,s); //inizializzo la stringa statica
   sprintf(st_num,"%d",i); //converto in stringa
   strcat(st_str,st_num); //concateno le due stringhe
   return st_str;
}
////////////////////////////////////////////////////////
E' un listato che ho scritto di getto, quindi mi scuso per eventuali
"piccoli" errori.
Tuttavia, io opterei per le più comode e sicure stringhe del C++...
Ciao
Domenico Barra

intera o char, in modo da generare un set di stringhe.
Se stai già usando le potenti CString è inutile sbatterti in
diavolerie varie, usa CString.Format("stringa%ld",var).
Luc.
PS: il solito smarrimento in un bicchiere d'acqua?

 eccoti un esempio che usa la funzione itoa in stdlib.h
itoa non e' una funzione standard.
Un esempio corretto e' questo:
MLO@pcdf0 5 $ cat bar.cxx
#include <iostream>
#include <sstream>
using namespace std;
int main() {
  for (size_t i = 0;  i < 10;  ++i) {
    ostringstream os;
    os << "string" << i;
    cout << os.str() << endl;
  }
}
MLO@pcdf0 6 $ KCC -o bar bar.cxx && ./bar
string0
string1
string2
string3
string4
string5
string6
string7
string8
string9
MLO@pcdf0 7 $
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it
A C++ exception is when the code gets in trouble and says:
"Beam me up, Scotty!".

Scusate, ma ho tagliato meta' della risposta.
Per finire --- se il vincolo e' quello di usare SOLTANTO le funzioni
definite in <cstring>, non credo sia possibile farlo; a meno di
scrivere una procedura homebrew per la conversione da intero a string.
Il modo standard di far questo in C e' l'uso di sprintf, uso che non
dovrebbe essere permesso dal vincolo su citato.



Sono dei comandi Unix, vero? Non vanno inseriti nel listato, o mi sto
"perdendo in un bicchiere d'acqua", come al solito ? ;-)
Grazie per la risposta,
Sebastiano

 PS: il solito smarrimento in un bicchiere d'acqua?
Penso che fosse semplicemente un dubbio.
Domenico Barra

generare un codice non portabile?
Il subject del messaggio ;)
Luc.

dovrebbe essere permesso dal vincolo su citato.
CString::Format che è il wrapper della sprintf in VC++
Luc.

}
Okkio che però le performances sono rasenti lo ZERO.
Luc.

Luc <TOGL...@katamail.com-TOGLI> writes:

<cstring> e' un header standard, che corrisponde a <string.h> in C.
Le CString non so cosa siano e non voglio saperlo :-)


Le CString non so cosa siano e non voglio saperlo :-)
E' una classe tanto potente quanto NON portabile 8)))
Luc.

 > MLO@pcdf0 7 $
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
                  Comandi Unix
    ^^^^^^^^^^^^^
    Prompt di Maurizio (corrisponde a "C>" del dos)
^^^
Caratteri di citazione inseriti dal lettore delle news
Per la precisione ;-)
Ciao,
Nicola

 Okkio che perņ le performances sono rasenti lo ZERO.
Non Kredo Proprio.  Se il tuo kompilatore funziona male, buttalo :-)
Ho voluto fare un konfronto abbastanza onesto, usando lo stesso
kompilatore x un kodice C e x l'equivalente C++; il kompilatore e' gcc
2.95.2.1, kon la versione 2.90.8 della libreria standard C++: ekko i
listati
-------------------------File: bar.c
#include <stdio.h>
#define BUF_LEN 80
#define NTRIES  1000000
int main() {
  unsigned long i;
  char buffer[BUF_LEN];
  for (i = 0;  i < NTRIES;  ++i) {
    sprintf(buffer, "string%lu", i);
    /* printf("%s\n", buffer); */
  }
  return 0;
}
-------------------------File: bar.cxx
// #include <iostream>
#include <sstream>
using namespace std;
int main() {
  ostringstream os;
  const size_t ntries(1000000);
  for (size_t i = 0;  i < ntries;  ++i) {
    os << "string" << i;
    // cout << os.str() << endl;
    os.seekp(0);
  }
}
-------------------------End code
Ecco i risultati:
MLO@mlinux 20 $ gcc -ansi -pedantic -Wall -O -o bar bar.c && strip bar && time ./bar
real	0m2.416s
user	0m2.410s
sys	0m0.000s
MLO@mlinux 21 $ g++ -ansi -Wall -O -fhonor-std -o bar bar.cxx && strip bar && time ./bar
real	0m2.260s
user	0m2.250s
sys	0m0.010s
I tempi, come vedi, sono praticamente uguali: ED IL CODICE C++ E' PIU'
VELOCE DI QUELLO C.
Kosa ne pensi, karo?


Kosa ne pensi, karo?
Penso che hai spostato "ostringstream os;" fuori dal ciclo for... era
quello che avrebbe rallentato il tutto... 8)
PS: Odio quelli che scrivono con la 'k' 
^___^
PS2: Lo so, ho cominciato io... 8/
Luc.

Wow, come č animata questa discussione. O io faccio domande carine o faccio
domande cretine... ogni volta simpaticamente rispondete in molti.
:-))
Bye,
Sebastiano

 listati
Cavolo, hai ragione! Ho provato anch'io il mio codice (vedi un mio
messaggio precedente) con il DJGPP e la situazione si è quasi capovolta.
Ma andiamo per gradi. Prima ho tirato fuori dal loop la definizione
dell'ostringstream ed ho ottenuto un miglioramento anche con il BCC55.
Ora ci mette la metà rispetto alla versione con la dichiarazione
all'interno, ma la versione con sprintf() è sempre più veloce di circa
cinque volte. Ho poi portato questo codice così modificato sul DJGPP e
la versione C++ risulta veloce il doppio rispetto a quella C! Veramente
incredibile. Ma è possibile una cosa del genere?
EMG

 Okkio che però le performances sono rasenti lo ZERO.
In effetti ho fatto la seguente prova con il BCC55
#include <iostream>
#include <sstream>
#include <cstdio>
#include <ctime>
int main()
{
    std::clock_t start = std::clock();
    for ( size_t i = 0; i < 10000; ++i )
    {
        std::ostringstream os;
        os << "string" << i;
    }
    std::cout << "Ticks impiegati: " << ( std::clock() - start ) <<
std::endl;
    start = std::clock();
    for ( size_t i = 0; i < 10000; ++i )
    {
        char buf[ 100 ] = "";
        std::sprintf( buf, "string%d", i );
    }
    std::cout << "Ticks impiegati: " << ( std::clock() - start ) <<
std::endl;
    return 0;
}
e la differenza è veramente notevole, praticamente quasi un ordine di
grandezza. :-(
EMG

 Il subject del messaggio ;)
Scherzi, vero? "cstring" è l'header standard C++ corrispondente a "string.h"
del C. Quindi niente CString Micro$oftiane.
Domenico Barra

Non è standard, mi pare... anzi ne sono certo.
Non sapevo che si trattasse di una funzione non standard, anche se
vista la sua scarsa funzionalità io non l'ho mai usata nei miei
programmi. Per contro credo che neanche sprintf sia una buona
soluzione al problema, e se proprio uno vuole restare fedele allo
standard farebbe molto meglio a scriversi da solo una funzione che
converte valori numerici in una stringa. Io per esempio tempo fa ho
scritto una funzione come questa:
template <class T> string DecToStr(T intero)
    {
    //Converte un tipo numerico in una std::string.
    int cifre=10;
    string res="";
    if(intero<0){res="-";intero=abs(intero);}
    while(intero<pow(10,cifre-1) && cifre>1)cifre--;
    vector<char>totcifre(cifre);
    int ccalc=cifre;
    while(intero>=10 || ccalc>0)
        {
        int cont=0;
        while(intero>=pow(10,ccalc-1))
            {
            intero-=pow(10,ccalc-1);
            cont++;
            }
        ccalc--;
        totcifre[ccalc]=cont;
        }
    for(int x=totcifre.size()-1;x>=0;x--)res+=totcifre[x]+48;
    return res;
    }
Se a qualcuno interessa é libero di provarla, ma sappia che obbliga ad
includere
#include<string>
#include<iostream>
#include<cstdlib>
#include<vector>
#include<cmath>
se puoi qualcuno ha qualche idea per migliorarla si faccia sentire.



<MEGA-CUT>
Caspita! Ma ne avete di tempo da perdere quando programmate... 8)

 se puoi qualcuno ha qualche idea per migliorarla si faccia sentire.
Prova questa: è la tua funzione con qualche piccola revisione (si potrebbe
fare ancora qualcos'altro, ma già così chiarezza e velocità sono buonine
secondo me): ha bisogno solo di <string> e di <cmath>, ed è un po' più
veloce (seguono test):
//////////////////////////////////////////////////////////
#include <string>
#include <cmath>
using namespace std;
string dectostr(int intero)
{
  static char totcifre[10];
  string res="";
  int cifre = 10;
  if (intero<0) { res="-"; intero = -intero; }
  while (intero<pow(10,cifre-1) && cifre>1) --cifre;
  int ccalc = cifre;
  while (intero>=10 || ccalc>0)
  {
   int cont = 0;
   while (intero>=pow(10,ccalc-1))
   {
    intero -= (int) pow(10,ccalc-1);
    ++cont;
   }
   --ccalc;
   totcifre[ccalc]=cont;
  }
  for(int x=cifre-1; x>=0; --x) res+=totcifre[x]+48;
  return res;
}
//////////////////////////////////////////////////////
Ecco i tempi di risposta:
[domenico@localhost domenico] g++ prova.cpp -o prova -O3
[domenico@localhost domenico] prova > exec_log
[domenico@localhost domenico] cat exec_log
Per 50000 chiamate:
Timediff with DecToStr: 1810000
Timediff with dectostr: 1700000
Per 100000 chiamate:
Timediff with DecToStr: 3940000
Timediff with dectostr: 3760000
Per 200000 chiamate:
Timediff with DecToStr: 8130000
Timediff with dectostr: 7770000
Per 500000 chiamate:
Timediff with DecToStr: 21540000
Timediff with dectostr: 20660000
Per 2000000 di chiamate:
Timediff with DecToStr: 95970000
Timediff with dectostr: 92500000
[domenico@localhost domenico]
Ciao :-)
Domenico Barra

 ... Mi sembra che itoa non sia standard...
è vero, sorry... nuova versione:
#include <string>
#include <iostream>
#include <strstream>
using namespace std;
class int2string
{
    int val_;
    string ret_;
public:
    int2string( int val): val_( val)
    {
        strstream stream;
        stream << val_;
        stream >> ret_;
    }
    operator string()    {    return ret_;}
};
int main()
{
 string s = "stringa";
 for( int i = 0; i < 30; ++i)
  cout << ( s + static_cast< string>( int2string( i))) << endl;
}
questa cos'ha che non va? ;)

 se puoi qualcuno ha qualche idea per migliorarla si faccia sentire.
Stasera, giocherellando con il problema della conversione da intero a
stringa, mi è venuto in mente di scrivermene ex novo una tutta mia. Non l'ho
ancora ottimizzata, ma penso che più o meno ci siamo già: rispetto alla
funzione "da migliorare" è tra 11.2 e 12 volte più veloce...
Eccola qui (si appoggia a due funzioni inline :-)) :
/********************************************************
 const char *inttostr(int);
 Takes an integer value and converts it to a string
 Version 0.1 21.12.2000 Domenico Barra
*********************************************************/
#include<iostream>
inline long pow_10(int i)
{
 switch (i)
 {
  case 0 : return 1L;
  case 1 : return 10L;
  case 2 : return 100L;
  case 3 : return 1000L;
  case 4 : return 10000L;
  case 5 : return 100000L;
  case 6 : return 1000000L;
  case 7 : return 10000000L;
  case 8 : return 100000000L;
  case 9 : return 1000000000L;
 }
 return 0L;
}
inline char to_char(char i)
{
 switch(i)
 {
  case 0: return '0';
  case 1: return '1';
  case 2: return '2';
  case 3: return '3';
  case 4: return '4';
  case 5: return '5';
  case 6: return '6';
  case 7: return '7';
  case 8: return '8';
   case 9: return '9';
 }
 return i+48;
}
const char * inttostr(int value)
{
 static char result [12];
 static char table  [10];
 int position = 0;
 int digits = 10;
 if (value<0) { value = -value; result[0]='-'; position=1; }
 for (long x=1000000000L; x>1; x/=10)    // checks the digits
   if (value<x) --digits; else break;
 register int temp;
 for (int x=digits-1; x>=0; --x)
 {
  temp = pow_10(x);
  table[x] = value/temp;
  value -= table[x]*temp;
 }
 while(digits>0) result[position++] = to_char(table[--digits]);
 result[position]='\0';
 return result;
}
///////////////////////////////////////////////////////////////////
Rispetto a quella che ho postato stamattina è un fulmine ...
Ciao
Domenico Barra

"Simone F" <x...@xxx.xx> ha scritto nel messaggio
news:Vcv06.156695$hk4.5...@news.infostrada.it...

E' ok, ma ho un dubbio (vedi dopo); tuttavia, se la tua standard library è
aggiornata, ti consiglio di utilizzare stringstream anziché strstream.
Un dubbio: strstream non ha bisogno di un array di base?
Ciao
Domenico Barra

 #include<iostream>
Sorry, non ci vuole, l'avevo inclusa per il debug :-)
E cosě, non richiede l'inclusione di alcun header.
Domenico Barra

 }
Sei sicuro di poterlo fare?
Supponi di chiamare una funzione (const char*) usando
come parametro inttostr(532) e questa funzione usa
anche lei inttostr prima di utilizzare il parametro...

 ha scritto nel messaggio
news:3A4377B0...@libero.it...

Poterlo fare, come vedi si puň fare.
Certo, questo č uno svantaggio della restituzione di un membro static, a cui
si puň facilmente porre rimedio copiando il risultato in una std::string o
in un altro array; nota tuttavia che la restituzione di un puntatore
costante a un membro static č pratica abbastanza comune, anche nella
libreria standard del C. Per risolvere il problema, in C++, si potrebbe
restituire direttamente una std::string, ma cosě com'č la funzione:
1. E' sia C sia C++
2. Non dipende da alcun header (era anche questo che si voleva, no?)
In alternativa, si potrebbe rendere la funzione:
void inttostr (int value, char *string);
copiando direttamente in string il risultato, ma ritengo che sia ugualmente
pericoloso, se non di piů.
Ciao
Domenico Barra

 Un dubbio: strstream non ha bisogno di un array di base?
no, c'è anche il costruttore di default che inizializza un oggetto
strstreambuf chiamando il suo costruttore di default. Questa però è
l'implementazione del BC55, ed ora che ci faccio caso dice che "This
is a deprecated feature and might not be available in future
versions.". Come mai? cosa dice lo standard?

Rispetto a quella che ho postato stamattina è un fulmine ...
Sicuramente, anche se bisogna dire che la mia funzione era ancora
ampiamente da ottimizzare.
Il Ghenio
WINWORD.EXE - ERRORE DI APPLICAZIONE
l'istruzione a "0x3017ff27"ha fatto riferimento alla
memoria a "0x02a3143c".La memoria non poteva essere 'read'.

 ampiamente da ottimizzare.
Certo, non voglio dire che il lavoro che hai fatto tu non sia da apprezzare
(scusami se ti ho dato questa impressione), anzi ti confesso che mi sono
ispirato a quello per la scrittura della mia. Solo, sono convinto che in
alcuni ambiti alle features di alto livello del C++ (come le stringhe e i
vettori) sia da preferire il classico array e l'operazione di basso livello.
D'altra parte, le dimensioni massime dell'array erano conosciute, e un array
che occupa si e no 12 byte, sul quale non devo eseguire complesse operazioni
di ricerca, è ben meglio di un vector o di una string di cui devo chiamare
il costruttore, il distruttore, l'allocatore e tutti gli annessi e connessi.
Ciao, e Buon Natale (sono le 2.35 del 25.12.2000)
Domenico Barra

return i+48;
Però non è portabile; non è detti che il sistema usi il codice ASCII;
al limite secondo me sarebbe meglio 
return i+'0';
purtroppo anche in questo caso non è portabile, perchè nessuno ci
assicura che i caratteri che rappresentano le cifre siano disposti in
ordine uno di seguito all'altro. La soluzione più portabile è
sicuramente quella con lo switch.
Cmq non ho capito una cosa: perchè hai messo sia lo switch che il
return i+48? Secondo me sarebbe più logico sollevare un'eccezione se
la cifra non è compresa tra 0 e 9.
Ciao Anto

 la cifra non è compresa tra 0 e 9.
Mah, volevo sviluppare una funzione semplice semplice, non ho pensato alla
gestione delle eccezioni. Dato che 'to_char' è usata solo da 'inttostr', e
che inttostr era solo un 'giocattolo', non mi è sembrato valesse la pena
dotarla di una gestione delle eccezioni intelligente... il 'return i+48' che
si trova alla fine poteva andare anche sotto l'etichetta 'default': era una
cosa messa lì, tanto per esserci, anche perché è molto improbabile che
to_char venga chiamato con un numero minore di 0 e maggiore di 9.
Ciao
Domenico Barra

 Rispetto a quella che ho postato stamattina è un fulmine ...
beh, mangiate la polvere con questo, polli ( sul mio sistema è + del
doppio
veloce) ;))
#include <string>
#include <iostream>
class int2str
{
 char *ptr_;
 char buff_[ 20];
 static const char values_[];
public:
 int2str( int val): ptr_( buff_ +19)
 {
  *ptr_-- = '\0';
  do
  {
   *ptr_-- = values_[ val % 10];
   val /= 10;
  } while ( val);
 }
 operator std::string() { return ptr_+1;}
};
const char int2str::values_[] = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9'};

 veloce) ;))
Coff, coff... beh, in effetti sul mio sistema l'istanziazione di x oggetti
int2str č 3 volte piů veloce di x chiamate a inttostr.
Tuttavia, avrei da fare un paio di considerazioni:
1. Quando vai a richiedere l'output, il rallentamento č evidente... la
velocitŕ diventa la stessa di inttostr (sul mio sistema ci impiega
addirittura un po' in piů). In pratica: la mia soluzione perde tempo nel
calcolo, la tua nella restituzione dell'output.
2. E' improbabile beccare degli interi a 20 cifre...
3. E' improbabile beccare solo interi positivi (a meno che non siano
unsigned)
[conta a tuo sfavore il tempo che impiegheresti nel trattare gli interi
negativi] :-))).
A conti fatti, come efficienza inttostr č ancora migliore di questa versione
primitiva di int2str.
Tutto sommato, con qualche miglioria, la tua soluzione č da considerarsi piů
valida della mia, ed č anche piů C++ (anche se io avevo pensato ad una
funzione che potesse essere sia C che C++, quindi l'idea dell'uso di una
classe non mi aveva neppure sfiorato :-)).
Ciao
Domenico Barra

 valida della mia, ed è anche più C++ (anche se io avevo pensato ad


Kosa ne pensi, karo?
Io continuo a sospettare che la libreria standard fornita con i
compilatori Borland sia ampiamente da ottimizzare in quanto a
prestazioni.
Lavinia
