Oppure

Loading
13/01/12 11:23
serfabio
Salve a tutti amici del forum!!!Mi rivolgo a voi, nella speranza di trovare un aiuto nella soluzione del seguente problema; è noto come due numeri interi ( che noi supporremo tali che il primo in ingresso sia maggiore o uguale al secondo, in quanto a numero di cifre che lo caratterizzano) possano essere rappresentati mediante due liste distinte che fanno uso di record e puntatori; si vuole scrivere un programma che dati due numeri così rappresentati, calcoli e stampi la loro somma. Ho provato ad elaborare un programma, risolutore del problema sopra citato, che fa uso di due procedure, la prima scritta per acquisire le due liste e rappresentarle, la seconda per calcolare la somma degli elementi delle liste suddette. In tale calcolo bisogna tenere conto delle cifre da riportare e da sommare, quando l'addizione di due elementi delle due liste superi il valore di dieci ed inoltre occorre tenere conto del fatto che , se le due liste sono di uguale lunghezza e la somma dell'ultima coppia di elementi ( le prime due cifre dei due numeri dati da sinistra!) ha valore maggiore di dieci occorre che la lista che rappresenta la somma abbia un elemento in più e pari ad 1. Ho provato ad elaborare due soluzioni distinte del problema ( una non ricorsiva e l'altra ricorsiva ),ove s, p e q costituiscono la lista somma e le due liste da sommare di cui la prima di lunghezza m e la seconda n, con m>=n:

a) Versione non ricorsiva:

program SommaDiDueListe(input,output);
label 99;
const bell=07;
type punt=^elem;
     elem= record
                 val: integer;
                 back : punt;
                 next : punt;
           end;
var p,q,s : punt;
    m,n,k : integer;

procedure LeggiEScriviLista( var p : punt; k : integer);
begin
     if k=0
     then p:=nil
     else begin
               new(p);
               read(p^.val);
               write(p^.val,' ');
               LeggiEScriviLista(p^.back,k-1);
          end;
end;{ Fine procedura LeggiEScriviLista }
procedure CalcoloSommaDiDueListe( var s : punt; p,q : punt);
var i : integer;
begin
     new(s);
     begin
          s^.val:=p^.val+q^.val;
          case(s^.val)of
          0,1,2,3,4,5,6,7,8,9 :  write(s^.val,' ');
          10,11,12,13,14,15,16,17,18 : begin
                                            s^.back^.val:=p^.back^.val+q^.back^.val+1;
                                            s^.val:=(s^.val)-10;
                                            write(s^.val,' ');
                                       end
          end;
          p:=p^.back;
          q:=q^.back;
          s:=s^.back;
          for i:=2 to m
                   do begin
                           case(p^.val+q^.val)of
                           0,1,2,3,4,5,6,7,8,9 : begin
                                                      if s^.back^.next^.val=p^.val+q^.val+1
                                                      then begin
                                                                s^.val:=(p^.val+q^.val+1);
                                                                write(s^.val,' ')
                                                           end
                                                      else begin
                                                                s^.val:=(p^.val+q^.val);
                                                                write(s^.val,' ')
                                                           end;
                                                 end;
                           10,11,12,13,14,15,16,17,18 : begin
                                                             if s^.back^.next^.val=p^.val+q^.val+1
                                                             then begin
                                                                       s^.val:=(p^.val+q^.val+1)-10;
                                                                       write(s^.val,' ');
                                                                  end
                                                             else begin
                                                                       s^.val:=(p^.val+q^.val)-10;
                                                                       write(s^.val,' ')
                                                                  end;
                                                        end
                           end;
                           p:=p^.back;
                           q:=q^.back;
                           s:=s^.back;
                      end;
     if i=m then begin
                      case(p^.val+q^.val)of
                      0,1,2,3,4,5,6,7,8,9 : s^.back:=nil;
                      10,11,12,13,14,15,16,17,18 : begin(s^.back^.val):=1;
                                                         write(s^.back^.val,' ');
                                                   end
                      end;
                      s^.back^.back:=nil;
                 end;
     end;
