précédent | suivant | table des matières

Exemple  3 : définition d’une classe Chaîne de caractères

Définition d’une classe Chaine semblable à la classe String. Les Objets ne la classe Chaine sont immuables ou constants ( leur valeur ne peut pas changer).



public final class Chaine implements Comparable { 
    private char rep[];
    private int longueur;

Constructeurs

   /**
    * Initialise une instance de <code>Chaine</code> avec la chaîne vide
   **/
   public Chaine() {
      rep = new char[0];
      longueur = 0;
   }

   /**
    * Initialise une instance de <code>Chaine</code> avec la chaine de
    * caractères en argument. Les chaines de caractères étant immuables,
    * elles peuvent partager leur représentation.
    * @param original une <code>Chaine</code>.
   **/
   public Chaine(Chaine original) {
      this.longueur = original.longueur;
      this.rep = original.rep;
   }

   /**
     * Initialise une instance de <code>Chaine</code> de telle façon
     * qu'elle ait pour valeur la chaine des caractères contenue
     * dans le tableau. Les caractères sont copiés.
     * @param tab un tableau de caractères
     * @throws NullPointerException si <code>tab</code> est
     * code>null</code>.
   **/
   public Chaine(char tab[]) {
     this.longueur = tab.length;
     this.rep = (char[])tab.clone();
   }

   
/** * Initialise une <code>Chaine</code> avec une partie du tableau en argument. * <code>deb</code> est l'indice du premier caractère * de la partie de tableau et * <code>l</code> le nombre de caractères du sous-tableau. * * @param tab le tableau source. * @param deb le début de la partie. * @param l la longueur de la partie. * @exception ChaineIndexOutOfBoundsException si <code>deb</code> * et <code>l</code> sont en dehors des bornes du * tableau <code>tab</code>. * @exception NullPointerException si <code>tab</code> est * <code>null</code>. **/ public Chaine(char tab[], int deb, int l) { if (deb < 0) throw new ChaineIndexOutOfBoundsException(deb); if (l < 0) throw new ChaineIndexOutOfBoundsException(l); if (deb > tab.length - l) throw new ChaineIndexOutOfBoundsException(deb + l); this.longueur = l; this.rep = new char[l]; System.arraycopy(tab, deb, this.rep, 0, l); }

Longueur, charAt(i)


   /**
    * Retourne la longueur de la chaîne.
    * La longueur est le nombre de caractères de la chaine.
    * @return la longueur de la chaîne.
   **/
   public int length() {
         return longueur;
   }

   /**
    * Retourne le caractère à l'indice spécifié en paramètre. 
    * Un indice va de <code>0</code> à <code>length() - 1</code>.
    * Le premier caractère est à l'indice <code>0</code>,
    *
    * @param index l'indice du caractère.
    * @return le caractère à l'indice spécifié.
    * @exception ChaineIndexOutOfBoundsException si <code>index</code>
    * est négatif ou plus grand ou égal à la longueur de 
    *la chaîne.
   **/
   public char charAt(int index) {
        if ((index < 0) || (index >= longueur))
           throw new ChaineIndexOutOfBoundsException(index);
      return rep[index];
   }

getChars, toCharArray

   /**
    * Copie les caractère de la <code>Chaine</code> vers le 
    * tableau <code>dest</code>
    * <p>
    * Le premier caractère est copié à l'indice <code>srcDeb</code>;
    * le dernier caractère est copié à l'indice <code>srcFin-1</code>
    * le nombre total de caractères copiés est 
    * <code>srcFin-srcDeb</code>.
    * Les caractères sont copiés dans <code>dest</code> à partir
    * de l'indice <code>dstDeb</code>
    * @param srcDeb indice dans la chaine du premier caractère à copier.
    * @param srcFin indice qui suit l'indice du dernier  caractère à copier
    * @param dst le tableau destination
    * @param dstDeb l'indice de début dans le tableau destination
    * @exception ChaineIndexOutOfBoundsException Si <ul><li><code>srcDeb</code> est négatif.
    * <li><code>srcDeb</code> est plus grand
    * que<code>srcFin</code>
    * <li><code>srcFin</code> est plus grand que la longueur de la Chaine
    * <li><code>dstDeb</code> négatif
    * <li><code>dstDeb+(srcFin-srcDeb)</code> est plus grand que
    * <code>dst.length</code></ul>
    * @exception NullPointerException si <code>dst</code> est<code>null</code>
   **/
   public void getChars(int srcDeb, int srcFin, char dst[], int dstDeb){
      if (srcDeb < 0) throw new ChaineIndexOutOfBoundsException(srcDeb);
      if (srcFin > longueur) throw new ChaineIndexOutOfBoundsException(srcFin);
      if (srcDeb > srcFin) throw new ChaineIndexOutOfBoundsException(srcFin - srcDeb);
      System.arraycopy(rep, srcDeb, dst, dstDeb, srcFin - srcDeb);
   }
   
