[ADA] Erreur dans un intervalle ?

Discutez d'informatique ici !
Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

[ADA] Erreur dans un intervalle ?

par Rockleader » 09 Mar 2013, 12:50

Bonjour, j'ai un petit soucis sur un programme qui compile comme il faut; mais lorsque j'exécute; voici ce qui s'affiche à l'écran:

raised CONSTRAINT_ERROR : romain.adb:21 range check failed


Si je comprends bien l'erreur; elle se situerait sur un intervalle de ma ligne 21:

Code: Tout sélectionner
Cca(indice..indice+lg):=ChiffreRomain'image(Cro);



Voici le code complet des sous programmes; le but final étant de convertir des nombres romains en nombres compréhensibles par tout le monde^^
Ici il y aura plusieurs sous programmes qui viendront après; mais à priori il y a une erreur dans celui de concatenation qui n'ets pas remarqué à la compilation

Code: Tout sélectionner
with entrees_sorties;use entrees_sorties;

procedure romain is

ENTIER_MAX:constant integer:=4999;
LG_MAX:constant integer:=20;
subtype EntierRomain is integer range 1..ENTIER_MAX;
type ChiffreRomain is (M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I);
type NombreRomain is record
      ch:string(1..LG_MAX);
      Ch_eff:Natural; -- longueur réelle de la chaîne
      val:EntierRomain;
end record;
type TabConversion is array (ChiffreRomain range M..I) of Natural;
VAL_ROMAIN: constant TabConversion:=(1000,900,500,400,100,90,50,40,10,9,5,4,1);

procedure concatenation (Cro:in ChiffreRomain;Cca:in out string;indice:in out Natural) is
   lg:Natural;
   begin
         lg:= ChiffreRomain'image(Cro)'length;
         Cca(indice..indice+lg):=ChiffreRomain'image(Cro);
         indice:=indice+lg;
   end concatenation;

Cro:ChiffreRomain:=CD;
indice:Natural:=3;
Cca:string(1..indice);

begin

concatenation(Cro,Cca,indice);
put(CCa);

end romain;



On passera sur d'éventuels nom de variables mal choisies :) je ne fais que reprendre les noms de variables imposées dans les exercices --'



Si quelqun voit d'où vient le problème je lui en serait bien reconnaissant parce que j'avoie que depuis ce matin je ne trouve pas du tout ce qui empêche la compilation. Mais j'avoue un peu avoir du mal avec les chaîne de caractère donc j'ai peut être fait un truc de travers.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 09 Mar 2013, 13:33

Hello,

au hasard. Que vaut lg, que vaut ChiffreRomain'image(Cro);
est-ce que ChiffreRomain'image(Cro); est de type string?
peux-tu au lieu de concaténer ecrire
cca(1..lg)=ChiffreRomain'image(Cro); ?

et probablement si tu déclares ton string de taille indice(==3), tu peux pas accéder "comme ca" aux indices style 4 ou plus.

Es-tu sur que tu peux?
As tu essayé un stupide
Cca:string(1..3);
Cca(4)='c';

moyennant la syntaxe....
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 09 Mar 2013, 14:24

fatal_error a écrit:Hello,

au hasard. Que vaut lg, que vaut ChiffreRomain'image(Cro);
est-ce que ChiffreRomain'image(Cro); est de type string?



lg vaut 1 ou 2 à chaque fois, à priori dans l'exemple que j'ai testé il vaut 2.
ChiffreRomain'image(Cro) dans mon exemple vaut CD; avec l'attribut lenght à coté on obtient la taille de CD soit 2 que j'affecte à lg.

ChiffreRomain est un type énuméré que je crée qui contient tout les nombres romains. le 'image(Cro) permet théoriquement de transformer si je puis dire le valeur énuméré de Cro (CD ici) en une chaîne de caractère CD.



cca(1..lg)=ChiffreRomain'image(Cro); ?


Je n'ai pas testé ça; mais vu que je suis obligé de concaténer il faut bien que je rajoute l'indice.

A la limite 1..indice+lg serait plus logique ?

et probablement si tu déclares ton string de taille indice(==3), tu peux pas accéder "comme ca" aux indices style 4 ou plus.



Oui; une fois mon string déclaré de taille 3; il n'y a rien après; c'est comme un tableau on alloue un espace en mémoire pour la taille du string; ou du moins c'est ce que j'ai compris.


As tu essayé un stupide
Cca:string(1..3);
Cca(4)='c';


Je n'ai pas essayé mais à priori ça ne devrait pas marcher. Parce qu'ici on essaie d'affecter une valeur à la case 4 si je puis dire qui n'a pas été réservé pour ça.
La différence avec mon programme c'est que je met à jour la taille du string avec l'indice.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 09 Mar 2013, 14:58

