Procedura aperta, scrivere e aggiungere in Ada
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:
- X_File: Seq_Float_IO.File_Type;
- File_Name: String;
|
sottotipo di vincoli non ammessi (inizializzazione bisogno) fornire un valore iniziale o limiti di matrice esplicite
- File_Name: String;
|
Non lo so 2 cose:
- 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"
- 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
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 );