end;{ Fine procedura CalcoloSommaDiDueListe }

{ Corpo del programma }
begin
     writeln('------------------------- Dati di ingresso --------------------------');
     writeln;
     write('Fornire la lunghezza della prima lista: ');
     readln(m);
     writeln;
     write('Fornire la lunghezza della seconda lista: ');
     readln(n);
     writeln;
     if m<n then begin
                      writeln(chr(bell),'Errore nei dati di ingresso!- STOP -');
                      goto 99;
                 end
            else begin
                      write('Fornire la prima lista: ');
                      LeggiEScriviLista(p,m);
                      writeln;
                      write('Fornire la seconda lista: ');
                      LeggiEScriviLista(q,n);
                      writeln;
                      writeln('La lista somma e'':');
                      CalcoloSommaDiDueListe(p,q,s);
                 end;
     99 :
     readln;

end.




b) Versione ricorsiva:


program SommaDiDueListe(input,output);
label 99;
const bell=07;
type punt=^elem;
     elem= record
                 val: integer;
                 back : punt;
           end;
var p,q,s : punt;
    m,n,k : integer;

procedure LeggiEScriviLista( var p : punt; k : integer);
begin
     if k=0
     then p:=nil
     else begin
               new(p);
               read(p^.val);
               write(p^.val,' ');
               LeggiEScriviLista(p^.back,k-1);
          end;
end;{ Fine procedura LeggiEScriviLista }
procedure CalcoloSommaDiDueListe( var s : punt; p,q : punt; k : integer);
begin
     if k=0
     then s^.back:=nil
     else begin
               new(s);
               s^.val:=p^.val+q^.val;
               case(s^.val)of
               0,1,2,3,4,5,6,7,8,9 :  write(s^.val,' ');
               10,11,12,13,14,15,16,17,18 : begin s^.val:=(s^.val)-10;
                                                  write(s^.val,' ');
                                                  s^.back^.val:=(p^.back^.val+q^.back^.val+1);
                                            end
               end;
               CalcoloSommaDiDueListe(s^.back,p^.back,q^.back,k-1);
          end;
end;{ Fine procedura CalcoloSommaDiDueListe }

{ Corpo del programma }
begin
     writeln('------------------------- Dati di ingresso --------------------------');
     writeln;
     write('Fornire la lunghezza della prima lista: ');
     readln(m);
     writeln;
     write('Fornire la lunghezza della seconda lista: ');
     readln(n);
     writeln;
     if m<n then begin
                      writeln(chr(bell),'Errore nei dati di ingresso!- STOP -');
                      goto 99;
                 end
            else begin
                      write('Fornire la prima lista: ');
                      LeggiEScriviLista(p,m);
                      writeln;
                      write('Fornire la seconda lista: ');
                      LeggiEScriviLista(q,n);
                      writeln;
                      writeln('La lista somma e'':');
                      CalcoloSommaDiDueListe(s,p,q,m);
                 end;
     99 :
     readln;

end.




Sarei molto grato a chiunque di voi, amici del forum, sapesse indicarmi se possono essere considerate soluzioni corrette poichè Dev-Pascal mi da errori a tempo di esecuzione ( MI CHIUDE LA FINESTRA AL MOMENTO DEL CALCOLO DELLA SOMMA) e, quindi , in caso non lo fossero, fornirmi le correzioni giuste . Grazie e ciao a tutti!!!
aaa
12/05/12 11:03
fabioser
Ho provato ad elaborare una versione migliorativa del sopracitato programma espresso in forma ricorsiva il cui codice completo è il seguente:

program SommaDiDueListe(input,output);
label 99;
const bell=07;
type punt=^elem;
     elem= record
                 val: integer;
                 back : punt;
                 next : punt;
           end;
var p,q,s : punt;
    m,n,k : integer;

procedure LeggiEScriviLista( var p : punt; k : integer);
begin
     if k=0
     then p:=nil
     else if k=n
     then p:=nil
     else begin
               new(p);
               read(p^.val);
               write(p^.val,' ');
               LeggiEScriviLista(p^.back,k-1);
          end;
