Newsgroup: it.comp.lang.c++
Titolo: convertire stringa

salve, il mio problema è convertire una stringa, tutta in minuscolo; giro in
internet e trovo le funzioni
.toUpperCase e .toLowerCase;  provo a creare un programmino cazzuto, ma
niente, il compilatore non mi riconosce queste
due funzioni, .....dove sbaglio?
il programmino include gia la classe string, e non trasformo la stringa
stessa in minuscolo ma assegno la stringa minuscola ad un altra stringa:
.....
.....
string c="HALLO"
string ss=c.touppercase();
...
...

 ....
il compilatore non ti riconosce quelle due funzioni perchè non esistono,
almeno non nelle implementazioni standard. Dove le avresti viste queste
due funzioni? Ricorda poi che, in generale, toUpperCase e touppercase
(come hai scritto nel codice) sono due funzioni diverse (il C++ è
case-sensitive).
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 wrote in message
news:7a_H9.47999$qF1.1...@news2.tin.it...


 wrote in message
news:7a_H9.47999$qF1.1...@news2.tin.it...


..nn so che dire...ho riguardato il file pdf che avevo scaricato, premetto
che non conosco il java, ma se il testo che ho letto è scritto in java, è
molto simile al c++( se nn ci credete vi invio il file in questione); cmq so
che il c++ è case sensitive, allora diciamo che riformulo la domanda:
ho una stringa, e la devo convertire tutta in minuscolo; come faccio?
grazie ciao

 wrote in message
news:7a_H9.47999$qF1.1...@news2.tin.it...


 minuscolo; come faccio? grazie ciao
#include <string>
#include <cctype>
#include <algorithm>
#include <iterator>
#include <iostream>
int main()
{
  std::string s = "PROVA";
  std::string res;
  std::transform(s.begin(), 
                 s.end(), 
                 std::back_inserter<std::string>(res), 
                 std::tolower);
  std::cout << res << std::endl;
}
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra

                  std::tolower);
Vorrei far notare che il gcc 3.2 non compila questo codice.
A std::tolower bisogna sostituire std::ptr_fun(::tolower).
--
Andrea Spadaccini - Catania (Italy)
Mail: _
lupin85...@libero.it
ICQ#: 91528290
 - It is not important what you believe, only that you believe -

 }
Per le iterazioni nelle std::string e, in generale, nei container
STL, č preferibile usare gli std::iterator.
Comunque la soluzione di Antonio č decisamente piů raffinata.


 A std::tolower bisogna sostituire std::ptr_fun(::tolower).
Ma, secondo lo standard, ha ragione il gcc32 o Cuni?
--
Gerolamo

 A std::tolower bisogna sostituire std::ptr_fun(::tolower).
si, lo so bene dato che io uso proprio g++, ma ho deciso di postarlo lo 
stesso perche` in ogni caso secondo lo standard e` (o meglio dovrebbe, 
se non sono io a fare ca**ate) corretto.


 se non sono io a fare ca**ate) corretto.
Mi spiace, ma il g++ fa molto bene ad avere problemi con questo
codice.
Primo: in genere le librerie standard C definiscono tolower come una
macro, che viene espansa inline dentro transform() - mentre questa si
aspetta come terzo argomento una "unary function".
Secondo, e piu' importante: lo Standard C definisce tolower come "int
tolower(int)", con la clause che il valore dell'argomento deve o
essere EOF o essere rappresentabile da un unsigned char (altrimenti,
undefined behavior); mentre gli iteratori di std::string, una volta
dereferenziati, ti danno un char.  Poco male, dici tu: a tradurre il
char in int ci pensano le regole di conversione implicite.  Ed ecco
scattare la trappola: ad esempio \377 e' un carattere validissimo
nell'encoding ISO-8859-1; in ambienti dove un char ha 8 bits ed e' di
default signed, \377 viene promosso ad intero con valore -1, il che e'
sbagliato.
L'unico modo di usare le funzioni definite in <cctype> correttamente
e' per prima cosa testare l'argomento per EOF (in questo caso e'
inutile) e poi fare un cast a unsigned char.
Per questo motivo, la soluzione del problema di partenza e' quella di
aggiungere un altro livello di astrazione (e' cosi' del resto che si
risolve la maggior parte dei problemi in C++ :-):
,-----
| struct lower {
|   unsigned char operator() (unsigned char c) { return tolower(c); }
| };
|
| ...
|
| transform( s.begin(), s.end(), s.begin(), lower() );
`-----
Il wrapper di tolower viene espanso inline, e non cambia le dimensioni
del codice generato.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy              ROT13: 
ybe...@cq.vasa.vg

 sbagliato.
questo non lo sapevo. In ogni caso puo` essere vero in generale (e 
sicuramente lo terro` presente in futuro), pero` l'esempio da me postato 
non rientra nell'undefinded behaviour: tutti i caratteri della stringa 
di esempio sono tranquillamente convertibili in unsigned char, per cui 
l'undefined behaviour "non s'ha da fare".
Tanto piu` che l'errore del g++ probabilmente e` proprio di considerare 
tolower come una macro; ecco l'errore
ccprova.cc:10: no matching function for call to `transform(
   __gnu_cxx::__normal_iterator<char*, std::basic_string<char,
   std::char_traits<char>, std::allocator<char> > >,
   __gnu_cxx::__normal_iterator<char*, std::basic_string<char,
   std::char_traits<char>, std::allocator<char> > >,
   std::back_insert_iterator<std::string>, <unknown type>)'
come puoi vedere secondo g++ l'ultimo argomento e` di tipo <unknown 
type>, ma se tolower fosse una funzione il compilatore saprebbe quale e` 
il tipo; infatti se provi ad aggiungere
int foo(int) {} // stesso tipo di std::tolower
passando foo a std::transform g++ non si lamenta piu`.
IMHO e` g++ che sbaglia, implementanto tolower come una macro quando lo 
standard richiederebbe una funzione.


 il tipo
Non e' che invece g++ non sa scegliere tra i due overload di tolower,
quello di <cctype> e quello di <locale>?
Ciao,
Nicola

 quello di <cctype> e quello di <locale>?
Penso proprio che tu abbia ragione: sinceramente non mi ricordavo neppure 
di un tolower definito in <locale>. In effetti provando questo codice 
che simula la situazione da te descritta:
template<class T> void foo(T) {}
void bar() {}
void bar(int) {}
int main()
{
  foo(bar);
}
ottengo lo stesso errore:
ccprova.cc:9: no matching function for call to `foo(<unknown type>)'
Questa cosa pero` mi pare un po' "inquietante": facendo un po' di prove 
ho scoperto che <locale> e` incluso da <iostream>; questo significa che 
questo sorgente compila tranquillamente:
#include <cctype>
template<class T> void foo(T) { }
int main()
{
  foo(std::tolower);
}
Ma se provo ad aggiungere #include <iostream> il compilatore riporta il 
solito errore: e` possibile che l'inclusione di un header "innocuo" 
faccia diventare il mio codice da corretto a non compilabile? 
Evidentemente la risposta e` "si", pero` IMHO e` una pitfall non da 
poco.
