Newsgroup: it.comp.lang.c++
Titolo: Alle prime armi

Sono alle prime armi del c++ e della programmazione in generale, per cui
vorrei un aiuto da parte di chi è più esperto di me.
Allora sto studiando da un libro che alla fine di ogni capitolo propone
esercizi da svolgere e mi è capitato un esercizio che sicuramente per voi
sarà banalissimo,ma che io non riesco a risolvere, ve lo propongo così come
dal libro:
Scrivete ed eseguite un programma che legge un intero positivo n e poi
stampa un triangolo di asterischi in n linee, usando un ciclo for.Per
esempio se n è 4, l'output sarà:
*
**
***
****
Quello che io sono riuscito a fare è stato:
   include <iostream.h>
    main()
    {
    int n;
    cout << "inserisci un numero : ";
    cin >> n;
    for (int i=0;i<n;i++)
    cout<<"*\n";
return o;
}
Che però se n=3 stampa
*
*
*
e non come richiede l'esercizio cioè:
*
**
***
Quindi vi prego aiutatemi, e forse anch'io capirò qualcosa di C++.

    #include <iostream.h>


E' l'algoritmo che è sbagliato.... pensaci un attimo, se li vuoi tutti
allineati allora non devi .... il resto fallo tu, ma ti dico che è proprio
banale.
Comunque non te ne esci con un solo ciclo for... ma a questo ci arriverai
anche tu dopo aver compreso come mettere allineati e non incolonnati gli
asterischi.
Bye,
Sebastiano

 wrote:
| Comunque non te ne esci con un solo ciclo for...
Ah, no?-)
[SPOILER x Max, che poi copia...]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <string>
#include <iostream>
int main(){
    std::string s;
    int n;
    std::cout << "inserisci un numero : ";
    std::cin >> n;
    for (int i = 0; i < n; ++i ){
        s += "*";
        std::cout << s << '\n';
    }
}
inserisci un numero : 6
*
**
***
****
*****
******


Eccoti una soluzione ricorsiva del problema :
#include <stdio.h>
#include <iostream.h>
void stampa2(char c, int n)
{
 if(n > 0)
 {
  cout<<c;
  stampa2(c, n - 1);
 }
}
void stampa(int n)
{
 if(n > 0)
 {
  stampa(n - 1);
  stampa2('*', n);
  cout<<endl;
 }
}
int main()
{
 int n = 4;
 stampa(80);
 return 0;
}
e siamo arrivati a zero cicli for.
ciao Al.

Io lo pensavo come una satampa di righe di una matrice..... d'impatto č
stata questa la prima soluzione che mi č venuta in mente... ma soprattutto
cercavo di stimolare il nostro amico a capire a cosa serve esattamente la
new line !
Bye,
Sebastiano.
P.S. Non prendertela se qualche volta esprimo qualche opinione un po
"bizzarra"

Secondo me l'esericio faceva parte del capitolo che spiega i cicli
for. Percui le soluzioni che non lo utilizzano sono bellissime ma fini
a se stesse.
Luc.


 wrote :
| Eccoti una soluzione ricorsiva del problema :
[...]
| e siamo arrivati a zero cicli for.
Ma molto piu' stack consumato :)
il mio post era solo per dire che ottimizzare un ciclo for e' una delle
cose principali da imparare:
ad es.
double calcola(double x, double y, int l) {
    double res;
    for (int n = 0; n < l; ++n){
        res += x*(x*n + y*n);
    }
    return res;
}
puo' essere scritto in modo che venga eseguito in maniera piu' veloce
usando poche operazioni di prodotto. Ma alcuni (buoni) compilatori riescono
a farlo. non sempre pero' il compilatore ottimizza per noi.
ad esempio:
for (int i = 0; i < vectFileNames.size(); ++i){
    ifstream in("lista_files.txt", ios::ate);
    in << vectFileNames[i];
}
"in" viene creato aperto e distrutto ad ogni ciclo, risultato penoso.
invece:
ifstream in("lista_files.txt", ios::ate);
for (int i = 0; i < vectFileNames.size(); ++i){
    in << vectFileNames[i];
}
e' molto + veloce.
stesso discorso usando due cicli for quando ne basta uno, o moltiplicare
per 2 o potenze 2^n un intero quando basta i<<1 o i<<n.
Questi casi non vengono ottimizzati, perche' e' diverso il concetto insito
nel programma, e il compilatore non li cambia. Questi sono concetti
basilari per scrivere programmi efficienti.
La ricorsione, utilissima nella gestione di b-alberi,grafi, etc, ha pero'
il difetto di richiede molto piu' stack per allocare le istanze delle
chiamate a funzioni, e su alberi di dimensioni notevoli, ti servono
gigabyte di stack!

 wrote |
| for (int i = 0; i < vectFileNames.size(); ++i){
|     ifstream in("lista_files.txt", ios::ate);
|     in << vectFileNames[i];
| }
|
| "in" viene creato aperto e distrutto ad ogni ciclo, risultato penoso.
|
| invece:
|
| ifstream in("lista_files.txt", ios::ate);
| for (int i = 0; i < vectFileNames.size(); ++i){
|     in << vectFileNames[i];
| }
da leggersi:
ofstream out("lista_files.txt", ios::ate);
...
out << vectFileNames[i];
(troppo caldo ai neuroni :-)


