|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Aug 2002
Messaggi: 3983
|
[C++]elementi uguali in una string
Ciao!!
Se ho una string con questi nomi: pino, andrea, peppe, luca, andrea, vito, peppe, pino, peppe. quale potrebbe essere la funzione che ricerca i nomi nell'array e mi restituisce ci sono numero 2: pino ci sono numero 2: andrea ci sono numero 3: peppe ecc ecc esiste anche una funzione che possa ordinarli (tutti gli elementi) e visualizzarli in ordine alfabetico? quale? grazie |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Codice:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string str;
char buf[4096];
cin.getline(buf, 4096); //leggo una riga dallo stdin
str = buf;
int start = 0, end = -1;
vector <string> v;
while(1)
{
start = str.find_first_not_of(' ', end+1); //tolgo gli spazi
end = str.find_first_of(',', start); //trovo la virgola
if(end == string::npos) //fine della stringa raggiunto
{
v.push_back(str.substr(start, string::npos)); //aggiungo l'ultimo
break;
}
v.push_back(str.substr(start, end-start)); //aggiungo un elemento
}
sort(v.begin(), v.end()); //ordino il vettore
//ed ora contiamo
int num = 1;
for(int i=1; i<v.size(); ++i)
{
if(!v[i].compare(v[i-1])) //è uguale al precedente ?
num++;
else //se è diverso
{
cout << num << " " << v[i-1] << endl;
num = 1;
}
}
cout << num << " " << v[i-1] << endl;
return 0;
}
|
|
|
|
|
|
#3 | ||
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Re: [C++]elementi uguali in una string
Quote:
Codice:
#include <map>
using namespace std;
map<string,int> count;
for ( int i=0 ; i< size ; ++i )
count[ array[i] ] ++;
for ( map<string,int>::const_iterator i=count.begin() ; i != count.end() ; ++i )
{
cout << "ci sono numero " << i->second << ": " << i->first << endl;
}
Quote:
nel primo caso puoi fare Codice:
#include <algorithm> std::sort( array , array+size); Se ti interessa invece ordinare l'uscita delle occorrenze con la map sei a post perche' di default le stringhe vengono ordinate alfabeticamente. Nel caso improbabile che cio' non avvenga puoi copiarle temporaneamente in un vettore e fare l'output da li': Codice:
#include <vector>
using namespace std;
...
vector< pair<string,int> > tmp( count.begin() , count.end() );
sort( tmp.begin() , tmp.end() );
for( unsigned int i=0 ; i<tmp.size() ; ++i )
{
cout << "ci sono numero " << tmp[i].second << ": " << tmp[i].first << endl;
}
|
||
|
|
|
|
|
#4 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Se invece i nomi effettivamente li hai in una stirng unica puoi fare cosi' per la conta:
Codice:
#include <sstream>
#include <map>
#include <string>
using namespace std;
string nomi = ...
map<string,int> count;
istringstream in(nomi);
string buf;
while( in >> buf )
{
count[ buf ] ++;
}
P.S.: cionci, ma una volta il tag [ code ] mi sembra ignorasse qualunque tag al suo interno o sbaglio ? Ora non piu'... sai se si puo' fare qualcosa ? |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Azz...non avevo pensato ad usare stringstream...che deficiente che sono...anche l'idea del map è forte !!!
Probabilmente li ignorava in phpBB |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Aug 2002
Messaggi: 3983
|
ok vi faccio sapere
grazie!!!! |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Aug 2002
Messaggi: 3983
|
..allora
intendevo dire che devo inserire i nomi in un array e al posto del char[] usare string (scusate è colpa mia, pasticcio ancora con le terminologie del linguaggio) ad esempio per farmi capire ho questa funzione che acquisisce i nomi: .... void leggifam(string *famiglie,int numelementi) { for (int riga = 0; riga < numelementi; riga++) { cout << "Inserisci il nome #" << riga+1 << " "; cin.getline(responso,256); famiglie[riga] = responso; } } e devo poi ricercare gli identici come spiegato sopra (quindi parliamo di un array di stringhe. giusto o mi sbaglio?) nel codice di Cionci si parla di virgola, quindi se ho capito bene si riferisce a nomi inseriti nello stesso array separati da una virgola. Non è poprio quello che volevo (ripeto: per colpa mia!!!!) ma mi interessa comunque; a proposito la penultima parentesi (quella del ciclo for) deve essere messa dopo l'ultimo cout. Scusami Marco, forse hai centrato il problema, ma io (essendo ancora mooooolto ingnorante in materia) non riesco a mettere adeguatamente insieme le parti di codice da te postate (ricevendo sempre messaggi di errore dal compilatore). Potresti, gentilmente, postarmi il codice (adesso penso che tu abbia capito la mia esigenza di cui sopra: ricerca>conteggio>ordinamento alfab. e visualizzazione ovviamente) completo comprensivo del main magari anche un po' commentato. Grazie e ciao |
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Come ti ha detto /\/\@®¢Ø, la struttura + adatta da utilizzare è un map: Codice:
void leggifam(map<string,int> &famiglie, int numelementi)
{
for (int riga = 0; riga < numelementi; riga++)
{
cout << "Inserisci il nome #" << riga+1 << " ";
cin.getline(responso,256);
famiglie[string(responso)]++;
}
}
|
|
|
|
|
|
|
#9 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Ecco una possibile implementazione:
Codice:
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
void leggifam(string *famiglie,int numelementi)
{
string responso;
for (int riga = 0; riga < numelementi; riga++)
{
cout << "Inserisci il nome #" << riga+1 << " ";
// usando una getline con le string evitiamo il rischio di sforare l'array di caratteri
getline( cin , responso);
famiglie[riga] = responso;
}
}
int main()
{
int numelementi;
cout << "Inserisci il numero di elementi " << endl;
cin >> numelementi;
string s;
// Questo serve solo per "finire" la riga
getline( cin , s );
// Leggi le famiglie
string* famiglie = new string[numelementi];
leggifam( famiglie , numelementi );
// Conta le occorrenze di ogni nome.
// Questo sfrutta il fatto che se un nome non e' ancora presente nella mappa
// allora gli viene associato il valore di default degli interi (0)
map<string,int> count;
for ( int i=0 ; i<numelementi ; ++i )
{
count[ famiglie[i] ]++;
}
// La mappa tiene le chiavi ordinate. Visto che di default l'ordine e' quello alfabetico
// non abbiamo alcun bisogno di ordinare a mano i nomi.
// Le informazioni vengono memorizate in coppie <chiave,valore> con l'uso della
// struttura pair<string,int> . Di conseguenza possiamo accedere alla chiave (il nome)
// dall'iteratore con i->first e al valore (le occorrenze) con i->second
cout << "Ci sono:" << endl;
for ( map<string,int>::const_iterator i=count.begin() ; i != count.end() ; ++i )
{
cout << i->second << ' ' << i->first << endl;
}
}
|
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Aug 2002
Messaggi: 3983
|
Quote:
li invece che dopo il cout il codice semplicemente non si compila. Anche se poi il programma non fa esattamente quello che mi aspetto forse dovuto a questo boh? es: ciccio, andrea, ciccio, andrea, peppe 2 andrea qual'è il problema? grazie |
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Non so cosa dirti...a me funziona benissimo...
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Aug 2002
Messaggi: 3983
|
Grande Marco, mi serviva proprio una cosa del genere!!
Un ultima cosa sul tuo codice completo: per visualizzare solo i nomi che compaiono piu di una volta(o 2, 3 ecc) ho aggiunto: cout << "Ci sono:" << endl; for ( map<string,int>::const_iterator i=count.begin() ; i != count.end() ; ++i ) { if((i->second)>1){ cout << i->second << ' ' << i->first << endl; } } ma non so come eliminare il "ci sono" se la condizione non è soddisfatta (voglio dire: non voglio che compaia il "ci sono" quando ad esempio c'è una sola occorrenza per nome) cosa devo aggiungere? Sto cercando di far funzionare anche il codice di Cionci, (per il momento uso la versione di marco per i nomi inseriti in una sola stringa) altrettanto interessante, ma il mio Dev mi segnala sempre un errore in quets riga: cout << num << " " << v[i-1] << endl; di tipo "name" in dettaglio nel log: stringa.cpp:46: name lookup of `i' changed for new ISO `for' scoping problema di include?? Boh?? ..poi avete parlato in merito all'uso delle stringhe di: vector, map, istringstream e funzioni tipo i=count.begin(), di i->second ecc Io ho un libro sul c++ (base) ma di tutte queste cose non ne parla e, a quanto pare sembrano necessarie per gestire le stringhe senza diventare matti e incominciare a fare sul serio con il c++. Per il momento non voglio comprare un altro libro (sono al verde!!), potete consigliarmi dei siti (possibilmente in italiano) che spiegano queste cose in maniera accessibile per un neofita? grazie ancora |
|
|
|
|
|
#13 | ||
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Quote:
Codice:
// dichiarata prima dell'altra funzione
bool mult( const pair<string,int>& x )
{ return x.second > 1 ; }
...
// Prima leggi la mappa...
// Ora teniamoci le occorrenze multiple
int n = count_if( count.begin() , count.end() , &mult );
if ( n == 1 )
{ cout << "C'e'" << /* come hai gia' fatto */
else
{
cout << "ci sono" << /* come hai gia' fatto */
}
...
Quote:
|
||
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Thinking in C++ di Bruce Eckel...cercalo su intenet...
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Aug 2002
Messaggi: 3983
|
un' ultima cosa per concludere l'argomento.
ecco due pezzi di codice il primo: Codice:
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
int main()
{
const int QUANTISONO = 10;
int rilev = 0;
char responso[256];
string nomi[QUANTISONO];
for (int riga = 0; riga < QUANTISONO; riga++)
{
cout << "Inserisci il nome #" << riga+1 << " ";
cin.getline(responso,256);
if(cin.eof()) break;
nomi[riga] = responso;
rilev++;
}
cout << endl << "I "<<rilev<<" nomi che hai inserito sono: " << endl;
for (int riga = 0; riga < QUANTISONO; riga++)
{
cout << nomi[riga] << endl;
}
map<string,int> count;
for ( int i=0 ; i<rilev ; ++i )
{
count[ nomi[i] ]++;
}
cout << "Ci sono nei "<<rilev<<" nomi inseriti:" << endl;
for ( map<string,int>::const_iterator i=count.begin() ; i != count.end() ; ++i )
{
if((i->second)>1){
cout << i->second << ' ' << i->first << endl;
}
}
cout<<endl;
system ("PAUSE");
return 0;
}
if(cin.eof()) break; (sul miol sistema si deve inserire Ctrl+z) vorrei che il ciclo possa essere interrotto anche con il semplice invio (cioè quando a un tot numero non si vuole inserire più nomi e si da l'invio) come si fa? secondo codice: Codice:
#include <iostream>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <iomanip>
#include <string>
using namespace std;
typedef string::const_iterator It;
int count_words( const string& s )
{
int count,i=0;
while ( true )
{
while( i < s.size() && s[i]==' ')
++i;
if ( i == s.size() ) break;
while( i < s.size() && s[i] != ' ')
++i;
count++;
}
return count;
}
int main()
{
string nomi;
cout<<"Inserisci i nomi da conteggiare separati da uno spazio:"<<endl<<endl;
getline( cin , nomi );
map<string,int> count;
istringstream in(nomi);
string buf;
while( in >> buf )
{
count[ buf ] ++;
}
cout<<"parole: "<<count_words(nomi);
cout << endl;
cout << "ci sono numero: "<<endl;
for ( map<string,int>::const_iterator i=count.begin() ; i != count.end() ; ++i )
{
cout<< setw(16) << i->second << ": " << i->first << endl;
}
cout<<endl;
system ("PAUSE");
return 0;
}
e per fare il conteggio totale delle parole (nomi)utilizzo una funzione che mi fu suggerita, se ricordo bene, sempre da marco). Ma c'è qualcosa che non va (il numero totale dei nomi) in console ecco il risultato: Inserisci i nomi da conteggiare separati da uno spazio: ciccio pino ciccio pino andrea numero nomi: 2293341 ci sono numero: 1: andrea 2: ciccio 2: pino qual'è il problema? esiste un metodo migliore per fare il conteggio totale che mi sfugge? |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:21.



