end;{ Fine procedura LeggiEScriviLista }
procedure CalcoloSommaDiDueListe( var s : punt; p,q : punt; k : integer);
begin
     if k=0
     then begin
               s^.back:=nil;
               case (p^.next^.val+q^.next^.val)of
               0,1,2,3,4,5,6,7,8,9 : s^.val:=0;
               10,11,12,13,14,15,16,17,18 : begin
                                                 s^.val:=1;
                                                 write(s^.val,' ');
                                            end
               end;
          end
     else begin
               new(s);
               s^.val:=p^.val+q^.val;
               case (p^.next^.val+q^.next^.val)of
               0,1,2,3,4,5,6,7,8,9 : s^.val:=p^.val+q^.val;
               10,11,12,13,14,15,16,17,18 : s^.val:=p^.val+q^.val+1
               end;
               case(s^.val)of
               0,1,2,3,4,5,6,7,8,9 :  write(s^.val,' ');
               10,11,12,13,14,15,16,17,18 : begin s^.val:=(s^.val)-10;
                                                  write(s^.val,' ');
                                            end
               end;
               CalcoloSommaDiDueListe(s^.back,p^.back,q^.back,k-1);
          end;
end;{ Fine procedura CalcoloSommaDiDueListe }

{ Corpo del programma }
begin
     writeln('------------------------- Dati di ingresso --------------------------');
     writeln;
     write('Fornire la lunghezza della prima lista: ');
     readln(m);
     writeln;
     write('Fornire la lunghezza della seconda lista: ');
     readln(n);
     writeln;
     if m<n then begin
                      writeln(chr(bell),'Errore nei dati di ingresso!- STOP -');
                      goto 99;
                 end
            else begin
                      write('Fornire la prima lista: ');
                      LeggiEScriviLista(p,m);
                      writeln;
                      write('Fornire la seconda lista: ');
                      LeggiEScriviLista(q,n);
                      writeln;
                      write('La lista somma e'':');
                      CalcoloSommaDiDueListe(s,p,q,m);
                 end;
     99 :
     readln;

end.





Tuttavia anche questa soluzione non sembra essere corretta. Qualcuno del forum è in grado di aiutarmi? Grazie!!!:)
aaa
13/05/12 14:43
Phi
Dovrebbe darti errore 216 (segmentation fault) qui:

case (p^.next^.val+q^.next^.val)of


Nel primo passaggio tu non hai ancora allocato ne p^.next ne q^.next.
E così ?

Edit: A dir la verità ora noto che non imposti mai il valore del campo next. Dovresti farlo quando leggi la lista.
Ultima modifica effettuata da Phi 13/05/12 14:48
aaa
14/05/12 5:31
fabioser
Intanto grazie mille per avermi risposto. Tuttavia ti devo precisare che i valori p^.next e q^.next sono noti, in quanto ne ho già effettuato l'acquisizione tramite le due procedure LeggiEScriviLista(p,m), applicata alla lista p di dimensione m e LeggiEScriviLista(q,n), applicata alla lista q di dimensione n<=m!!!Grazie tante per i suggerimenti che vorrai proporre per la mia soluzione del problema.
aaa
14/05/12 12:36
Phi
Postato originariamente da fabioser:

Tuttavia ti devo precisare che i valori p^.next e q^.next sono noti, in quanto ne ho già effettuato l'acquisizione tramite le due procedure LeggiEScriviLista(p,m)


Sei sicuro. Non vedo mai un "next:=".
Purtroppo ho problemi a leggere la lista come vai tu quindi ho apportato una piccola modifica(potrebbe dipendere dal differente compilatore, chissà;).
Secondo me dovresti iniziare così:

uses crt;

[ ... ]

procedure LeggiEScriviLista( var p : punt; next: punt; k : integer);
begin
	if k=0 then p:=nil
	else begin
		new(p);
		repeat
			p^.val := byte(readkey)-48;
		until p^.val<10;
		if next=nil then new(p^.next)
		else p^.next:=next;
		write(p^.val,' ');
		LeggiEScriviLista(p^.back,p,k-1);
	end;
