Newsgroup: it.comp.lang.pascal
Titolo: Indice analitico..

Salve a tutti.
Premetto che sono alle prime armi con il Pascal.
Ho fatto un programma che prende in input una serie di nomi da un file e
crea un file di output
che contiene i nomi ordinati (in modo da creare, ad esempio, un indice
analitico a partire dai
singoli argomenti).
Per far questo ho creato un array di stringhe e ho costruito una procedura
che ordina questo array dalla stringa di valore minore a quella maggiore.
Poi ovviamente faccio stampare l'array.
Ma il mio array deve avere una lunghezza fissata in partenza.
Ho creato una costante (maxnum) che indica la lunghezza dell'array,
dichiarata all'inizio del programma, e chiaramente l'ho settata ad un numero
alto perché il mio programma potesse ordinare un gran numero di nomi.
il sistema perň rileva i seguenti errori:
      maxnum>255       -> structure too large.
92<maxnum<=255    -> too many variables
Quindi posso ordinare solo 92 nomi e il mio programma, potrete capire, perde
molto senso.
Come posso aggirare questo problema?
Ringrazio anticipatamente.
Gebriele

Un bel di' Gabriele scrisse:
G> alto perché il mio programma potesse ordinare un gran numero di nomi.
G> il sistema perň rileva i seguenti errori:
G> 
      maxnum>>255       -> structure too large.
G> 92<maxnum<=255    -> too many variables
G> 
G> Quindi posso ordinare solo 92 nomi e il mio programma, potrete capire, perde
G> molto senso.
giovane!! Una string in pascal tiene 256 byte!!! :-))
Prova ad "accorciare le stringhe", dichiarandole cosi':
	string[n]
dove n e' la lunghezza massima della stringa... :-)
Lo so, fa schifo, pero' come soluzione di comodo e' l'unica... senno' ti
sbatti ad allocarti la memoria, oppure passi al C++ :-)
-- 
"L'esperienza e' direttamente proporzionale all'attrezzatura rotta",
postulato di Horner
-- 
Emanuele Cesena
d.a.m...@iol.it
    occhio all'antispam NOSPAM!
http://www.geocities.com/SiliconValley/Grid/8879


Tieni presente che  in borland pascal tutte le variabili dichiarate
a livello di programma + quelle a livello di unit possono occupare in totale
al massimo 64Kbyte.

La soluzione migliore e più efficiente è di usare variabili
allocate dinamicamente, tramite puntatori e le funzioni NEW  e DISPOSE.

Per iniziare a lavorare con i puntatori prova a partire  da questo:


Type pstring=^string; (* crei un tipo puntatore di stringa*)


Var str_array: array [0..quantomiserve] of pstring;


ed ogni volta che hai bisogno di usare una stringa creala con

New(str_array[xyz]);


 e quindi


str_array[xyz]^:='questa è la stringa da usare'
;


 o circa. Ricordati che la variabile senza ^ è il puntatore 
con è la variabile effettiva.


Con questo sistema puoi utilizzare effettivamente tutta la memoria a
tua disposizione. .


Gabriele ha scritto:

Salve a tutti.

Premetto che sono alle prime armi con il Pascal.

Ho fatto un programma che prende in input una serie di nomi da un file
e

crea un file di output

che contiene i nomi ordinati (in modo da creare, ad esempio, un indice

analitico a partire dai

singoli argomenti).

Per far questo ho creato un array di stringhe e ho costruito una procedura

che ordina questo array dalla stringa di valore minore a quella maggiore.

Poi ovviamente faccio stampare l'array.

Ma il mio array deve avere una lunghezza fissata in partenza.

Ho creato una costante (maxnum) che indica la lunghezza dell'array,

dichiarata all'inizio del programma, e chiaramente l'ho settata ad
un numero

alto perché il mio programma potesse ordinare un gran numero
di nomi.

il sistema però rileva i seguenti errori:


      maxnum>255      
-> structure too large.

92<maxnum<=255    -> too many variables


