Domanda

Questa domanda è un follow-up del post a

Ada un'operazione di file: esemplificazione ed eccezione

A proposito di scrittura di file in Ada.

ho scelto di mettere la questione in un post a parte in modo che esso diventerà visibile a più persone, come ho già accettato una risposta su un tema leggermente diverso (che era sulle eccezioni in gestione dei file) in quella citata posta.

WITH Ada.Sequential_IO;
WITH Ada.Float_Text_IO;

PROCEDURE TEST is

package Seq_Float_IO is new Ada.Sequential_IO (Element_Type => Float);
X_File : Seq_Float_IO.File_Type;
File_Name : String;


procedure Open_Data(File : in out Seq_Float_IO.File_Type; 
Name : in String) is

BEGIN

   begin
      Seq_Float_IO.Open (
         File => File,
         Mode => Seq_Float_IO.Append_File,
         Name => File_Name );
   exception
      when Seq_Float_IO.Name_Error =>
      Seq_Float_IO.Create (
         File => File,
         Mode => Seq_Float_IO.Out_File,
         Name => File_Name);
   end;

END Open_Data;


x        : CONSTANT Float := 2.0;


BEGIN --main program
   Open_Data(X_File, "xvalues.dat");
   Seq_Float_IO.Write(File => X_File,Item => x);

   Seq_Float_IO.Close(File => X_File);
END TEST;

Sulla compilazione del sopra ottengo un errore come segue:

  1. X_File: Seq_Float_IO.File_Type;
    1. File_Name: String;             |
        
          
            

      sottotipo di vincoli non ammessi (inizializzazione bisogno)       fornire un valore iniziale o limiti di matrice esplicite

          
        

Non lo so 2 cose:

  1. Ho File_Name: String; come io voglio essere in grado di scrivere su file diversi. Quindi voglio una stringa generale e non qualcosa di simile:

File_Name: Costante String: = "one_File_Only.dat"

  1. sarebbe meglio per salvare la procedura Open_Data in annunci e ADB separati (per il corpo) file?

Grazie mille ...


NUOVO ...

Ho modificato il codice come segue:

WITH Ada.Sequential_IO;

PROCEDURE TEST1 is

package Seq_Float_IO is new Ada.Sequential_IO (Element_Type => Float);
X_File, Y_File : Seq_Float_IO.File_Type;
Name_X : CONSTANT String := "domainvalues.dat";
Name_Y : CONSTANT String := "ordinatevalues.dat";


procedure Open_Data(File : in out Seq_Float_IO.File_Type; Name : in String) is

BEGIN

   begin
    Seq_Float_IO.Open (
         File => File,
         Mode => Seq_Float_IO.Append_File,
         Name => Name_X );
    exception
      when Seq_Float_IO.Name_Error =>
         Seq_Float_IO.Create (
            File => File,
            Mode => Seq_Float_IO.Out_File,
            Name => Name_X);
   end;

END Open_Data;


x        : CONSTANT Float := 2.0;


BEGIN --main program
   Open_Data(File => X_File, Name => Name_X);
   Seq_Float_IO.Write(File => X_File, Item => x);
   Seq_Float_IO.Close(File => X_File);

   Open_Data(File => Y_File, Name => Name_Y);
  Seq_Float_IO.Write(File => Y_File, Item => x);
  Seq_Float_IO.Close(File => Y_File);

END TEST1;

Come vedi ho

Seq_Float_IO.Open (
             File => File,
             Mode => Seq_Float_IO.Append_File,
             Name => Name_X );

ho messo Name_X come il parametro che nome sta prendendo, ma questo non è giusto, come dovrei essere in grado di passare in un nome generico che può essere sia Name_X o Name_Y. Scusate ragazzi, non riesco a capire cosa mettere qui.

I sarebbe molto apprezzare il vostro aiuto. Grazie

È stato utile?

Soluzione

La cosa String pianura in Ada è che una particolare stringa, come il vostro File_Name, deve essere fissato di lunghezza; ma diverse stringhe possono essere di diversa lunghezza.

È possibile scrivere

S1 : String := "1234";
S2 : String := "12345";

nel qual caso S1 è di lunghezza 4, e le assegnazioni ad esso deve essere di lunghezza 4. È possibile scrivere

S1 := "abcd";

, ma se si tenta di scrivere

S1 := "pqrst";

o

S1 := S2;

si otterrà un Constraint_Error.

Nel caso di parametri stringa di sottoprogrammi, come il vostro Open_Data, il parametro String Name assume la lunghezza - e, naturalmente, il valore! del parametro attuale nella chiamata. Così si può dire che

Open_Data (X_File, "x.dat");
Open_Data (Y_File, "a_very_long_name.dat");

Hai problemi in precedenza con

procedure Open_Data(File : in out Seq_Float_IO.File_Type; 
                    Name : in String) is
begin
   Seq_Float_IO.Open (File => File,
                      Mode => Seq_Float_IO.Append_File,
                      Name => ????);

Sono riluttante a dire solo la risposta, in modo - prendere in considerazione la parte File => File. Il primo File è il nome del parametro formale del Seq_Float_IO.Open e il secondo File è ciò che deve essere passato, nel parametro Open_Data questo caso di File.

Potrebbe aiutare se faccio notare che ho potuto scrivere le chiamate di cui sopra come

Open_Data (File => X_File, Name => "x.dat");
Open_Data (File => Y_File, Name => "a_very_long_name.dat");

Altri suggerimenti

La risposta di @Simon Wright è corretta, e si possono trovare utile per confrontare la sua risposta alla seconda ho scritto in precedenza. Si noti che se si ha

Name_X : constant String := "domainvalues.dat";
Name_Y : constant String := "ordinatevalues.dat";

In ogni stringa, Name_X o Name_Y, potrebbero essere utilizzati come parametro attuale Name a Open_Data. Il parametro formale, Name, è di tipo String. String è vincolata, e può essere qualsiasi (implementazione definita) lunghezza massima. Al contrario, Name_X e Name_Y hanno ciascuno una lunghezza fissa determinata dalla loro assegnazione iniziale.

Addendum: Hai scritto un sottoprogramma con un parametro formale (Name) di tipo String, avendo questa firma

procedure Open_Data(
    File : in out Seq_Float_IO.File_Type;
    Name : in String) is ...

In sede di attuazione, si vuole trasmettere al Open il String state ricevute riguardo il parametro attuale (Name), non il nome di una costante globale (Name_X).

Seq_Float_IO.Open (
    File => File,
    Mode => Seq_Float_IO.Append_File,
    Name => Name );
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top