end;{ Fine procedura LeggiEScriviLista }

[ ... ]

	write('Fornire la prima lista: ');
	LeggiEScriviLista(p,nil,m);
	writeln;
	write('Fornire la seconda lista: ');
	LeggiEScriviLista(q,nil,n);

[ ... ]


Tuttavia non è ancora a posto. Ti darà ancora errore di segmentazione quando, durante la somma, arriverai ad avere k=0. Però meglio risolvere un problema alla volta.
Ultima modifica effettuata da Phi 14/05/12 12:37
aaa
14/05/12 16:32
fabioser
Grazie per il tuo prezioso consiglio. Proverò ad essere più chiaro. La lista si compone di tre campi, di cui due puntatore ( back e next ) perchè ho necessità di percorrerla in tutti e due i sensi ovvero da sinistra a destra e da destra a sinistra. Quindi avevo pensato di far puntare a nil sia il primo che l'ultimo elemento, e poi di scandirla a ritroso in forma ricorsiva, creando le n o le m istanze necessarie. Ti ripropongo la procedura di acquisizione che ho corretto perchè ho ripetuto il valore di k e pertanto non mi ero accorto del fatto che tale variabile ripetuta cadeva nel caso delle note regole di campo d'azione. Dimmi esattamente dove ho sbagliato, poichè quando il compilatore (ma devo provare ancora il programma su Lazarus che è meglio di dev-Pascal) dovrebbe stamparmi la lista (da write('p^.val,' ' in sequenza per le n istanze) mi si chiude la pagina. Non trovi il next:='', perchè suppongo appunto di procedere dall'ultimo al primo elemento della lista con ciascuno che punta il precedente.

type punt=^elem;
     elem= record
                 val: integer;
                 back : punt;
                 next : punt;
           end;
var p,q,s : punt;
    m,n,k : integer;

procedure LeggiEScriviLista( var p : punt; t : integer);
begin
     if k=0
     then p:=nil
     else begin
               new(p);
               read(p^.val);
               write(p^.val,' ');
               LeggiEScriviLista(p^.back,t-1);
          end;
end;{ Fine procedura LeggiEScriviLista }


Grazie per l'aiuto e scusa per il disturbo.:)

P.S. poichè già l'istruzione read è di per se sufficiente ad attribuire il valore al p^.val della singola istanza ho pensato di risparmiare l'istruzione di assegnazione (correggimi se sbaglio).
aaa
14/05/12 17:07
Phi
suppongo appunto di procedere dall'ultimo al primo elemento della lista con ciascuno che punta il precedente.

Questo vale nella procedura di lettura.

Ma nella procedura di calcolo della somma tu chiedi p^.next^ e q^.next^, ma tu non hai mai impostato questi valori. Mentre leggi la lista non devi solo assegnare il valore richiesto a back, ma anche a next, altrimenti p^.next sarà ancora non iniziailizzato per ogni p.


Per capire meglio che problemi ha il programma sarebbe utile vederne l'output, potresti eseguirlo da prompt(se usi windows) o da terminale(se usi linux) e poi postare tutto l'output.
aaa
15/05/12 5:28
fabioser
Intanto ti ringrazio ancora per la pazienza e la cortesia che dimostri nell'interessarti al mio problema. Tuttavia voglio qui sollevare un' eccezione a quanto dici.Come ti ho già spiegato, secondo il mio parere i vari valori p^.val della lista p (ed analogamente della lista q) sono noti, perchè scanditi uno per uno dalle varie k=0,k=1,..,k=n-1,k=n istanze della procedura ricorsiva LeggiEScriviLista. Pertanto ad ogni valore di k corrisponde un solo valore della lista p (o q) noto, perchè già acquisito tramite la procedura LeggiEScriviLista. Di conseguenza i valori della somma p^.next+q^.next ai quali puntano p^.val e q^.val, in corrispondenza del generico elemento k della lista, dovrebbero essere noti anch'essi ( perchè già acquisiti tramite la solita procedura), e dare l'elemento somma corrispondente a k, s^.val...correggimi se sbaglio...:-?
aaa