Quindi posso ordinare solo 92 nomi e il mio programma, potrete capire,
perde







Ti ringrazio per il suggerimento. Il 
programma ora funziona e mi ordina fino a 5000 nomi e rotti.


Non riesco però a levare 
gli spazi bianchi che compaiono nel file di output (dovuti al fatto che in 
genere non inserisco 5000 nomi, ma voglio comunque la possibilità di 
inserirli).


Allego il programma di seguito.


 


program rubrica;
uses wincrt;
const 
maxnum=200{5895};   {inizializzazione n° max di nomi}
var 
input,output:text;
var i,p,place:integer;
var 
nomeinput,nomeoutput:string;
type pstring=^string;
var 
str_array_in:array[1..maxnum]of pstring;
var str_array_out:array[1..maxnum]of 
pstring;


 


procedure ordina 
(nome:string;
                 
var posto:integer);
var n:integer;
begin
    
posto:=1;
    for n:=1 to maxnum 
do
        if 
nome>str_array_in[n]^
         
then posto:=posto+1
end;


 


BEGIN
 write('Scrivi il nome del 
file di input: ');
 readln(nomeinput);
 write('Scrivi il nome 
del file di output: ');
 readln(nomeoutput);
 assign 
(input,nomeinput);
 reset (input);
 for i:=1 to maxnum 
do
  begin
   new(str_array_in[i]); {assegna spazio 
all'array di puntatori}
   new(str_array_out[i]);
  
end;
 for i:=1 to maxnum do readln 
(input,str_array_in[i]^);
 {legge i nomi collocandoli nelle celle di 
memoria indicate di puntatori dell'array}
 for i:=1 to maxnum 
do
  begin
   ordina 
(str_array_in[i]^,place);
   
str_array_out[place]^:=str_array_in[i]^
  
end;
 assign(output,nomeoutput);
 rewrite (output);
 for 
place:=1 to maxnum do
  writeln(output, 
str_array_out[place]^);
 close (output);
 writeln('FINE 
PROGRAMMA.');
 writeln;
 writeln('I nomi contenuti nel file 
',nomeinput);
 writeln('sono stati ordinati e 
archiviati');
 writeln('nel file ',nomeoutput)
END.


 




Mauro Minnella
 ha scritto:


Un bel di' Gabriele scrisse:
G> Ti ringrazio per il suggerimento. Il programma ora funziona e mi ordina fino a 5000 nomi e rotti.
G> Non riesco per? a levare gli spazi bianchi che compaiono nel file di output (dovuti al fatto che in genere non inserisco 5000 nomi, ma voglio comunque la possibilit? di inserirli).
G> Allego il programma di seguito.
G> 
Non ho letto il prog... perdonami ma non ho tempo :-)
Comunque il problema non e' tanto complesso:
- prendi il numero di parole in input (n)
- for i:=1 to n
	prendi la parola
- ordini
- for i:=1 to n
	output della parola
(secondo me ti manca solo l'ultimo for) :-)
ciao! :-)
-- 
"9. Tieni sempre la porta del tuo ufficio chiusa. Questo mettera' i
visitatori sulla difensiva e dara' l'impressione che sei sempre in
riunione", dal decalogo di Spark per il giovane manager


ciao! :-)
Ciao e grazie.
Allego di nuovo il programma per una migliore comprensione:
program rubrica;
uses wincrt;
const maxnum=300{5895};   {inizializzazione n° max di nomi}
var mydata,output:text;
var i,p,place:integer;
var nomeinput,nomeoutput:string;
type pstring=^string;
var str_array_in:array[1..maxnum]of pstring;
var str_array_out:array[1..maxnum]of pstring;
procedure ordina (nome:string;
                 var posto:integer);
var n:integer;
begin
    posto:=1;
    for n:=1 to maxnum do
        if nome>str_array_in[n]^
         then posto:=posto+1
end;
BEGIN
 write('Scrivi il nome del file di input: ');
 readln(nomeinput);
 write('Scrivi il nome del file di output: ');
 readln(nomeoutput);
 assign (mydata,nomeinput);
 reset (mydata);
 for i:=1 to maxnum do
  begin
   new(str_array_in[i]); {assegna spazio all'array di puntatori}
   new(str_array_out[i]);
  end;
 for i:=1 to maxnum do readln (mydata,str_array_in[i]^);


Essendo alle prime armi con il Pascal adesso avrai modo di conoscere i puntatori
e di capirne il loro valore ;).
Per la tua applicazione devi definire un albero binario come nel programma che
ti ho scritto di seguito.
L'albero binario ha il vantaggio di non essere ridondante e di essere
auto-ordinato  :
uses crt;
type  ptr_nodo_albero = ^nodo_albero;
      nodo_albero = record
                      ptr_parola : ^string;
                      peso : word;
                      sinistra, destra : ptr_nodo_albero;
                    end;
procedure inserisci_parola(var nodo : ptr_nodo_albero; parola : string);
var nodo_temp : ptr_nodo_albero;
begin
  new(nodo_temp);
  nodo_temp^.peso := 1;
  nodo_temp^.sinistra := nil;
  nodo_temp^.destra := nil;
  getmem(nodo_temp^.ptr_parola, length(parola)+1);
  nodo_temp^.ptr_parola^ := parola;
  if (nodo = nil) then
    nodo := nodo_temp
  else
  if (nodo^.ptr_parola^ = parola) then
  begin
    freemem(nodo_temp^.ptr_parola, length(parola)+1);
    dispose(nodo_temp);
    inc(nodo^.peso);
  end
  else
  if (nodo^.ptr_parola^ < parola) then
  begin
    if (nodo^.sinistra <> nil) then
       inserisci_parola(nodo^.sinistra, parola)
    else
       nodo^.sinistra := nodo_temp;
  end
  else
  if (nodo^.ptr_parola^ > parola) then
  begin
    if (nodo^.destra <> nil) then
       inserisci_parola(nodo^.destra, parola)
    else
       nodo^.destra := nodo_temp;
  end
end;
procedure scrivi_albero(nodo : ptr_nodo_albero);
begin
  if (nodo^.destra <> nil) then scrivi_albero(nodo^.destra);
  writeln(nodo^.ptr_parola^+' (',nodo^.peso,')');
  if (nodo^.sinistra <> nil) then scrivi_albero(nodo^.sinistra);
end;
var radice : ptr_nodo_albero;
begin
  clrscr;
  radice := nil;
  inserisci_parola(radice, 'armadio');
  inserisci_parola(radice, 'scarpa');
  inserisci_parola(radice, 'imbuto');
  inserisci_parola(radice, 'stuzzicadenti');
  inserisci_parola(radice, 'attaccapanni');
  inserisci_parola(radice, 'imbuto');
  inserisci_parola(radice, 'imbuto');
  inserisci_parola(radice, 'armadio');
  inserisci_parola(radice, 'canneto');
  inserisci_parola(radice, 'uccello');
  inserisci_parola(radice, 'indirizzo');
  inserisci_parola(radice, 'lettera');
  inserisci_parola(radice, 'attaccapanni');
  inserisci_parola(radice, 'asino');
  inserisci_parola(radice, 'cassetto');
  inserisci_parola(radice, 'brocca');
  scrivi_albero(radice);
end.
 
Andrea (mica uno qualunque...)
------------------------------
(se mi mandi la spam ti metto un'aspirina nella fanta...)
--
Posted from 
itaca.ulysse.it
 [195.223.254.1]
via Mailgate.ORG Server - 
http://www.mailgate.org

disposizione. .
Mi spiace ma non e' cosi'.
'str_array' e' comunque un array di 'variabili' puntatore (che occupano 4 byte).
Quindi, essendo il limite per 'str_array' di 64Kb sara'  limitato a _circa_
16000 e rotti elementi.
A questo proposito e' bene precisare che un puntatore non e' una variabile
dinamica.
E' una variabile come tutte le altre.
Quello che e' dinamico, ovvero che viene creato,  utilizzato per un certo tempo
e poi distrutto e', semmai, il valore puntato, ovvero quello che risiede
effettivamente nella memoria HEAP.
Ci tengo a precisarlo perche' tante volte questo e' uno dei motivi che genera
confusione per chi e' alle prime armi.


Un bel di' Sparacacca Liquidator scrisse:
SL> Per la tua applicazione devi definire un albero binario come nel programma che
SL> ti ho scritto di seguito.
SL> 
ben tornato... oh Andrea... :-)
Finito il milite?? :-))
Ma, una domanda che sorge a me spontanea.... tu fai tutto con gli alberi
binari?? :-)
bye!
-- 
"L'opulenza dell'ufficio di rappresentanza e' inversamente proporzionale
alla solvenza della ditta", legge delle Istituzioni


>(secondo me ti manca solo l'ultimo for) :-)
G> 
G> No, l'ultimo for ce l'ho messo...
G> 
vabbuo' :-)
G> Il mio problema non è questo: voglio trovare il modo di non far leggere al
G> sistema (o almeno di non fargli scrivere) le stringhe che non ho inserito, e
G> che lui inizializza nel vettore a spazi bianchi,  comportando qualcosa come
G> paginate di spazi bianchi completamente inutili.
G> 
aho... ma scherzi!? :-))
guarda questo mini programma:
readln(max_str);
for i:=1 to max_srt do
   readln(stringa[i]);
ordina;
for i:=1 to max_str do
   writeln(stringa[i]);
ti pare che legga e scriva stringa bianche!? :-)
anche se dichiari l'array come 
var stringa:array[1..10^32 :)]of stringa[50];
ed inserisci 2 stringhe (max_str=2),
non vedi certo nessuna stringa vuota... comunque vediamo!
G> 
G> Allego di nuovo il programma per una migliore comprensione:
G> 
vabbe'... lo leggero' :-))
G>  for i:=1 to maxnum do readln (mydata,str_array_in[i]^);
eccolo qua, il problema:
non puoi prendere dal file 300{5895} (ossia maxnum) stringhe...
ma solo quante ce ne stanno :-)
num:=0;
while not(eof(mydata)) and num<=maxnum do
   begin
    readln(mydata,str_array_in[num]^);
    inc(num);
   end;