A proposito di stack non c'è il modo di aumentarlo?
Ad es. se volessi trovare ricorsivamente il fattoriale di 1000 come debbo
fare?
Mi esce fuori stack?
Se si non c'è un modo per regolarlo?
Grazie
Alberto

 fare?
Il fattoriale di (gasp! shudder...) *1000* ?
E' un'intero di piu' o meno 2570 cifre; la prima cosa da fare e'
pensare a perche' lo vuoi calcolare, la seconda a come lo vuoi
rappresentare in memoria ...
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 wrote :
| A proposito di stack non c'è il modo di aumentarlo?
| Ad es. se volessi trovare ricorsivamente il fattoriale di 1000 come debbo
| fare?
| Mi esce fuori stack?
| Se si non c'è un modo per regolarlo?
sul VC++:
/STACK   (Stack Allocations)
...
The Stack Allocations (/STACK:reserve[,commit]) option sets the size of the
stack in bytes.
....
the reserve argument on the command line specifies the total stack
allocation in virtual memory. The default stack size is 1 MB. The linker
rounds up the specified value to the nearest 4 bytes.
sul bcc:
/S:xxxx Specifies application stack reserve size in hexadecimal
defualt is 0x04000 (16K)
sul gcc per i PE:
`--stack RESERVE'
`--stack RESERVE,COMMIT'
     Specify the amount of memory to reserve (and optionally commit) to
     be used as stack for this program.  The default is 32Mb reserved,
     4K committed.

Se si non c'è un modo per regolarlo?
Certo che si', ma il modo di farlo dipende dall'implementazione.
Forse, pero', sarebbe utile rivedere il proprio approccio alla
soluzione dei problemi. Il calcolo del fattoriale e' un esempio tipico
di pessimo uso della ricorsione. Si fa senza problemi in modo
iterativo.

Ragazzi, certo che con voi non si puň barare...... mi fregate sempre.
Ancora ho da imparare, mi sa che non mi pronuncerň piů....
:-)

Anch'io sono alla prime armi (direi ai coltelli da cucina, o alla pistala
laser di quake 2...) e mi sono scervellato per cercare di riuscirci. Dopo
averci molto pensato, a questo sono arrivato. Credevo di aver fatto chissa'
cosa, e invece vedendo i listati... ne devo fare ancora di strada! Comunque,
per quello che vale, ti invio la mia "idea" sperando che ti possa essere
utile.
Ciao
Stefano
p.s.: Se non capisci i commenti fammelo sapere che cerchero' di spiegarteli.
#include <iostream>
int main()
{
cout << "Inserire un numero.\n";   //In queste tre linee immetti
int i;                                             //il numero di asterischi
che vuoi
cin >> i;                                      //avere alla base della
"piramide"
for (int j=1;j<=i;j++)             //Primo ciclo: con questo fai in modo che
vengano
                                           //stampate le serie di * per il
numero di righe i
    {
    int k=j;                       //Secondo ciclo: in questo modo fai in
modo che le serie
    for (;k>0;k--){           //degli asterischi vengano stampati in
orizzontale. Gli asterischi orizzontali
    cout << "*";               //aumentano di uno ogni volta che scendi di
linea.
    }
    cout << "\n";              //con questa linea posizioni il cursore nella
nuova linea appena ne hai riempita
    }                              file://  una (in pratica appena e'
terminato il secondo ciclo for.
}

 Il tuo programma funziona ed usa un solo ciclo for come richiede
l'esercizio, solo che sul libro(l'esercizio è al cap. 3 e anche io come
conoscenze sono fermo li!!) non si  è ancora accennato alla libreria
string.h, quindi credo che la soluzione sia diversa.
Dovrebbe potersi risolvere con solo un ciclo for e usando solo la libreria
iostream.h.
Ciao.

 wrote :
| Il tuo programma funziona ed usa un solo ciclo for come richiede
| l'esercizio, solo che sul libro(l'esercizio è al cap. 3 e anche io come
| conoscenze sono fermo li!!) non si  è ancora accennato alla libreria
| string.h, quindi credo che la soluzione sia diversa.
| Dovrebbe potersi risolvere con solo un ciclo for e usando solo la
libreria
| iostream.h.
| Ciao.
1 - gli include standard non hanno il .h finale.
2 - string dovrebbe essere presentata "prima" dei for, secondo me...
3 - per non usare string devi usare un array di char, allocato
    dinamicamente, o le funzioni ricorsive. ricorsive le hai viste,
    per gli array di char, al solo fine di questo es., poi scordali
    e usa string, ecco qua.
#include <iostream>
int main(){
    int n;
    std::cout << "inserisci un numero : ";
    std::cin >> n;
    char *s = new char[n + 1];
    for (int i = 0; i < n; ++i ){
        s[i] = '*';
        s[i+1] = '\0';
        std::cout << s << '\n';
    }
    delete[] s;
}
Nota la maggior complessita, la necessita' di allocare memoria e di
spostare il '\0' di fine stringa. std::string fa tutto questo per te.