Newsgroup: it.comp.lang.c++
Titolo: std::transform

salve a tutti,
qualcuno sa dirmi perché non mi viene compilata la seguente riga:
transform(input.begin(), input.end(), tolower);
inserita in questo contesto:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <cctype>
using namespace std;
void StampaOccorrenze(const int[]);
int main() {
    int occorrenze[26] = { 0 };
    string input;
    cout << "Inserire il testo da analizzare (CTRL-Z per terminare)." <<
endl;
    getline(cin, input, static_cast<char>(EOF));
    transform(input.begin(), input.end(), tolower);
    for(string::iterator iter = input.begin(); iter != input.end(); ++iter)
{
        if(isalpha(*iter))
            occorrenze[*iter - 96] += 1;
    }
    StampaOccorrenze(occorrenze);
    cin.clear();
    cout << endl << "Premere INVIO per continuare..." << endl;
    while(cin.get() != '\n');
    return 0;
}
eppure l'utilizzo di transform dovrebbe essere quello...
ah, un'altra domanda, un po' OT.
utilizzando getline, che carattere di terminazione posso usare se mi
interessa,
come in questo caso, che possano essere inserite più righe?
qui ho usato EOF, ma è sbagliato. infatti chiedo di inserire ctrl+z per
terminare,
e poi utilizzo cin.clear() per potere eseguire l'ultimo ciclo while.
TIA,
--
Lupin85©
Azzurranet IRC: @#afiad, @#fils, @#pokegalaxy - ICQ: 91528290
Mail: Remove PAN to contact me
- "It is not important what you believe, only that you believe." -

 infatti chiedo di inserire ctrl+z ...
Beh, ctrl-z e' Micro$oft; in Unix e' ctrl-d.  Chiedi di inserire
EOF tout court...
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy          loreti at pd dot infn dot it

 una delle righe alla volta, fino all'EOF (o all'errore di lettura :-)
ottima idea, grazie mille! :)


 transform(input.begin(), input.end(), tolower);
se non ci dici quale e` l'errore e` un po' difficile indovinarlo, non 
credi?
Cmq una cosa simile era capitata anche a me: probabilmente il problema 
deriva dal fatto che tolower e` definita come macro dal tuo compilatore, 
per cui transform non la accetta; se scrivi std::tolower non dovrebbero 
esserci problemi.
Nota che il tuo codice e`, a norma di standard, corretto: se il problema 
e` quello che ho ipotizzato e` un bug del compilatore: lo standard C 
permetteva di scegliere se implementare tolower & C. come funzioni o 
come macro, ma lo standard C++ obbliga ad implementarle come funzioni.
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra

 credi?
hai ragione...
ecco l'errore (correggendo tolower in std::tolower):
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> > >,
    <unknown type>)'
ho provato a fare come ha consigliato il prof. Loreti, utilizzando la forma
transform(input.begin(), input.end(), input.begin(), std::tolower), ma
ottengo questo errore (molto simile al precedente):
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> > >,
   __gnu_cxx::__normal_iterator<char*, std::basic_string<char,
   std::char_traits<char>, std::allocator<char> > >,
   <unknown type>)'
non riesco proprio a capire...
ormai è una questione di principio. anche perché ho risolto il problema
prima di scrivere il messaggio, scrivendo una mia tolower che accetta una
stringa.
ora ho provato scrivendo una funzione proxy per tolower, e passandola a
transform non ho problemi.
forse è un problema del compilatore..
tu che compilatore usi? hai provato a compilare il mio codice?
io uso il gcc 3.2
grazie mille!


    std::char_traits<char>, std::allocator<char> > >,
L'errore e' dovuto al fatto che tolower e' una macro.  So che esistono
modi di costringere il compilatore ad usare una funzione al posto
della macro, ma non ho sottomano documentazione dove sono adesso...
Comunque, aggiungento un altro livello, tutto funziona:
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
struct myTolower {
  char operator() (char c) { return tolower(c); }
};
struct myToupper {
  char operator() (char c) { return toupper(c); }
};
int main() {
  string s( "AbCdEf" );
  cout << "String: \"" << s;
  transform(s.begin(), s.end(), s.begin(), myTolower());
  cout << "\"; lowered: \"" << s;
  transform(s.begin(), s.end(), s.begin(), myToupper());
  cout << "\"; uppered: \"" << s << "\".\n";
}
Il trucco e' di creare un function object che richiami la macro.
Grazie alla Dea il tutto viene espanso inline e ne' le dimensioni del
codice ne' il tempo di esecuzione ne risentono.


 };
[snip]
Ho risolto in maniera simile, creando una funzione inline che richiama
tolower.
Certo, questa soluzione è decisamente più elegante... :)