prova questo... dovrebbe fungere :-)
dove inc(i) significa i:=i+1 :-)
dopodiche' non fai piu' i cicli fino a maxnum, ma fino a num!! :-)
ciao!
-- 
"Bellezza moltiplicata per intelligenza e' uguale a una costante", legge di
Beckhap





Scusa ma leggo solo adesso la tua risposta,  ma vedo anche la risposta
di LaForgia, che è esattamente la stessa che ti avrei dato io. Il
suggerimento era proprio per iniziare a lavorare e comprendere il concetto
di puntatori, che se ben usati ti permettono di risultati straordinari,
rispetto ad alle risorse di altri linguaggi.

Un suggerimento: ricordati sempre di inizializzare sempre i puntatori
a nil prima di usarli. Anche se a volte la cosa sarà totalmente
inutile, questa abitudine ti risparmierà tante tempo perso in dubugging.

saluti.


Gabriele ha scritto:

 
Ti
ringrazio per il suggerimento. Il programma ora funziona e mi ordina fino
a 5000 nomi e rotti.
Non riesco però a levare
gli spazi bianchi che compaiono nel file di output (dovuti al fatto che
in genere non inserisco 5000 nomi, ma voglio comunque la possibilità
di inserirli).Allego il programma di seguito. 
program
rubrica;




