Newsgroup: it.comp.lang.c++
Titolo: Programma generazioni frasi casuali

Ho creato questo programma per la generazione di 20 frasi casuali, funziona
ma c'è un piccolo problemino mi vengono visualizzate solo poche frasi messe
in ordine sballato.
Poi vorrei modificare il programma in modo tale che produca una storiella
mettendo insieme le frasi generate, come potrei fare?
Grazie.
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
int main(){
    int a, b, c, d, e, i=0;
 char *articolo[]={"The", "A", "One", "Some", "Any"};
 char *nome[]={"boy", "girl", "dog", "town", "car"};
 char *verbo[]={"drove", "jumped", "ran", "walked", "skipped"};
 char *preposizione[]={"to", "from", "over", "under", "on"};
        char frasona[80];
 for (int n=0; n<20; n++){
 a= 0 + rand() % 4;
 b= 0 + rand() % 4;
 c= 0 + rand() % 4;
 d= 0 + rand() % 4;
 e= 0 + rand() % 4;
 for(; articolo[a][i]!='\0'; i++){
    for (int u=0; u<80; u++)
  frasona[u]=' ';
 frasona[i]=articolo[a][i];
 }
 frasona[i]=' ';
 i++;
 for(int j=0; nome[b][j]!='\0'; i++, j++){
 frasona[i]=nome[b][j];
 }
 frasona[i]=' ';
 i++;
 for(int h=0; verbo[c][h]!='\0'; i++, h++){
 frasona[i]=verbo[c][h];
 }
 frasona[i]=' ';
 i++;
 for(int g=0; preposizione[d][g]!='\0'; i++, g++){
 frasona[i]=preposizione[d][g];
 }
 frasona[i]=' ';
 i++;
 for(int l=0; nome[e][l]!='\0'; i++, l++){
 frasona[i]=nome[e][l];
 }
 frasona[i]='.';
 i++;
 frasona[i]='\0';
 cout << frasona << endl;
 }
 return 0;
}

 in ordine sballato.
Intanto devi inizializzare il generatore di numeri casuali.
Il modo migliore e' passargli un seme che dipende dal
momento in cui esegui il programma.
Quindi aggiungi
#include<time.h>
e poi alla partenza del programma esegui, una volta
sola srand(time(NULL));
// vai a vederti srand e time...
poi i numeri casuali che generi sono tra 0 e 3 (compresi).
Non ha senso visto che hai 5 oggetti da cui scegliere.
devi fare rand()%5 per generare numeri da 0 a 4.
Poi in generale e' meglio non usare il modulo per generare
numeri casuali piccoli, ma questo e' un argomento che e'
gia' stato trattato 10000 volte qui e comunque esula dal
tuo problema che e' molto piu' di base. Pero'
ti fornisco comunque una funzione randint(int mx)
che calcola nel modo ritenuto piu' corretto un numero
casuale intero tra 0 e mx-1 (estremi compresi).
Il modo in cui cerchi di accodare in frasona[] i vari
pezzi e' talmente farraginoso che non ho avuto il
coraggio di leggerlo nel dettaglio!
Mai sentito parlare delle funzioni di
#include<string.h>
come strcat(a,b) strcpy(a,b) etc.etc.
la strcat accoda una stringa ad un altra
la strcpy copia una stringa in un altra
(bisogna ovviamente che ci sia abbastanza spazio
allocato.)
Poi siccome presumo che vorrai aumentare il numero
di parole, ogni volta e' una palla andare a modificare il
programma per tenere conto che gli array di stringhe hanno
un certo numero di elementi.
Per fortuna se tu hai un array definito in quel modo
diciamo "verbo" se fai sizeof(verbo) ti restituisce
la dimensione di verbo. Ricordando che verbo e' un array
di puntatori facendo sizeof(verbo)/sizeof(verbo[0]) ottieni
esattamente il numero di stringhe nell'array verbo.
A questo punto allora conviene scrivere una piccola macro:
(vedi programma sotto)
RANDEL(arr) che genera un elemento casuale dell array arr
specificato.
Riassumendo il tuo programma potrebbe essere riscritto cosi'
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <time.h>
using namespace std;
int randint(int mx){return (int) (((double)mx)*rand()/(RAND_MAX+1.0));}
int main(){
  char *articolo[]={"The", "A", "One", "Some", "Any"};
  char *nome[]={"boy", "girl", "dog", "town", "car","cat"};
  char *verbo[]={"drove", "jumped", "ran", "walked", "skipped"};
  char *preposizione[]={"to", "from", "over", "under", "on"};
  char frasona[80];
#define RANDEL(arr) arr[randint(sizeof(arr)/sizeof(arr[0]))]
  srand(time(NULL));
  for (int n=0; n<20; n++)
  {
    strcpy(frasona,RANDEL(articolo));
    strcat(frasona," ");strcat(frasona,RANDEL(nome));
    strcat(frasona," ");strcat(frasona,RANDEL(verbo));
    strcat(frasona," ");strcat(frasona,RANDEL(preposizione));
    strcat(frasona," ");strcat(frasona,RANDEL(nome));
    cout << frasona << endl;
  }
  return 0;
}
per quel che riguarda
 >"Poi vorrei modificare il programma in modo tale che produca una
 >storiella mettendo insieme le frasi generate, come potrei fare?"