Je n'ai pas testé ça; mais vu que je suis obligé de concaténer il faut bien que je rajoute l'indice.

c'est pour tester que ton assignation est correcte. Inutile de tester la concaténation si tu peux même pas assigner.


Je n'ai pas essayé mais à priori ça ne devrait pas marcher. Parce qu'ici on essaie d'affecter une valeur à la case 4 si je puis dire qui n'a pas été réservé pour ça.

eh ben testes le!

La différence avec mon programme c'est que je met à jour la taille du string avec l'indice.

ah bon, ou ca?
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 09 Mar 2013, 15:15

ah bon, ou ca?


Et bien lorsque je fais

Code: Tout sélectionner
Cca(indice..indice+lg):=ChiffreRomain'image(Cro);


L'indice est entré dans l'entête de la procédure et lg est automatiquement calculé de sorte que l'intervalle soit correct.


Dans mon exemple il y avait certes des erreurs que j'ai rectifié.

J'ai initialisé ma chaine de caractère en entrant "" de façon à ce qu'elle soit vide.
J'ai rentré un indice donc de 0 puisque la chaine est vide.
et Cro vaut toujours CD.

lg=2.

Donc mon string (0..2) = "" + "CD" = "CD"
indice=0+2 = 2

De sorte que C va être rangé dans la case 0 du string;D dans la case 1; c'est peut être là qu'est l'erreur non ? la case 2 du string n’est pas affecté.
Pourtant lorsque je reteste comme ça le même problème survient.




Code: Tout sélectionner
As tu essayé un stupide
Cca:string(1..3);
Cca(4):='c';



Je l'ai testé et le résultat est bien comme je le dis:


romain.adb:37:05: warning: value not in range of subtype of "Standard.Integer" defined at line 27
romain.adb:37:05: warning: "Constraint_Error" will be raised at run time




On sort de l'intervalle donc il est normal que l'affectation ne puisse pas se faire...là l'erreur apparaît à la compilation et non à l’exécution.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 09 Mar 2013, 15:30

il faut vraiment que tu arrives à réfléchir plus que les questions que jpose.

eh ben testes le!

ah pour but de te faire réfléchir sur les accès à des index qui sont pas dans le range 1..3.
Tu testes cca(1..4), ca pete.
pourquoi est-ce que cca(indice...indice+1) ca marcherait si indice=3...

Ensuite,
De sorte que C va être rangé dans la case 0 du string;D dans la case 1; c'est peut être là qu'est l'erreur non ? la case 2 du string n’est pas affecté.

c'est bien tu te poses la question. Pourquoi tu testes pas avec indice=2 alors!!

Ensuite je sais même pas pourquoi tu t'emmerdes avec ta fonction qui marche pas.
Tu peux pas simplement tester des cas triviaux?
Cca:string(1..2);
Cca(1)='C'
Cca(1..2)="CD"
Cca(1..2)=CD

parce que si ci-dessus ca marche, alors tout ce que tu as besoin, cest de redimensionner ton string...ou de creer un string plus grand.
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 09 Mar 2013, 16:00

Cca(1)='C' ==> Marche

Cca(1..2)="CD" ==> Marche
Cca(1..2)=CD ==> Ne marche pas; ce qui est normal puisque là je rentre un type ChiffreRomain et non une chaine de caractère.



Lorsque dans ma ligne je fais

ChiffreRomain'image(Cro);

On a L'image en chaîne de caractère de la variable Cro; c’est donc bien une chaîne de caractère ici.
Dans le doute, j'ai testé en écrivant

"ChiffreRomain'image(Cro)";

Même résultat la compilation passe; et je me retrouve avec la même erreur.




Tout cela me pousse à croire qu'il s'agit bien d'une erreur d'intervalle mais je ne vois pas où....
Dans la déclaration de Cca je lui ai affecté une taille plus grande 1..20 et même erreur...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 09 Mar 2013, 16:23

Code: Tout sélectionner
with Ada.Text_IO; use Ada.Text_IO;
procedure Hello is
type ChiffreRomain is (CD, M);
s: String(1 .. 2);
Cro:ChiffreRomain:=CD;
Crp:ChiffreRomain:=M;
begin
  s(1..2) :="GR";
  s(1..2) := ChiffreRomain'image(Cro); -- CD is length 2
  put_line(s); -- expects CD
 
  s(1..1) := ChiffreRomain'image(Crp); -- M is length 1
  put_line(s); -- expects MD
end Hello;
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 09 Mar 2013, 16:35

Bon, alors j'ai refait tout un tas de test, j'ai écouté tes conseil et je ne me suis pas occupé de la fonction; je l'ai juste entré dans le corps du programme; ce qui m'a permis de vérifier que j'avais une erreur d'intervalle et de la vérifier.

Le code correct est donc