Grazie Emanuele.
A quanto ho capito però tu mi suggerisci di contare il numero delle stringhe
da ordinare ogni volta, di inserirlo in maxnum con un read(maxnum) e di
ciclare fino a num(<=maxnum) e non fino al numero massimo di stringhe.
Giusto. Senonchè io ero arrivato a questo problema perché non volevo che
l'utente fosse costretto ,se avesse voluto creare ad esempio una rubrica
telefonica, a contare tutte le volte il numero di persone che conosceva per
poi ordinarle alfabeticamente.
Ho provato con la funzione che hai usato tu (eof), facendogli leggere le
stringhe fino alla fine del file e poi facendogli stampare il vettore fino
al valore in cui mi si era fermato il contatore del ciclo appena descritto
(il cui valore quindi si arresta al numero di righe che effettivamente
contengono nomi) ma riesco ad ottenere soltanto un errore a tempo di
compilazione. Forse dipende dal fatto che non sono pratico di questa
funzione? Ho messo:
i:=1;
repeat
 readln(mydata,str_array_in[i]^);
 inc(i)
until eof;
num:=i;
 .
 .
 ...ordina l'array...
 .
 .
....for i:=1 to num {stampa l'array ordinato}
Che mi potete dire?
      Gabriele

Ho trovato il modo per risolvere il problema..
Bastava usare bene eof per capire quando il file finiva. Soltanto era una
funzione che non conoscevo:) Grazie a tutti:)
Gabriele

