prof. Nunzio Brugaletta
C++: programmazione e oggetti

EnneBi - Programmazione
Avanti - Indietro - Inizio

Stringhe: esempi di utilizzo dei metodi della classe

Il primo programma proposto acquisita da input una stringa contenente cognome e nome separati da uno spazio, estrae il cognome, il nome e genera una nuova stringa con i dati in ordine inverso (prima il nome e poi il cognome).

#include <iostream>
#include <string>
using namespace std;

int main()
{
  string cognnome, nome, cognome, nomecogn;
  int pos;

  cout << "Da una stringa con cognome e nome separati da spazio" << endl
       << "estrae cognome nome e inverte ordine\n\n";

  cout << "Cognome e nome separati da uno spazio ";
  getline(cin,cognnome);	/*1*/

  // ricerca spazio ed estrazione

  pos = cognnome.find(' ');	/*2*/
  if(pos>=0){	/*3*/
    cognome = cognnome.substr(0,pos);	/*4*/
    nome = cognnome.substr(pos+1);	/*5*/
 
    nomecogn = nome+" --- "+cognome;	/*6*/
    cout << "Cognome: " << cognome << endl;
    cout << "Nome: " << nome << endl;
    cout << "Inverso: " << nomecogn << endl;
  }

  return 0;
}

Per acquisire la stringa, nella 1, è usata la funzione getline che permette di scrivere una stringa contenente spazi e che viene considerata completata con Invio. Alla funzione vengono passati come parametri il canale da dove ricevere la linea (cin) e la stringa dove conservare la linea (cognnome). La funzione estrae dal buffer di tastiera (la zona di memoria dove vengono inseriti i caratteri digitati) tutti i caratteri fino a Invio, li mette nella variabile specificata e scarta il carattere Invio. È questo comportamento che se, prima dell'input della stringa, fosse stato effettuato un input di una variabile di altro tipo, produce come effetto il salto dell'istruzione. Nel buffer è contenuto Invio e una getline preleva quello che trova fino all'Invio stesso, cioè niente. Quando, in una istruzione precedente l'uso di getline, c'è un input diverso (una variabile di uno dei tipi elementari) è opportuno inserire subito dopo l'input, e prima dell'acquisizione della stringa, la riga cin.ignore(); che ha l'effetto di ignorare (scartare) il prossimo carattere presente nel buffer.

Nella 2 viene inviato, alla stringa cognnome, il messaggio find passando, stavolta, solo il parametro di cosa cercare. In pos, al solito, ci sarà la posizione dello spazio all'interno della stringa.

Se esiste nella stringa uno spazio (controllo della 3), la stringa viene divisa in due parti. Nella 4 viene messa in cognome la sottostringa che si forma estraendo da cognnome una quantità pos di caratteri dalla posizione 0. Quelli dalla posizione pos+1 alla fine vanno, invece, in nome (5).

la 6 costruisce la nuova stringa nomecogn mettendo assieme (operatore +) stringhe già esistenti e nuove (quella centrale).

Il prossimo programma proposto, acquisita una stringa e una parola, sostituisce la seconda parola della stringa con la parola acquisita da input.

#include <iostream>
#include <string>
using namespace std;

int main()
{
  string dove,metti;
  int inizio,fine,quanti;

  cout << "Data una stringa e una parola in input" << endl
       << "la inserisce al posto della seconda parola della stringa";
  cout << "\n\nInserire stringa da elaborare ";
  getline(cin,dove);
  cout << "Parola da inserire ";
  getline(cin,metti);

  // ricerca spazi che includono la seconda parola

  inizio = dove.find(' ');	/*1*/
  fine = dove.find(' ',inizio+1);	/*2*/

  // eliminazione parola, inserimento nuova

  quanti = (fine-inizio)-1;    	/*3*/
  dove = dove.erase(inizio+1,quanti);	/*4*/
  dove = dove.insert(inizio+1,metti);	/*5*/

  cout << "Nuova stringa" << endl << dove << endl;

  return 0;
}

Nella 1 si cerca la posizione del primo spazio e nella 2 quella del secondo in modo da isolare la parola da eliminare.

Nella 3 si calcola la quantità dei caratteri da eliminare. Si ricorda, per il conteggio, che le posizioni vengono contate a partire da 0.