   /**
    * Convertit la chaine en un tableau de caractères.
    *
    * @return un tableau de caractères contenant les caractères de la chaîne.
   **/
   public char[] toCharArray() {
       char resultat[] = new char[longueur];
       for( int i = 0; i< longueur; ++i) 
           resultat[i] = rep[i];
       return resultat;
   }

Comparaisons


   /**
    * Compare cette chaîne à l'objet en paramètre.
    * Le résultat est <code>true</code> si et seulement si l'objet est différent 
    * <code>null</code> et si l'objet est une instance de
    * <code>Chaine</code> qui contient la même séquence de caractères.
    * @param unObjet l'objet à comparer à la <code>Chaine</code>.
    * @return <code>true</code> si <code>Chaine</code> et 
    * le paramètre sont égaux
    * <code>false</code> sinon.
    * @see compareTo
    * @see equalsIgnoreCase
   **/
   public boolean equals(Object unObjet) {
       if (this == unObjet) return true;// le même objet
       if (unObjet instanceof Chaine) {
          Chaine c = (Chaine)unObjet;
          if (longueur == c.longueur) {
            for (int i = 0; i<longueur; ++i)
                if (rep[i] != c.rep[i]) return false;
            return true;
         }
      }
      return false;
   }


   /**
    * Compare deux chaines pour l'ordre lexicographique.
    * La comparaison estt basée sur la valeur unicode de chacun des caractères.
    * Le résultat est un entier négatif si l'objet <code>Chaine</code> précède 
    * lexicographiquement l'argument chaine.
    * Le résultat est 0 si les chaines sont égales.
    * Deux chaînes sont différents si :
    * <ul><li>il existe un indice tel que les
    * caractères au même indice dans les deux chaines sont différents
    * <li> si les deux chaines ont des longueurs différentes.</ul>
    * S'il existe un plus petit indice pour lequel les deux caractères 
    * sont différents, 
    * <code>compareTo</code> retourne la différence des valeur 
    * des deux caractères.
    * s'il n'y a pas d'indice tels que les deux caractères soient différents,
    * la chaîne la plus courte est la chaîne la plus petite.
    * Dans ce cas c'est la diffréene des longueurs qui est retournée.
    *
    * @param uneChaine la <code>Chaine</code> à comparer.
    * @return la valeur <code>0</code> si les deux chaines sont égales.
    * une valeur négative si la chaîne est plus petite que 
    * le paramètre. 
    *une valeur positive si la chaîne est plus grande que la paramètre
    *
    * @exception NullPointerException si s<code>uneChaine</code> 
    * est <code>null</code>.
   **/