binari?? :-)
Perche' e' sicuramente il metodo piu' sbrigativo ed efficiente...


Un bel di' Gabriele scrisse:
G> Grazie Emanuele.
de che'?? Non va ancora... aspetta, aspetta... :-)))
G> Giusto. Senonchè io ero arrivato a questo problema perché non volevo che
G> l'utente fosse costretto ,se avesse voluto creare ad esempio una rubrica
G> telefonica, a contare tutte le volte il numero di persone che conosceva per
G> poi ordinarle alfabeticamente.
ho capito il problema... questa soluzione non va :-)
G> contengono nomi) ma riesco ad ottenere soltanto un errore a tempo di
G> compilazione. Forse dipende dal fatto che non sono pratico di questa
G> funzione? Ho messo:
G> 
credo dipenda da questo... ma copia la mia funzione, che e' meglio, ti
spiego perche':
G> i:=1;
G> repeat
G>  readln(mydata,str_array_in[i]^);
G>  inc(i)
G> until eof;
G> num:=i;
intanto i e' superflua:
num:=1;
repeat
  readln(mydata,str_array_in[i]^);
  inc(num)
until eof;
      ^^^
e comunque l'errore e' qui: eof e' una funzione che ritorna vero
quando si raggiunge la fine del file (eof = end of file)... si', ma
che file se non glielo passi?? :-)
Dunque sara' 
	until eof(f);
Ma non ci siamo ancora: cosi' num vale "uno di troppo":
num = 1
  readln;
  inc(num) => num = 2
  readln;
  inc(num) => num = 3
ma abbiamo letto solo 2 stringhe... :-)
Prova con:
num:=0;
repeat
  readln(mydata,str_array_in[i]^);
  inc(num)
until eof(mydata);
num = 0
  readln;
  inc(num) => num = 1
  readln;
  inc(num) => num = 2
... e cosi' va :-)
Ultimo passo: perche' avevo messo il ciclo col while??
Semplice: se il file e' vuoto, cosa ti succede??
num = 0
  readln;
  inc(num) => num = 1
e sembra che hai letto una stringa...
(il ciclo repeat until verifica la condizione alla fine, quindi una volta,
almeno, fa quello che c'e' all'interno).
Invece col while risolvi anche questo problema.
Il while, in generale, e' un po' piu' ostico, piu' difficile da imparare
ad usare, ma nella maggiorn parte dei problemi (soprattutto quando si
devono leggere n cose, scrivere n cose...) e' preferibile al repeat :-)
Ciao!
-- 
"In ogni impresa umana, il lavoro cerca sempre il livello gerarchico piu'
basso", assioma di Vail


>binari?? :-)
SL> 
SL> Perche' e' sicuramente il metodo piu' sbrigativo ed efficiente...
SL> 
ahhh :-)
-- 
"Chi ha, prende", legge di ferro della Distribuzione