la domanda e' poco chiara. Cosa vorresti fare esattamente.
Vuoi solo stampare le frasi una di seguito all'altra o vorresti
che le frasi prese di seguito avessero un senso ?
ciao,
g.


 g.
grazie per la risposta mi sei stato di grandissimo aiuto, ho risolto anche
il problema della storiella grazie mille, scusa se ne approfitto vorrei
chiederti un'ultima cosa, vorrei scrivere un programma che prende una linea
di testo in ingresso che estrae i token e li visualizza in ordine inverso
come potrei fare?
Vorrei estrarre i token metterli in un array di puntatori a carattere e
visualizzare in ordine inverso gli elementi di questo array, pensi possa
funzionare?
C'è qualche sistema migliore non complicato comprensibile ad uno alle prima
armi?
Grazie ancora.

...

char* gestisce le stringhe a basso livello in C. in C++ c'e' la classe
string.
 non ho letto tutto il tuo codice ma sono sicuro che lo puoi dimezzare
usando la classe string.

Ho provato a creare questo pèrogramma che prende una linea di testo estrae i
token e li visualizza in ordine inverso. Il programma mi viene compilato
correttamente però al momento dell'esecuzione mi vengono date degli errori.
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
int main(){
 char string[]="This is a sentence with 7 tokens";
 char *tokenPtr, *token[70], *count;
 int i=0, k=0;
 count=strtok(string, " ");
 while (count!=NULL){
  count=strtok(NULL, " ");
  k++;
 }
 tokenPtr=strtok(string, " ");
 while(tokenPtr != NULL){
   strcpy (token[i], tokenPtr);
   i++;
      tokenPtr = strtok(NULL, " ");
 }
 for (int j=k-1; j>0; j--)
  cout << token[j] << endl;
 return 0;
}

 }
ciao,
g.

Giovanni Resta wrote:
Volevo solo aggiungere:
stai attento quando usi la strtok (sconsigliata per alcuni usi seri),
perche' ti modifica la stringa di partenza, ciao,
g.

Grazie ancora, quindi, spero něche tu non mi voglia picchiare ti assicuro
che con questo chiudo, mi puoi spiegare questa riga di codice:
token[i]=(char *)malloc(strlen(tokenPtr)+1);
Grazie

   char *articolo[]={"The", "A", "One", "Some", "Any"};
I string-literal non sono modificabili, quindi:
  const char* articolo[] = ...
       Mauro

 con il C.  Non ha senso consigliarlo per nuovi programmi.
Caro Mauro (a proposito, buon compleanno, anche se sono in ritardo di
qualche giorno),
io sono un povero C-ista che usa il C++ solo quando gli serve la STL,
(o quando devo usare uindous, vedi il mio Verbatron),
sicche' sono piuttosto ignorante al riguardo,
ma siccome nessuno rispondeva al Piotre, mi sono permesso
di suggerirgli qualcosa che almeno funzionasse.
Tutto giusto quello che dici, a parte il fatto che non mi
piace la frase in cui tassativamente e
apoditticamente proibisci l'uso delle macro.
Secondo me ogni strumento a disposizione in un linguaggio
puo' trovare la sua ragione d'utilizzo. Precludersi a priori
delle possibilita' e' un atteggiamento che non condivido.
La discriminante ultima secondo me deve essere il buon senso
del programmatore e l'uso che deve essere fatto del codice.
(c'e' differenza tra scrivere programmini sporchi brutti e cattivi
come capita spesso a me per lavoro e lunghi programmi ai quali magari
piu' persone devono mettere le mani.)
Ciao,
g.

 macro.
Le macro servono per evitare l'inclusione multipla degli header, per
la compilazione condizionale e poco altro.
In C le macro si usavano anche al posto delle funzioni, per aggirare
la mancanza di template e funzioni inline, in C++ non c'e` bisogno di
usare le macro in questo modo.
Ovviamente ci sono anche dei casi particolari in cui ha senso usare le
macro, ma sono molto rari.  Nei casi normali gli effetti collaterali
superano largamente gli eventuali vantaggi.
         Mauro

 come potrei fare?
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
int main()
{
    std::istream_iterator<std::string> first( std::cin );
    std::istream_iterator<std::string> last;
    std::vector<std::string> tokens( first, last );
    std::copy( tokens.rbegin(), tokens.rend(), 
        std::ostream_iterator<std::string>(std::cout, " " ) );
    std::cout << std::endl;
}
sbirish@sophia $ g++ rev.cpp -o rev && echo "uno due tre" | ./rev
tre due uno
sbirish@sophia $