Come creare un array 2D in fase di runtime in Ada? [chiuso]

2

Nella programmazione Ada, qual è il modo migliore per creare una matrice 2D di una dimensione specificata dall'utente?

Mi sto insegnando Ada per lavoro (dopo molti anni di programmazione in C), e ho difficoltà a capire come creare un array di una dimensione che è nota solo al runtime ...

Il mio semplice programma deve fare quanto segue.

  1. Chiedi all'utente di digitare due numeri, per la larghezza (X) e l'altezza (Y) di una matrice di caratteri bidimensionali.
  2. Utilizza questi valori come limiti superiori dell'array (0..X-1, 0..Y-1).
  3. Inizializza la matrice con zeri.

Dopo un po 'di googling penso di esserci quasi, se faccio un codice fisso dell'array a una dimensione fissa, allora il programma funziona bene, ma mi piacerebbe che l'array fosse dimensionato secondo il desiderio dell'utente.

Il mio programma completo è il seguente, non viene compilato, ma spero sia sufficiente per dimostrare cosa sto cercando di fare.

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Characters; use Ada.Characters;

procedure test is
  type Two_Dimensional_Char_Array is array (Integer range <>, Integer range <>) of character;
  --grid : Two_Dimensional_Char_Array (0..59, 0..29) := (others => (others => ' '));
  grid : Two_Dimensional_Char_Array;

  procedure Draw_Grid(scr : Two_Dimensional_Char_Array) is
    X, Y : Integer := 0;
  begin
    Put("Width? ");
    Get(X);

    Put("Height? ");
    Get(Y);

    declare
      grid : Two_Dimensional_Char_Array(0..X-1, 0..Y-1);
    begin
      grid := (others => (others => 0));
    end;

    Put("+");
    for X in scr'First(1)..scr'Last(1) loop
      Put("-");
    end loop;
    Put_Line("+");

    for Y in scr'First(2)..scr'Last(2) loop
      Put("|");
      for X in scr'First(1)..scr'Last(1) loop
        Put(scr(X, Y));
      end loop;
      Put_Line("|");
    end loop;

    Put("+");
    for X in scr'First(1)..scr'Last(1) loop
      Put("-");
    end loop;
    Put_Line("+");
  end Draw_Grid;

begin
  grid(0,0) := 'a';
  grid(0,1) := 'b';
  grid(1,1) := 'c';
  grid(20,10) := 'd';
  grid(59,29) := 'X';
  Draw_Grid(grid);
end test;
    
posta Wossname 01.07.2015 - 10:38
fonte

2 risposte

4

La procedura migliore è utilizzare la funzione "costruttore".

Sebbene il tipo possa essere non vincolato, l'oggetto effettivo deve possedere dei limiti di tempo di compilazione sulla dimensione (a meno che non lo si allochi sull'heap).

Dovresti creare una funzione aggiuntiva per la creazione di questo array. Ecco come ho modificato il tuo codice e funziona bene (tieni presente che ho cambiato gli indici per essere basato su 1, perché odio gli indici di array basati su 0).

Inoltre nel tuo codice di esempio hai provato a inizializzare Grid con Integers ... (nonostante il fatto che Grid sia una matrice 2D di caratteri)

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure test is
  type Two_Dimensional_Char_Array is
    array (Integer range <>, Integer range <>) of Character;

  -- "constructor" function.
  function Create_Grid return Two_Dimensional_Char_Array
  is
    X, Y: Natural := 0;
  begin
    Put ("Width? ");
    Get (X);

    Put ("Height? ");
    Get (Y);

    declare
      Grid: constant Two_Dimensional_Char_Array (1 .. X, 1 .. Y) :=
        (others => (others => ' '));
    begin
      return Grid;
    end;
  end Create_Grid;

  procedure Draw_Grid(scr : Two_Dimensional_Char_Array) is
  begin
    Put ("+");
    for X in scr'Range (1) loop
      Put ("-");
    end loop;
    Put_Line ("+");

    for Y in scr'Range (2) loop
      Put ("|");
      for X in scr'Range (1) loop
        Put (scr (X, Y));
      end loop;
      Put_Line ("|");
    end loop;

    Put ("+");
    for X in scr'Range (1) loop
      Put ("-");
    end loop;
    Put_Line ("+");
  end Draw_Grid;

  -- Create grid at runtime using function.
  Grid: Two_Dimensional_Char_Array := Create_Grid;

begin
  Grid (1,1)    := 'a';
  Grid (1,2)    := 'b';
  Grid (2,2)    := 'c';
  Grid (21,11)  := 'd';
  Grid (60,30)  := 'X';
  Draw_Grid (Grid);
end test;

Inoltre c'è un bel attributo in Ada: 'Range - usato in per loop quando stai andando su un'intera gamma (che è solo una scorciatoia per' First .. 'Last)

PS: perché voi, programmatori C, siete così contrari all'uso degli spazi nel codice? Rende difficile leggere [come in: scr'First (1) .. scr'Last (1)].

    
risposta data 01.07.2015 - 11:17
fonte
1

Ecco una versione rivista:

 with Ada.Text_IO; use Ada.Text_IO;
 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
 with Ada.Characters; use Ada.Characters;

 procedure test is
    type Two_Dimensional_Char_Array is
      --  Natural range seems more appropriate
      array (Natural range <>, Natural range <>) of Character;

   procedure Draw_Grid(grid : Two_Dimensional_Char_Array) is
   begin
      Put("+");
      for X in grid'First(1)..grid'Last(1) loop
         Put("-");
      end loop;
      Put_Line("+");

      for Y in grid'First(2)..grid'Last(2) loop
         Put("|");
         for X in grid'First(1)..grid'Last(1) loop
            Put(grid(X, Y));
         end loop;
         Put_Line("|");
      end loop;

      Put("+");
      for X in grid'First(1)..grid'Last(1) loop
         Put("-");
      end loop;
      Put_Line("+");
   end Draw_Grid;

   X, Y : Natural;

 begin
    Put("Width? ");
    Get(X);

    Put("Height? ");
    Get(Y);

    declare
       grid : Two_Dimensional_Char_Array(0..X-1, 0..Y-1) := (others => (others => ' '));
    begin
       --  grid is only visible in this block

       grid(0,0) := 'a';
       grid(0,1) := 'b';
       grid(1,1) := 'c';
       grid(20,10) := 'd';
       grid(59,29) := 'X';
       Draw_Grid(grid);
    end;
 end test;
  • Draw_Grid disegna solo la griglia. Non ha bisogno di conoscere le dimensioni effettive, perché il codice che hai scritto usa 'First e 'Last attributi, che è buono. Forse sarebbe possibile accorciarlo un po 'con grid'Range , ma non ci ho provato.

  • Cambio il tipo di indice in Natural , perché non ti aspetti di avere indici negativi (che potrebbero essere possibili, ma 0..X-1 ti suggerisce di non volerlo).

  • X, Y sono dichiarati nell'ambito della procedura principale e inizializzati per primi chiedendo all'utente.

  • Quindi, grid viene dichiarato in un sottoblocco (non sarà accessibile al di fuori di questo ambito), con le dimensioni specificate.
  • Infine, compila la griglia e disegnala.

Si noti che un runtime Constraint_Error viene generato quando le dimensioni non sono abbastanza grandi: si assume che sia possibile impostare un valore a (59,29).

    
risposta data 01.07.2015 - 11:19
fonte

Leggi altre domande sui tag