Il messaggio erase lanciato a dove, nella 4, ha l'effetto di eliminare dalla stringa una certa quantità di caratteri. È necessario specificare, come parametri, la posizione a partire da dove cancellare (quella successiva al primo spazio: inizio+1) e la quantità di caratteri da cancellare. Il risultato dell'operazione viene depositato nuovamente in dove.

Eliminati i caratteri, si può inserire nella stringa la nuova parola. A ciò provvede la funzione membro insert della 5, applicata a dove. Come parametri si specificano la posizione iniziale di inserimento e la stringa da inserire. Anche in questo caso il risultato è una nuova stringa, ma il programma richiede che le variazioni siano fatte nella stringa di partenza e, quindi, come nell'istruzione precedente, il risultato viene assegnato a dove.

Il programma funziona anche quando la stringa di partenza è composta da una sola parola. In questo caso viene sostituita quella parola.

Come ultimo esempio, che illustra l'uso del metodo per la conversione di una stringa in valore numerico, si mostra un programma che calcola la media aritmetica delle valutazioni che un allievo ha ottenuto in una materia che viene fornita come input. Le valutazioni vengono fornite come stringhe contenenti materia e voto separati dalla virgola. Questo programma assumerà un interesse particolare per un tipo di elaborazione che verrà trattata più avanti (file CSV).

#include <iostream>
#include <string>
using namespace std;

int main()
{
  string matinp,matvoto,mat,voto,temp;
  int cont,pos;
  float vot,somma;
  float media;

  cout << "Calcola media voti di una materia, "
          "da stringhe con materia e voto" << endl;
  cout << "Quale materia? ";
  getline(cin,matinp);	/*1*/
 
  cont=somma=0;
  cout << "Materia e voto separati da virgola (invio per finire) ";
  getline(cin,matvoto);	/*2*/
  while(matvoto!=""){
    temp=matvoto;	/*3*/
    pos=temp.find(',');	/*4*/

    // estrae materia e verifica se interessa

    mat=temp.substr(0,pos);	/*5*/
    temp=temp.erase(0,pos+1);	/*6*/
    if(mat==matinp){

      // trasforma voto da stringa a float ed elabora

      vot=atof(temp.c_str());	/*7*/
      cont++;
      somma += vot;
    }
    cout << "Materia e voto separati da virgola (invio per finire) ";
    getline(cin,matvoto);	/*2*/

  }

  if(cont){
    media = (float) somma/cont;
    cout << "media dei voti nella materia " << media << endl;
  }
  else
    cout << "Non ci sono valutazioni per quella materia" << endl;

  return 0;
}

Nella 1 si acquisisce la materia di cui si vuole calcolare la media delle valutazioni.

Nelle 2 si acquisiscono le stringhe delle valutazioni. La stringa viene ricopiata in un'altra (3) per poterla modificare senza che le modifiche comportino una modifica di quello che è stato acquisito in input. Questa è una pratica comune: gli input non si modificano mai perché rappresentano, ai fini di qualsiasi tipo di esigenza, il punto di partenza della elaborazione. Se serve, come nel caso proposto, modificare il valore di un input, questo si ricopia in una nuova variabile.

Per ogni valutazione innanzi tutto si ricerca (4) la posizione della virgola separatrice, si ricopia (5) in una nuova stringa tutta la sottostringa che rappresenta la materia: la quantità di caratteri è lo stesso numero della posizione della virgola (le posizioni si contano da 0) e si cancella (6) la parte estratta. Questa scelta è dettata dalla motivazione di rendere più semplice l'elaborazione della suddivisione delle parti logiche della stringa, principalmente quando le parti sono tante.

L'istruzione principale del programma è la 7. Tolta la parte della materia, con la 6, nella stringa temp è rimasto solo il voto ma non è immediatamente utilizzabile perché in formato stringa. È necessario prima trasformarlo, per mezzo del metodo c_str(), in modo da poter applicare al risultato della trasformazione la funzione atof che permette la conservazione in memoria come valore float così come previsto nella dichiarazione di vot. Se era necessaria una conversione in valore di tipo int occorreva utilizzare atoi al posto di atof.



Avanti - Indietro - Inizio

http://ennebi.solira.org
ennebi@solira.org