le tuto sur le langage Ada n'ayant plus de forum attitré, je crée un topic pour :
vous tenir informer de l'avancement du tutoriel
répondre à vos questions, remarques ou commentaires
Vous trouverez le tutoriel à l'adresse suivante. Vous aurez sûrement remarqué que le tuto a été mis en avant par le SdZ depuis le 18 décembre dernier et qu'avec la V4 du site, il bénéficie même d'un icône "officiel" très sobre, façon Windows8. Je reviendrais au bas de ce message sur les icônes justement. Commençons par aborder l'avancement du cours.
Elle est passée inaperçue sur le site, mais deux nouveaux chapitres ont été ajoutés récemment : Les exceptions et Le multitasking. Deux chapitres plutôt ardus qui viennent clore, pour l'heure la partie IV. Un TP a été rédigé pour achever cette difficile partie IV, il sera bientôt proposer à validation. Il s'agit d'un jeu de "bataille navale" façon RPG, mettant en application les notions de POO. Je m'attaque donc enfin à la rédaction de la partie V sur GtkAda. Le premier chapitre explique ce qu'est GTK et pourquoi j'ai fait ce choix, puis dans un second temps il expliquera comment installer la bibliothèque. La première partie de ce chapitre est achevée, la seconde quasiment (il faudrait que je vérifie mon install pour Linux mais je n'ai plus de PC sous Ubuntu ). Je pense rédiger les chapitres 2 et 3 dans la semaine.
En attendant de prochaines mises à jour, voici le plan prévu et son avancement :
Partie I : Premiers pas avec Ada (validé)
Partie II : Notions essentielles (validé)
Partie III : Les types composites (validé)
Partie IV : Notions avancées et programmation orientée objet (en cours de validation)
1) Algorithmique : tri et complexité (validé)
2) Variables III : gestion bas niveau des données (validé)
3) Programmation modulaire II : encapsulation (validé)
4) Programmation modulaire III :généricité (validé)
5) Programmation modulaire IV : héritage et dérivation (validé)
6) Programmation modulaire V :polymorphisme, abstraction et héritage multiple(validé)
7) Programmation modulaire VI :finalisation et types contrôlés (validé)
8) [TP4] La bataille navale (achevé mais non validé)
9) Les exceptions (validé)
10) Le Multitasking (validé)
11) L'interfaçage avec d'autres langages (suspendu)
12) [TP5] : interfaçage d'une bibliothèque (suspendu)
Partie V : La programmation évènementielle avec GtkAda (en cours)
1) Introduction et installation (achevé à 85%)
2) Votre première fenêtre GTK (achevé mais non validé)
3) Les conteneurs I(achevé mais non validé)
4) Les signaux (40%)
5) Les widgets I (en projet)
6) [TP5] : Jeu de démineur (en projet)
7) Les conteneurs II (en projet)
8) Les Widgets II (en projet)
9) Les menus et les barres (en projet)
10) [TP6] (en projet)
Depuis quelques temps déjà, j'essaie de faire en sorte que les icônes demeurent dans les tons bleus, bleu utilisé par le logo de Ada 95 pour garder une unité de thème. L'icône officiel attribué au tuto Ada est d'un bleu légèrement différent et surtout d'un style penchant vers Windows 8, très différent du logo et des icônes utilisés jusque là. J'ai donc commencé à réaliser un nouveau pack d'icônes que je vous soumets pour comparaison :
juste un petit message pour vous indiquer que la partie V avance à grands pas puisque deux nouveaux chapitres sont terminés : "votre première fenêtre GTK" et "les conteneurs I". Le chapitre n°4 sur les signaux et callbacks est déjà bien entamé. Il sera sûrement terminé d'ici la fin de la semaine. J'espère pouvoir finir les chapitres 1, 4, 5 ainsi que le TP du chapitre 6 avant fin Mars et vous les proposer en validation.
je suis (très) en retard, mais comme vous l'avez peut-être remarqué, le tuto s'est enrichi il y a "quelques" jours de six nouveaux chapitres :
TP4 - Bataille navale : il s'agit d'un TP pas si compliqué mais plutôt long où vous devrez mettre en oeuvre les notions de POO vues précédemment.
GTKAda - Introduction et installation : on commence la programmation événementielle. Ce premier chapitre vous expliquera ce que sont GTK et GTKAda, et bien sûr comment les installer.
Votre première fenêtre : premier bout de code avec GTKAda : initialisation, boucle événementielle, fenêtre et boutons.
Les conteneurs I : première partie traitant de l'organisation de vos fenêtres. Ce chapitre n'aborde pour l'heure que des conteneurs relativement simples. D'autres seront vus plus tard car plus complexes.
Les signaux : pour faire interagir les boutons et fenêtres avec votre programme. Il s'agit certainement du chapitre principal de cette partie.
Les widgets I : un recueil des principaux widgets. Sont abordés les zones de saisie de texte, de nombre, les divers boutons ou boîtes de dialogue, les images, les textes non modifiables (étiquettes) ...
Je prépare en ce moment un nouveau TP pour mettre tout cela en pratique avant de vous proposer encore une poignée de chapitres. C'en sera alors terminé de la première version du tuto. Je m’attellerai ensuite à une grande relecture du cours afin de rectifier certains termes notamment. Mais rassurez-vous, j'ai dors et déjà d'autres idées pour d'éventuelles partie VI ou VII.
(en faisant une recherche pour savoir si quelqu'un avait recontré le même problème que moi, je suis tombé sur ce topic, je me permets de le remonter plutôt que d'en créer un nouveau, désolé c'était mieux de créer un topic à part)
J'ai un soucis dans la partie sur les signaux (chapitre V), dans la section "Connecter un signal à un callback". Jusque là, je n'ai jamais eu de soucis de compilation, mais là j'ai droit à un :
instantiation error at gtk-handlers.ads:1025
subprogram must not be deeper than access type
J'ai essayé avec le code proposé (le tout dernier, avec les deux appels à connect), et pareil, c'est la ligne 11 qui est à l'origine de ce message:
PACKAGE P_Callback IS NEW Gtk.Handlers.Callback(Gtk_Bin_Record) ;
J'ai fait une recherche sur Google, il n'y a pas des masses de résultats et souvent le même publié sur différents site en fait (=> https://groups.google.com/forum/#!topic/comp.lang.ada/DVCAP0V6Jdk). Et malheureusement, ça ne m'avance pas du tout. Donc voilà, si quelqu'un a une solution ou une piste ...?
Je veux utilliser une variable String sans limite et sans bloc declare .
Le code suivant ce compile et s'éxécute , mais rien ne se produit .
with Ada.Text_IO;
with Ada.Strings.Unbounded;
use Ada.Text_IO;
use Ada.Strings.Unbounded;
procedure autre is
var : Unbounded_String ;
transform : String := To_String(var) ;
begin
get(transform);
end autre;
- Edité par mr.pouvoir_code 28 décembre 2015 à 2:50:07
Une variable string sans limite, ça n'existe tout bonnement pas. Soit tu repousses la déclaration au maximum afin d'obtenir la taille voulue, soit tu utilises les unbounded_string, mais il faut vraiment oublier cette idée que l'on pourrait modifier la taille d'une chaîne de caractère. Dans ton exemple, tu crées une variable de type unbounded_string. Celle-ci est donc initialement vide et donc de longueur 0. Puis tu déclares un string obtenu par conversion d'un unbounded_string vide, c'est donc comme si tu écrivais : transform : String(1..0) ; Bref, une chaîne vide ! Ton Get(transform) s'effectue donc bien, sauf que saisir zéro caractère, c'est assez vite fait.
with Ada.Text_IO;
with Ada.Strings.Unbounded;
with Ada.Text_IO.Unbounded_IO;
use Ada.Text_IO;
use Ada.Strings.Unbounded;
use Ada.Text_IO.Unbounded_IO;
procedure autre is
var_string : Unbounded_String;
begin
get_line(var_string);
put(var_string);
end autre;
- Edité par mr.pouvoir_code 28 décembre 2015 à 15:38:09
Il y a des paramètres In Out, mais je pense que tu parles du mode d'ouverture des fichiers. L'idée avec les fichiers, c'est qu'on travaille sans eux la plupart du temps. On les ouvre, on copie leur contenu dans une variable et on ferme le fichier. On travaille sur cette variable autant qu'on le veut, et quand on souhaite enregistrer, on ré-ouvre le fichier, on écrit dedans (par-dessus l'existant ou à la fin) et on le referme. Si c'est un fichier texte, tu copies tout dans un string (ou à la rigueur un unbounded_string).
Quel est ton objectif général ? Je peux peut-être te donner une piste ?
Je doit créer un programme qui ouvre son code source , puis se modifie .
Ce qu'il est impossible de faire avec les 3 paramétres , par exemple pour déplacer le curseur à une ligne , puis écrire quelque chose .
Il faudrait un autre mode :
with Ada.Text_IO; use Ada.Text_IO;
Procedure Main is
Ce_Fichier : File_type ;
begin
Open
(File => Ce_Fichier ,
Mode => In_File ,
Name => "main.adb");
Set_Line (Ce_Fichier , To => 2);
Put (Ce_Fichier , "--modif_du_programme");
end Main;
- Edité par mr.pouvoir_code 30 décembre 2015 à 5:19:36
En effet, ce n'est pas possible comme tu le fais. Il faut procéder ainsi :
ouvrir en In_File
Copier tout dans un string
fermer en In_File
modifier le string
ouvrir en écriture (choisis ton mode)
Ecrire le string dans le fichier
Fermer le fichier
Pour cela, je te conseille de créer une fonction assez basique qui ouvre le fichier en In_File, puis renvoie son contenu dans un string. Ainsi, ton code deviendrait :
with Ada.Text_IO; use Ada.Text_IO;
Procedure Main is
Ce_Fichier : File_type ;
Document : Strng := Recopie(Ce_Fichier,"main.adb") ;
begin
Modifications_de(Document);
Open
(File => Ce_Fichier ,
Mode => Out_File ,
Name => "main.adb");
Put (Ce_Fichier , Document);
Close(Ce_Fichier) ;
end Main;
Pour ta fonction Recopie(), je verrais quelque chose du type :
function Recopie() return string is
res : unbounded_string ;
begin
boucle
je_met_tout_dans res ;
fin boucle
return To_String(res) ;
end ;
Désolé, c'est très schématique, mais je manque de temps là donc j'abrège.
Correspond à modifier la valeur du fichier recopié , qui est une String .
Plus précisément , écrire dedans à une position voulue .
Là , je bloque .
Il y a un moyen d'y parvenir ?
Voici le code maintenant :
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;
Procedure Main is
function Recopie() return string is
res : unbounded_string ;
Ce_Fichier : File_type ;
a_la_ligne : Positive_Count := 1 ;
begin
Open
(File => Ce_Fichier ,
Mode => In_File ,
Name => "main.adb");
loop
exit when End_Of_File(Ce_Fichier) = true ;
Set_Line (Ce_Fichier , To => a_la_ligne);
res := get_line(Ce_Fichier);
a_la_ligne := a_la_ligne +1 ;
end loop;
Close(Ce_Fichier);
return To_String(res) ;
end ;
Ce_Fichier : File_type ;
Document : String := Recopie(Ce_Fichier,"main.adb") ;
BEGIN
Set_Line (Ce_Fichier , To => 4);
-- Ces 2 lignes de code sont les modifications dans Document
Put (Ce_Fichier , "--modif_du_programme");
Open
(File => Ce_Fichier ,
Mode => Out_File ,
Name => "main.adb");
Put (Ce_Fichier , Document);
end Main;
Tes lignes 41 et 43 devraient manipuler le string Document (ou l'unbounded_string si tu préfères ou si tu as besoin) et non le fichier. Après tout dépend des modifications que tu dois faire. S'il s'agit de remplacer les majuscules par des minuscules, un string suffira. S'il s'agit de pouvoir retirer ou ajouter autant de texte que voulu, la taille de Document doit pouvoir varier, et dans ce cas, retour aux unbounded !
Le mieux serait peut-être même d'avoir une fonction Modification() qui gère les modif et renvoie le bon string. Il suffirait ainsi de remplacer tes dernières lignes par :
...
BEGIN
Open
(File => Ce_Fichier ,
Mode => Out_File ,
Name => "main.adb");
Put (Ce_Fichier , Modification(Document)); Close(Ce_Fichier);
end Main;
La fonction Modification() gèrerait toutes les modif, saisies éventuelles etc.
Mais tu trouveras également toutes les procédures et fonctions dans le fichier a-strunb.ads situé dans ./GNAT/201#/lib/gcc/i686-pc-mingw32/4.5.3/adainclude (le chemin peut varier légèrement selon les versions). J'y vois notamment ces deux primitives (va voir vers les lignes 336 pour trouver ton bonheur) :
function Insert
(Source : Unbounded_String;
Before : Positive;
New_Item : String) return Unbounded_String;
procedure Insert
(Source : in out Unbounded_String;
Before : Positive;
New_Item : String);
Un exemple d'utilisation :
...
txt : unbounded_string := Une_Valeur_Initiale_Quelconque ;
BEGIN
insert(txt,13,"Du texte en plus après le 3ème caractère") ;
append(txt,"du texte en plus à la fin") ;
--celle-là on la trouve vers la ligne 107
...
END ;
Regarde dans ce fichier .ads, tu trouveras des procédures ou fonctions pour insérer (Insert), remplacer (Replace_Slice, Replace_element), écrire à la fin ou concaténer (Append, &), ou encore écrire par dessus et supprimer (overwrite, delete). Tu trouveras également des primitives pour connaître la longueur de l'unbounded (length), l'élément placé à une certaine position (Element) ou les éléments (Slice, unbounded_slice) et également plusieurs fonctions de recherche ou de comptage (Index, Count). Commence par y jeter un oeil, je t'aiderais ensuite si besoin (mais je vais être absent un couple de jours pour les fêtes).
La procédure Get() saisit tout le texte présent dans l'objet-fichier File et l'enregistre dans le string Item (le curseur se trouve alors à la fin du fichier.
Dans ce cas , pourquoi à l'éxécution , le fichier concerné devient vide ?
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;
Procedure Main is
function Recopie return string is
res : unbounded_string ;
Ce_Fichier : File_type ;
begin
Open
(File => Ce_Fichier ,
Mode => In_File ,
Name => "main.adb");
declare
ce_fichier_string : String := To_String( Source => res );
begin
Get (File => Ce_Fichier , Item => ce_fichier_string);
res := To_Unbounded_String( Source => ce_fichier_string );
Close(Ce_Fichier);
end;
return To_String(res) ;
end ;
Ce_Fichier : File_type ;
Document : String := Recopie ;
BEGIN
Open
(File => Ce_Fichier ,
Mode => Out_File ,
Name => "main.adb");
Put (Ce_Fichier , Document);
end Main;
Edit : Sinon , il y a les boucles avec des get_line comme tu l'a sugéré , mais cette premiére méthode paraissait plus simple .
- Edité par mr.pouvoir_code 1 janvier 2016 à 12:24:02
Seulement , je continue de chercher à insérer tout le fichier , pour qu'il ne soit pas dans une seule et même ligne
Il faudrait créer des unbounded_string en boucle selon le nombre de lignes , puis faire des get_line sur ces variables et enfin , tout metre dans le fichier .
Pour l'instant je ne sais pas comment , une idée ?
with Ada.Text_IO.Unbounded_IO ; use Ada.Text_IO.Unbounded_IO ;
with Ada.Strings.Unbounded ; use Ada.Strings.Unbounded ;
with Ada.Text_IO ; use Ada.Text_IO ;
Procedure main is
this_file : File_Type ;
copy_file_1 : Unbounded_String ;
copy_file_in_1 : Unbounded_String ;
next_line : Positive_Count := 1 ;
Begin
Open
(Mode => In_file ,
File => this_file ,
Name => "main.adb" ) ;
loop
exit when End_Of_File ( this_file ) ;
Set_Line ( this_file , next_line );
get_line ( this_file , copy_file_in_1 ) ;
Append
( Source => copy_file_1 ,
New_Item => copy_file_in_1 ) ;
next_line := next_line + 1 ;
end loop ;
Close ( this_file ) ;
Open
(Mode => Out_file ,
File => this_file ,
Name => "main.adb" ) ;
put ( this_file , copy_file_1 ) ;
Close ( this_file ) ;
end main ;
- Edité par mr.pouvoir_code 6 janvier 2016 à 14:20:08
with Ada.Text_IO.Unbounded_IO ; use Ada.Text_IO.Unbounded_IO ;
with Ada.Strings.Unbounded ; use Ada.Strings.Unbounded ;
with Ada.Text_IO ; use Ada.Text_IO ;
Procedure main is
this_file : File_Type ;
copy_file_1 : Unbounded_String ;
copy_file_in_1 : Unbounded_String ;
next_line : Positive_Count := 1 ;
Begin
Open
(Mode => In_file ,
File => this_file ,
Name => "main.adb" ) ;
loop
exit when End_Of_File ( this_file ) ;
Set_Line ( this_file , next_line );
-- if next_line < 1 then
--> Le programme crée une variable unbounded_string
-- cette opération est dupliquée jusqu'à ce qu'il n'y ai plus de next_line , donc jusqu'à end_of_file()
--> get_line ( nouvelle_variable ) ;
-- Cette opération est dupliquée pour toutes les unbounded_string , précédement crée
next_line := next_line + 1 ;
end loop ;
Close ( this_file ) ;
Open
(Mode => Out_file ,
File => this_file ,
Name => "main.adb" ) ;
--put ( nouvelle_variable , copy_file_1 ) ;
-- cette opération est répété pour toutes les nouvelle variables
Close ( this_file ) ;
end main ;
- Edité par mr.pouvoir_code 7 janvier 2016 à 12:19:51
Mais je sais pas pourquoi , a l'execution 2 lignes sont rajoutés en fin de fichier
Est-ce que ça vous fait la même chose ?
WITH Ada.Text_IO ; USE Ada.Text_IO ;
WITH Ada.Text_IO.Unbounded_IO ; USE Ada.Text_IO.Unbounded_IO ;
WITH Ada.Strings.Unbounded ; USE Ada.Strings.Unbounded ;
Procedure main is
this_file : File_type ;
Type T_Tableau is array( 1 .. 1_000 ) of unbounded_string ;
case_of_array : T_Tableau ;
get_l : integer := 1 ;
-- Rôle d'intervalle dans le tableau , dans la boucle
Begin
Open
(File => this_file ,
Mode => In_file ,
Name => "main.adb");
loop exit when End_Of_File ( this_file ) ;
case_of_array(get_l) := Get_Line( this_file );
get_l := get_l + 1 ;
-- num de case du tableau & compte le nbr de get_line effectué
end loop ;
Reset ( this_file , Out_file ) ;
for i in 1 .. get_l loop
Put_line( this_file , case_of_array( i ) ) ;
end loop ;
End main ;
- Edité par mr.pouvoir_code 12 janvier 2016 à 2:56:14
est ce qu'une solution a été apportée au post du 28/06/2014 ci dessous, sachant que le problème est toujours actuel, svp.
Merci
---===-----
(en faisant une recherche pour savoir si quelqu'un avait recontré le même problème que moi, je suis tombé sur ce topic, je me permets de le remonter plutôt que d'en créer un nouveau, désolé c'était mieux de créer un topic à part)
J'ai un soucis dans la partie sur les signaux (chapitre V), dans la section "Connecter un signal à un callback". Jusque là, je n'ai jamais eu de soucis de compilation, mais là j'ai droit à un :