   public int compareTo(Chaine uneChaine) {
      int l1 = longueur;
      int l2 = uneChaine.longueur;
      int n = l1<l2?l1:l2;
      for (int i = 0; i<n; ++i)
         if (rep[i] != uneChaine.rep[i]) return rep[i] - uneChaine.rep[i];
       return l1 - l2;
   }

/** * Compare la chaîne à un Objet. Si l'objet est une chaine, * le comportement est le même que compareTo avec un paramètre chaine * Sinon, levée d'une exception <code>ClassCastException</code> : une chaine * n'est comparable qu'à une chaine. * * @param o <code>Object</code> à comparer. * @return <code>0</code>, <code><0</code> , <code>>0</code> * @exception <code>ClassCastException</code> si le paramètre * n'est pas une <code>Chaine</code>. * @see java.lang.Comparable **/ public int compareTo(Object o) { return compareTo((Chaine)o); } /** * Retourne <code>true</code> si la chaîne en paramètre est un préfixe de * la chaîne. * * @param p le prefixe. * @return <code>true</code> si le paramètre est un préfixe, * <code>false</code> sinon. * @exception java.lang.NullPointerException si<code>p</code> est *<code>null</code>. **/ public boolean startsWith(Chaine p) {       if (p.longueur>longueur) return false;       for (int i = 0; i < p.longueur; ++i)       if (rep[i] != p.rep[i]) return false;       return true; } /** * Retourne <code>true</code> si la chaîne en paramètre est un suffixe * de la chaîne. * * @param s le suffixe. * @return <code>true</code> si le paramètre est un suffixe, * <code>false</code> sinon. * @exception java.lang.NullPointerException si<code>p</code> est * <code>null</code>. **/ public boolean endsWith(Chaine s) {       if (s.longueur>longueur) return false;       for (int i = s.longueur-1, j = longueur-1; i>=0; --i, --j) if (rep[ i] != s.rep[j]) return false;       return true; }

indexOf