lg:= ChiffreRomain'image(Cro)'length;
Cca(indice+1..indice+lg):=ChiffreRomain'image(Cro);
indice:=indice+lg;




J'ai testé dans le corps du programme et ça a très bien marché.

Du coup j'ai remis tout ça dans la fonction:

procedure concatenation (Cro:in ChiffreRomain;Cca:in out string;indice:in out Natural) is
lg:Natural;
begin
lg:= ChiffreRomain'image(Cro)'length;
Cca(indice+1..indice+lg):=ChiffreRomain'image(Cro);
indice:=indice+lg;
end concatenation;



Et je l'ai testé;


Cca(1..2):="CD";new_line;
concatenation(Cro,Cca(1..2),indice);
put(Cca(1..indice));

qui compile;

et ça me ressort

raised CONSTRAINT_ERROR : romain.adb:21 range check failed


lorsque j'exécute.


Alors pourquoi est ce que ça marchait en brut; et cela ne marche plus lorsque je passe par la fonction ?

Aurais je fais une maladresse lors de l'appel de la sous procédure ?

Là je comprends vraiment pas surtout que j'ai bien corrigé l'erreur d'intervalle.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 09 Mar 2013, 16:39

Cca(1..2) c'est une chaine de taille 2.
Pourquoi t'essaies d'accéder à l'indice 3 de Cca?
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 09 Mar 2013, 16:50

fatal_error a écrit:Cca(1..2) c'est une chaine de taille 2.
Pourquoi t'essaies d'accéder à l'indice 3 de Cca?


Et bien comme tu viens de le dire parce que Cca est de taille 2; donc pour continuer de la remplir il faut bien se décaler d'une position et donc aller en 3.


Concrètement je rentre

Un chiffre romain (M), Une chaine de taille 2 (CD), l'indice 2 (car chaine de taille 2)

lg =1
Cca(3..3) = 'M'
indice = indice+lg = 2+1 = 3


Donc Cca(1..2) n'a pas été modifié
J'ai ajouté Cca(3) = M

ET si j'affiche Cca (1..3) j'obtiens CDM

Voilà comment ça devrait fonctionner.

Je dirais même plus voilà comment ça fonctionne lorsque je ne passe pas par la fonction.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 09 Mar 2013, 16:54

... :marteau:

Ta taille de chaine c'est 2.
tu peux pas accéder a l'élément 3 avec un string de base de taille 2
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 09 Mar 2013, 16:56

Ben pourtant je l'ai fais dans le corps de la fonction et ça a marché...sachant que j'ai modifié la taille maximum de la chaîne a 20 avec une constante.





Dans ce cas comment je m'y prend pour accéder au rang suivant de la chaîne ?
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 09 Mar 2013, 17:00

Ben pourtant je l'ai fais dans le corps de la fonction et ça a marché...sachant que j'ai modifié la taille maximum de la chaîne a 20 avec une constante.


est-ce que 20 c'est égal à 2?
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 09 Mar 2013, 17:03

fatal_error a écrit:est-ce que 20 c'est égal à 2?



Ah mais bien sur !!!!!!! :marteau: :marteau: :marteau: :marteau: :marteau:


Il fallait évidemment que je rentre la taille entière de ma chaîne de caractère sinon bien sûr qu'on ne peut pas aller plus loin..

Je suis désolé c'était tout bête en fait...si seulement j'étais moins étourdies...


Merci pour ton aide !
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 10 Mar 2013, 12:04

J'ai à nouveau le même problème sur une autre fonction; elle compile très bien; mais lorsque je la teste ça ne passe pas à cause d'une erreur d'intervalle.



Code: Tout sélectionner
function creerNombreRomain (Cca: string) return EntierRomain is
      Cro:ChiffreRomain;
      i:Natural:=Cca'First;
      d:Natural:=Cca'Last;
      ConvertCro:EntierRomain;
begin
      ConvertCro:=0;
      While (i <= d-2) loop
        Cro:=ChiffreRomain'value(Cca(i..i+1));
         ConvertCro:= EntierRomain(VAL_ROMAIN(Cro)) + ConvertCro; -- on force la conversion en entier romain
      i:=i+2;           
      end loop;
      return ConvertCro;
end creerNombreRomain;




La fonction commence par convertir les 2 premiers indices de la chaîne de caractère en type énuméré. (Je n'ai pas traité le cas ou l'on est qu'un seul nombre j'en conviens mais c'est trivial)
Et ce type énuméré est converti en entier par le bien d'un tableau défini tel quel.


Code: Tout sélectionner
type ChiffreRomain is (M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I);
type TabConversion is array (ChiffreRomain range M..I) of Natural;
VAL_ROMAIN: constant TabConversion:=(1000,900,500,400,100,90,50,40,10,9,5,4,1);
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 10 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite