Discussione:
Programma generazioni frasi casuali
(troppo vecchio per rispondere)
Piotre Ugrumov
2003-11-10 20:16:22 UTC
Permalink
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;
}
Giovanni Resta
2003-11-11 08:54:59 UTC
Permalink
Post by Piotre Ugrumov
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.
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
Post by Piotre Ugrumov
"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.
Post by Piotre Ugrumov
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;
}
Piotre Ugrumov
2003-11-11 09:30:45 UTC
Permalink
Post by Giovanni Resta
Post by Piotre Ugrumov
"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.
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.
sbirish
2003-11-13 10:39:29 UTC
Permalink
[SNIP]
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?
#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;
}

***@sophia $ g++ rev.cpp -o rev && echo "uno due tre" | ./rev
tre due uno
***@sophia $

Mauro Casini
2003-11-11 11:05:37 UTC
Permalink
Giovanni Resta <***@iit.cnr.it.nospam> writes:

[...]
Post by Giovanni Resta
Quindi aggiungi
#include<time.h>
time.h e` un header deprecato, rimasto solo per compatibilita`
con il C. Non ha senso consigliarlo per nuovi programmi.
Post by Giovanni Resta
Mai sentito parlare delle funzioni di
#include<string.h>
altro header deprecato.
Post by Giovanni Resta
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.)
Mai sentito parlare delle stringhe e dell'header <string>?

string s3 = s1 + s2;

senza preoccuparsi dello spazio allocato.
Post by Giovanni Resta
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.
E la fortuna quale sarebbe?

Con tutti i contenitori della libreria standard basta
verbo.size()
mentre con gli array serve un'espressione contorta.

Quando serve la dimensione, a e l'array sembra il caso piu` sfigato.
Le macro e` sempre meglio evitarle.
Post by Giovanni Resta
int main(){
char *articolo[]={"The", "A", "One", "Some", "Any"};
I string-literal non sono modificabili, quindi:

const char* articolo[] = ...


Mauro
Giovanni Resta
2003-11-11 14:57:24 UTC
Permalink
Post by Mauro Casini
time.h e` un header deprecato, rimasto solo per compatibilita`
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.
Mauro Casini
2003-11-12 22:02:23 UTC
Permalink
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.
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
fa
2003-11-11 09:38:00 UTC
Permalink
Post by Piotre Ugrumov
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;
}
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.
Piotre Ugrumov
2003-11-11 09:45:39 UTC
Permalink
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;
}
Giovanni Resta
2003-11-11 10:01:12 UTC
Permalink
Post by Piotre Ugrumov
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;
Questo ciclo a cosa serve ??
Tanto le scandisci di nuovo dopo !!
Post by Piotre Ugrumov
count=strtok(string, " ");
while (count!=NULL){
count=strtok(NULL, " ");
k++;
}
tokenPtr=strtok(string, " ");
while(tokenPtr != NULL){
Non hai allocato memoria in token[i]!!!
devi aggiungere qualcosa tipo:

token[i]=(char *)malloc(strlen(tokenPtr)+1);
prima di fare la copia !
Post by Piotre Ugrumov
strcpy (token[i], tokenPtr);
i++;
tokenPtr = strtok(NULL, " ");
}
Premesso che il numero di strighe e' in "i"
invece che in "k" (se uno elimina il
ciclo inutile iniziale), comunque
per scandirle tutte devi andare
da i-1 (o k-1) fino a j>=0 e non j>0,
perche' appunto la prima l'hai memorizzata in token[0].
Post by Piotre Ugrumov
for (int j=k-1; j>0; j--)
cout << token[j] << endl;
return 0;
}
ciao,
g.
Giovanni Resta
2003-11-11 10:06:31 UTC
Permalink
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.
Piotre Ugrumov
2003-11-11 10:32:16 UTC
Permalink
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
Loading...