   /**
    * retourne l'indice de la première occurrence du caractère spécifié
    * en paramètre.
* Si le caractère n'est pas présent dans la chaîne retourne -1. * * @param ch un caractère. * @return retourne l'indice de la première occurrence du caractère * spécifié en paramètre * Si le caractère n'est pas présent dans la chaîne retourne -1. **/
public int indexOf(int ch) {       return indexOf(ch, 0); }
/** * retourne l'indice de la première occurrence du caractère spécifié * en paramètre, à partir de deb. * Si le caractère n'est pas présent dans la chaîne retourne -1. * * @param ch un caractère. * @param deb l'indice de départ. * @return retourne l'indice de la première occurrence du caractère spécifié en paramètre * Si le caractère n'est pas présent dans la chaîne retourne -1. **/ public int indexOf(int ch, int deb) {       if (deb < 0) deb = 0;       else if (deb >= longueur) return -1;       for (int i = deb ; i < longueur ; i++)  if (rep[i] == ch) return i ;       return -1; } /** * retourne l'indice de la dernière occurrence du caractère * spécifié en paramètre * Si le caractère n'est pas présent dans la chaîne retourne -1. * * @param ch un caractère. * @return retourne l'indice de la dernière occurrence du * caractère spécifié en paramètre * Si le caractère n'est pas présent dans la chaîne retourne -1. ** public int lastIndexOf(int ch) {       return lastIndexOf(ch, longueur - 1); } /** * retourne l'indice de la dernière occurrence du caractère spécifié * en paramètre, à partir de deb. * Si le caractère n'est pas présent dans la chaîne retourne -1. * * @param chun caractère. * @param deb l'indice de départ. * @return retourne l'indice de la dernière occurrence du caractère spécifié en paramètre * Si le caractère n'est pas présent dans la chaîne retourne -1. **/ public int lastIndexOf(int ch, int deb) { for (int i = (deb >= longueur) ? longueur - 1 : deb ; i >= 0; i--) if (rep[i] == ch) return i ; return -1; } /** * Retourne l'indice de la première occurrence de la chaine c * spécifiée en paramètre * retourne -1 si la sous chaîne n'est pas trouvée. * * @param c une Chaine. * @return Retourne l'indice de la première occurrence de la chaine * spécifiée en paramètre * retourne -1 si la chaîne n'est pas trouvée. * @exception java.lang.NullPointerException si <code>c</code> est * <code>null</code>. **/ public int indexOf(Chaine c) {       return indexOf(c, 0); }
/** * Retourne l'indice de la première occurrence de la sous chaine spécifiée * en paramètre à partir de deb * retourne -1 si la sous chaîne n'est pas trouvée. * * @param str une Chaine. * @return Retourne l'indice de la première occurrence de la sous chaine * spécifiée en paramètre * @exception java.lang.NullPointerException si <code>str</code> est * <code>null</code>. **/ public int indexOf(Chaine c, int deb) {       if (deb > longueur) return -1 ;       if (deb == longueur && c.longueur == 0) // il y a une chaîne vide à la fin d’une chaine          return 0;       if (deb < 0) deb = 0;       if (c.longueur == 0) // il y a une chaine vide en deb return deb;       for ( int i = deb; i<longueur - c.longueur; ++i){ int j; for( j = 0; j<c.longueur; ++j)              if(rep[i+j]!=c.rep[j]) break; if( j>=c.longueur)return i;       }       return -1; } /** * Retourne l'indice de l'occurrence la plus à droite de la chaîne en paramètre * La chaîne vide "" a une occurrence à <code>this.longueur()</code>. * La valeur -1 est retournée si pas d'occurrence * * @param c la chaîne cherchée. * @return l'indice de l'occurrence la plus à droite de si elle est trouvée, * <code>-1</code> sinon. * @exception java.lang.NullPointerException si <code>c</code> est * <code>null</code>. **/ public int lastIndexOf(Chaine c) {       return lastIndexOf(c, longueur); } /** * Retourne l'indice de l'occurrence la plus à droite à partir de <code>depuis</code> * de la chaîne en paramètre. * La chaîne vide "" a une occurrence à <code>this.longueur()</code>. * La valeur -1 est retournée si pas d'occurrence * * @param c la chaîne cherchée. * @param depuis l'indice à partir duquel la chaîne est cherchée. * @return l'indice de l'occurrence la plus à droite de si elle est trouvée, * <code>-1</code> sinon. * @exception java.lang.NullPointerException si <code>c</code> est * <code>null</code>. **/ public int lastIndexOf(Chaine c, int depuis) { if (depuis < 0) return -1; int indiceDroit = longueur - c.longueur; if (depuis > indiceDroit) depuis = indiceDroit; if (c.longueur == 0) return depuis; // chaine vide for(int i = depuis ; i>=0; --i){       int j;        for( j = 0; j < c.longueur-0; ++j) if( c.rep[j]!=rep[i]) break;       if(j>=c.longueur) return i; } return -1; }

Sous chaîne

   /**
    * Retourne la sous chaîne commençant en deb et allant jusqu'à la 
    * fin de la chaîne.
    * @paramdeb l'indice de début de la sous-chaîne.
    * @return la sous-chaîne.
    * @exception IndexOutOfBoundsException si
    * <code>deb</code> est négatif ou plus grand ou 
    * égal à la longueur de la chaîne
   **/
   public  Chaine subString(int deb) {
      return subString(deb, longueur);
   }

   /**
    * Retourne la sous chaîne commençant en deb et allant jusqu'à la fin de la chaîne.
    * @paramdeb l'indice de début de la sous-chaîne.
    * @paramfinl'indice de fin.
    * @returnla sous-chaîne.
    * @exception IndexOutOfBoundsException si
    * <code>deb</code> est négatif, ou
    * <code>fin</code> est plus grand que la longueur de la chaîne
    * ou <code>deb</code> est plus grand que<code>fin</code>.
   **/
   public Chaine subString(int deb, int fin) {
      if (deb < 0) throw new ChaineIndexOutOfBoundsException(deb);
      if (fin > longueur) throw new ChaineIndexOutOfBoundsException(fin);
      if (deb > fin) throw new ChaineIndexOutOfBoundsException(fin - deb);
       return ((deb == 0) && (fin == longueur)) ? this : new Chaine( rep, deb, fin - deb);
   }

Concaténation

   /**
    * concaténation de chaînes.
    *
    * si la longueur de la chaîne en argument est <code>0</code>, alors l'objet
    * <code>Chaine</code> est retourné. sinon une nouvelle
    * <code>Chaine</code> est créée.
    * @param c la <code>Chaine</code> qui est concaténée à la fin de l'objet
    * <code>Chaine</code>.
    * @return une chaîne qui représente la concaténation des deux chaînes.
    * @exception java.lang.NullPointerException si <code>c</code> est
    * <code>null</code>.
   **/
   public Chaine concat(Chaine c) {
      if (c.longueur == 0) return this;
      char buf[] = new char[longueur + c.longueur];
      int i;
      for( i = 0; i<longueur; ++i) buf[i] = rep[i];
      for( int j = 0; j<c.longueur; ++i, ++j) buf[i] = c.rep[j];
      return new Chaine(buf, 0, longueur + c.longueur);
   }

Divers

   /**
    * Retourne une chaîne obtenue en remplaçant toutes 
    * les occurrences du caractère
    * <code>aCar</code> par<code>nCar</code>.
    * <p>
    * Si le <code>aCar</code> n'a pas d'occurrence dans l'objet
    * <code>Chaine</code>, alors une référence à cet objet est retournée
    * sinon, un nouvel objet <code>Chaine</code> est créé, qui contient la même
    * séquence de caractères, sauf tous les <code>aCar</code> qui sont
    * remplacés par des <code>nCar</code>.
    * @param aCar l'ancien caractère.
    * @param nCar le nouveau caractère.
    * @return aune chaîne obtenue en remplaçant les <code>aCar</code>
    * par <code>nCar</code>.
   **/
   public Chaine replace(char aCar, char nCar) {
      if (aCar == nCar) return this;
      int i;
      for ( i = 0; i< longueur; ++i) if (rep[i] == aCar) break;
      if (i == longueur) return this;
      char tampon[] = new char[longueur];
      for ( i = 0 ; i<longueur ; ++i)
          tampon[i] = (rep[i] == aCar) ? nCar : rep[i];
      return new Chaine(tampon);
   }


   /**
    * Enlève les espaces en début et fin de chaîne.
    * Si la chaîne n'a pas d'espaces en début ou en fin, l'objet 
    * lui même est retourné.
    * @return la Chaîne sans les espaces de début et de fin.
   **/
   public Chaine trim() {
      int fin ;
      int deb ;
      for(deb = 0; (deb < longueur) && (rep[deb] == ' '); ++deb) ;
      if(deb == longueur)return new Chaine() ; // la chaine vide
      for(fin = longueur-1 ; (fin>=deb) && (rep[fin] == ' '); --fin) ;
      return ((deb == 0) &&(fin == longueur-1)) ? this : subString(deb, fin);
   }
   
   /**
    * retourne l'objet lui même.
    *
    * @return l'objet lui même.
   **/
   public String toString() {
      return new String(rep);
   }

   /**
    * Retourne une représentation en chaine de l'argument <code>boolean</code>.
    *
    * @param b un <code>boolean</code>.
    * @return si l'argument est <code>true</code>,une chaine égale à
    * <code>"true"</code> sinon <code>"false"</code>.
   **/
   public static Chaine valueOf(boolean b) {
        return b ? 
              new Chaine("true".toCharArray()) :
             new Chaine("false".toCharArray());
   }

/** * Retourne une représentation en chaine de l'argument <code>char</code> . * * @param c un <code>char</code>. * @return une chaine contenant le caractère c. **/ public static Chaine valueOf(char c) {       char data[] = {c};       return new Chaine(data, 0, 1); } /** * Retourne la représentation en chaine de l'argument <code>int</code>. * * @param i un <code>int</code>. * @return une chaine **/ public static Chaine valueOf(int i) { if(i==0) return new Chaine(new char[]{'0'}); int negatif = i<0?1:0; if(negatif==1) i = -i; char chiffres[]; int a = i, nbChiffres; for( nbChiffres = 0; a!=0; ++nbChiffres, a/=10); chiffres = new char[nbChiffres+negatif]; --nbChiffres; for( ; i!=0; --nbChiffres, i/=10) chiffres [nbChiffres+negatif] = (char)(i%10 +'0'); if(negatif==1) chiffres [0]='-'; return new Chaine(chiffres); } }

ChaineIndexOutOfBoundsException

public class ChaineIndexOutOfBoundsException extends RuntimeException {
    public ChaineIndexOutOfBoundsException(int ou) {
      super("ChaineIndexOutOfBoundsException en "+ String.valueOf(ou));
   }
}

haut de la page