Manipulation de string [Résolu]

Signaler
Messages postés
41
Date d'inscription
vendredi 30 janvier 2004
Statut
Membre
Dernière intervention
18 janvier 2014
-
alcat2002
Messages postés
41
Date d'inscription
vendredi 30 janvier 2004
Statut
Membre
Dernière intervention
18 janvier 2014
-
j'ai un string du style:

0___0_0____0___00_____0________0__


'O' -> la goutte est tombée
'_' -> la goutte n' est pas tombée


et j'aimerai trouver une fonction qui me signale quand mon 'robinet' fuit de maniere
constante :

0___0___0___0___0___0___0___0

ou encore:
00_____00_____00_____00_____


voila ..dur! dur! et merci a ceux qui pouront m'aider!

AlcAt

50 réponses

Messages postés
6
Date d'inscription
dimanche 3 octobre 2010
Statut
Membre
Dernière intervention
5 février 2011

Bonjour;
le cas :
00__00__00__00__00__00

a mon avis on change carrement de sujet vue que dans ce cas on parle d'ensemble de goutes constantes

pour moi c'est simple ce cas n'est pas constant .

pour résumer je te conseil des faire ce qu'on appel un intervalle de référence

function GetFirst0(text: string): Byte;
var
  I: byte;
begin
  for I := 1 to Length(text) do
    if Text[i] = '0' then
    begin
     Result := i;
     exit
    end;
end;

function GetLast0(text: string): Byte;
var
  I: Byte;
begin
  for I := Length(text) downto 1 do
   if text[i] = '0' then
   begin
     result := i;
     exit
   end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Byte;
  Pinterval: Byte;
  interval: Byte;
  count0: Byte;
begin
  for I := GetFirst0(Edit1.Text) to GetLast0(Edit1.Text) do
  begin
    if Edit1.Text[i] = '0' then
    begin
      inc(Count0);
      if Count0 = 2 then Pinterval := interval
      else if interval <> Pinterval then
           begin
             ShowMessage('irregulier');
             Exit
           end;
      interval := 0
    end
    else inc(interval);
  end;
  ShowMessage('Regulier');
end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (key in ['_','0',#8]) then key := #0
end;


il faudra juste joué avec la valeur 2 de la ligne
if Count0 = 2 then Pinterval := interval  


ps: je ne suis pas sur du résultat j'ai pas delphi sur cette machine
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
Bonjour quand même,

« [i]j'aimerai trouver une fonction qui me signale quand mon 'robinet' fuit de maniere
constante /i»

On trouve de drôles de trucs sur le site mais, franchement, il y a peu de chances qu'un développeur ait déjà publié une telle fonction (je ne vois que Francky... Et encore! Il s'intéresse plus aux gaz qu'aux liquides).

Tu peux toujours regarder dans l'Aide Delphi à la rubrique 'Pos'.
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
... et même 'PosEx' (c'est mieux pour les fuites).

« j'aimerai trouver une fonction qui me signale quand mon 'robinet' fuit de maniere
constante » je ne vois que Francky... Et encore! Il s'intéresse plus aux gaz qu'aux liquides

je ne vois que Francky=> Bah alors mon Cari, un expert comme toi du bitoniau, une ptite fuite ca devrait pas te poser problème ;)

Plus objectivement je procéderais ainsi, je créerais une fonction qui
1)Lirais chacun des caractères de ta string.
2)Si le caractère lu est 0, alors il suffit de diviser sa position dans la string par la position du premier 0 non nulle, que tu as eu.
Si le reste est nul alors tu renvoies true sinon tu renvoies False.

C'est tout simple non ?
Messages postés
41
Date d'inscription
vendredi 30 janvier 2004
Statut
Membre
Dernière intervention
18 janvier 2014

oui scusez! bonjour d'abord..
interressant ta facon de voir francky,
je supose que tu voulais dire si le reste = 1..


AlcAt
Messages postés
41
Date d'inscription
vendredi 30 janvier 2004
Statut
Membre
Dernière intervention
18 janvier 2014

par contre ca marche pour ca 0___0___0___0
effectivement
mais pas pour ca
00__00__00__00__00__00
et encore moins pour ca...
0__0___0__0___0__0___0__0___0__0

AlcAt

Effectivement Boxma les 2 exemples donnés par alcat ne correspond pas à une fuite constante

@alcat : Non le reste doit être nul et non égal à 1. Rappel d'une division euclidienne : N=D*Q+R.
Messages postés
41
Date d'inscription
vendredi 30 janvier 2004
Statut
Membre
Dernière intervention
18 janvier 2014

merci boxma! j'vais essayer ca tonight...

vous etes super cool!


AlcAt
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
La fonction suivante semble fonctionner.
Si la fonction renvoie -1, la suite n'est pas périodique. Sinon, la fonction renvoie la période:

uses  StrUtils;

function IsPeriodic(S: string): Integer;
  var    Count,Index: Integer;
         SubStr: string;
  begin
  Result := -1;
  for Count := 2 to Length(S) div 2 do begin
    for Index := 1 to Length(S) div 2 do begin
      SubStr:= Copy(S,Index,Count);
      if (PosEx(SubStr,S,Index+Count)=Index+Count)
         and (PosEx(SubStr,S,Index+Count+Count)=Index+Count+Count)
         then begin
     	  result := Count;
      	  exit;
   	end;
     end;
   end;
end;
Messages postés
6
Date d'inscription
dimanche 3 octobre 2010
Statut
Membre
Dernière intervention
5 février 2011

Bonsoir,
@Caribensila
j'avoue que je n'est pas bien ton compris code
ça seré sympa d'ajouter quelque détail

surtt sur le point suivant:

les 2 boucles imbrique
for Count := 2 to Length(S) div 2 do begin
    for Index := 1 to Length(S) div 2 do begin



Merci
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
SubStr est la sous-chaîne dont tu recherches les occurences dans la suite. Mais elle peut commencer n'importe où dans la string et on ne connaît pas sa longueur a priori...

Pour comprendre les 2 boucles imbriquées, le mieux est que tu places un TMemo (avec une ScrollBar verticale) sur ta fiche, puis que tu ajoutes :

Form1.Memo1.Lines.Add(SubStr);


après

SubStr:= Copy(S,Index,Count);


Ca te semblera plus clair...
Messages postés
41
Date d'inscription
vendredi 30 janvier 2004
Statut
Membre
Dernière intervention
18 janvier 2014

merci Caribensila

pour ce code de genie!
ca marche nikel...
AlcAt
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
Merci à toi.

Mais ce n'est pas un code de génie car la fonction peut s'arrêter à une sous-période et laisser passer une période plus longue...

Le mieux serait quand même de changer le joint du robinet...
Messages postés
6
Date d'inscription
dimanche 3 octobre 2010
Statut
Membre
Dernière intervention
5 février 2011

rebonsoir
merci la rapidité de ta repense Caribensila
Messages postés
250
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
2 décembre 2019
5
Salut,
intéressant comme problème les fuites, les gouttes, les joints, les robinets, les bitoniaux ...
donc voilà régularité ou constante... je suis parti dans un truc un peu différent de caribensila, une trame qui contient peut-être une constante exemple:
0_0_0_0_0_0_0 => constante 0_
00_00_00_00_00 => constante 00_
0_00_0_00_0_00_ => constante 0_00_
0_00__0_000_0_00__0_000_0_00__0_000_ => constante 0_00__0_000_
0_00__0___0__0_0_0_0_0__000__0_0 => pas constante
Ceci est un exemple des constantes retrouvés avec le bout de code suivant
Par contre j'ai pas véritablement testé à fond, c'est juste un exemple que tu peux améliorer et optimiser.
Ps : dans le code j'ai ajouté un tableau de constante prédéfini donc... ainsi que l'information d'une nouvelle constante donc...
uses StrUtils;

const
    TabC : array [0..2] of string = ('0__','00__','0_0__');

var
    Tab : array of string;

function Search(Value: string): Boolean;
var
  I     : Integer;
  N     : Integer;
  V     : Integer;
  J     : Integer;
  NewV  : string;
begin
    Result := True;
    N := Length(Value);
    for I := 0 to High(Tab) do
    begin
        V := Length(Tab[I]);
        NewV := Value;
        for J := 1 to Trunc(N div V) do
        begin
            if Pos(Tab[I], NewV) = 1 then
            begin
                Result := False;
                NewV := Copy(NewV, V+1, N);
            end
            else
            begin
                Result := True;
                Break;
            end;
        end;
        if not Result then
        begin
            if Length(NewV) <= 1 then
            begin
                if I = High(Tab) then
                    MessageDlg('Nouvelle sorte de Constante '+Tab[I], mtInformation, [mbOK], 0);
                Break;
            end
            else
                Result := True;
        end;
    end;
end;

procedure List0_(Value, SubStr1, SubStr2: string; List1, List2: TStringList; Trie: Boolean);
var
    A       : Integer;
    B       : Integer;
    SubStr  : string;
begin
    List1.Clear;
    List1.Sorted := Trie;
    List1.Duplicates := dupIgnore;
    List2.Clear;
    List2.Sorted := Trie;
    List2.Duplicates := dupIgnore;
    SubStr := Value;
    while (Pos(SubStr1, Substr) <> 0)and (Pos(SubStr2, Substr) <> 0)  do
    begin
        A := Pos(SubStr1, Substr);
        B := PosEx(SubStr2, Substr, A);
        List1.Add(Copy(Substr, A-1, B-1));
        Substr := Copy(Substr, B, Length(SubStr));
        A := Pos(SubStr1, Substr);
        if A <> 0 then
            List2.Add(Copy(Substr, 0, A-1));
        Substr := Copy(Substr, A, Length(SubStr));
    end;
end;

function SearchReg(Value: string): string;
var
    I       : Integer;
    C       : Integer;
    D       : Integer;
    List0   : TStringList;
    List_   : TStringList;
    SubStr  : string;
    SubStr1 : string;
    SubStr2 : string;
begin
    List0 := TStringList.Create;
    List_ := TStringList.Create;
    try
        if Pos('0',Value) = 1 then
        begin
            SubStr1 := '0';
            SubStr2 := '_';
        end
        else
        begin
            SubStr1 := '_';
            SubStr2 := '0';
        end;
        SubStr := Value;
        List0_(Value, SubStr1, SubStr2, List0, List_, True);
        C := List0.Count;
        D := List_.Count;
        List0_(Value, SubStr1, SubStr2, List0, List_, False);
        if D > C then
            C := D;
        SubStr := EmptyStr;
        for I := 0 to C - 1 do
            SubStr := SubStr + List0[I] + List_[I];
        Result := SubStr;
    finally
        List0.Free;
        List_.Free;
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
    I : Integer;
begin
    SetLength(Tab, High(TabC)+ 2);
    Tab[High(Tab)] := SearchReg(Edit1.Text);
    for I := 0 to High(TabC) do
        Tab[I] := TabC[I];
    if Search(Edit1.Text)then
        ShowMessage('Irrégulier')
    else
        ShowMessage('Régulier');
end;

@+Yanb
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
Haaa mais tout dépend de la fuite!
ici au Portugal on a des fuites de ce genre là:
_0000000000_0000000_0000_00_0_________000000000000_00______________________________________
0000000000_0000000_0000_00_0_________000000000000_00______________________________________
0000000000_0000000_0000_00_0_________000000000000_00______________________________________
0000000000_0000000_0000_00_0_________000000000000_00______________________________________

En plus, vous vous compliquez trop la vie pour une fuite d' eau, alors, de gaz, je n' ose même pas imaginer!!!

Je pense qu' il nous manque donc un paramètre important qui est la quantité maximum de gouttes/non gouttes pour la séquence qui se répète:

function Recherche_Sequence_la_plus_grande(Fuite: String; MaxSequence: Integer): String;

// Cette sous-fonction vérifie que cette séquence se répète dans la fuite :)
function SequenceValide(UneSequence: String): Boolean;
var
posSequence: Integer;
Reste_a_analyser: String;
PosOk: Boolean;
begin
Reste_a_analyser := fuite;

// Recherche de la 1ere occurence de la séquence:
posSequence := pos(UneSequence, Reste_a_analyser);
PosOk := posSequence <> 0;

while posOk do
begin
Delete(Reste_a_analyser, posSequence, length(UneSequence));
posSequence := pos(UneSequence, Reste_a_analyser);
posOk :p 1;
end;

Result := length(Reste_a_analyser) < length(UneSequence); // La séquence s' est bien répétée jusqu' à la fin ...
end;

var
i, s: Integer;
EtudierSequence: String;
begin
Result := '';

for i := 1 to length(Fuite) do
for s:= 1 to Length(MaxSequence) do
begin
EtudierSequence := Copy(Fuite, i, s);

if SequenceValide(EtudierSequence)
then
if Length(EtudierSequence) > Length(Result)
then Result := EtudierSequence;
end;
end;

la fonction peut très bien être appelée comme ça:
SequenceTrouvee := Recherche_Sequence_la_plus_grande(Fuite, Length(fuite));

Voilà,

Composants Cindy pour Delphi
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
Arg, je reposte car j' avais bien indenté:

function Recherche_Sequence_la_plus_grande(Fuite: String; MaxSequence: Integer): String;

    // Cette sous-fonction vérifie que cette séquence se répète dans la fuite :) 
    function SequenceValide(UneSequence: String): Boolean;
    var 
      posSequence: Integer;
      Reste_a_analyser: String;
      PosOk: Boolean;
    begin
      Reste_a_analyser := fuite;

      // Recherche de la 1ere occurence de la séquence: 
      posSequence := pos(UneSequence, Reste_a_analyser);
      PosOk := posSequence <> 0;

      while posOk do 
      begin
        Delete(Reste_a_analyser, posSequence, length(UneSequence));
        posSequence := pos(UneSequence, Reste_a_analyser);
        posOk :p 1;
      end;

      Result := length(Reste_a_analyser) < length(UneSequence); // La séquence s' est bien répétée jusqu' à la fin ...
    end;

var 
  i, s: Integer;
  EtudierSequence: String;
begin
  Result := '';

 for i := 1 to length(Fuite) do 
   for s:= 1 to Length(MaxSequence) do 
   begin
     EtudierSequence := Copy(Fuite, i, s);

     if SequenceValide(EtudierSequence)
     then 
       if Length(EtudierSequence) > Length(Result)
       then Result := EtudierSequence;
   end;
end;
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
Cette fois j' ai testé et ça marche impecc' :

procedure Tform1.cySpeedButton2Click(Sender: TObject);

    function Recherche_Sequence_la_plus_petite(Fuite: String; MaxSequence: Integer): String;

        // Cette sous-fonction vérifie que cette séquence se répète dans la fuite :)
        function SequenceValide(UneSequence: String): Boolean;
        var
          posSequence: Integer;
          Reste_a_analyser: String;
          PosOk: Boolean;
        begin
          Reste_a_analyser := fuite;

          // Recherche de la 1ere occurence de la séquence:
          posSequence := pos(UneSequence, Reste_a_analyser);
          PosOk := posSequence <> 0;

          while posOk do
          begin
            Delete(Reste_a_analyser, posSequence, length(UneSequence));
            posSequence := pos(UneSequence, Reste_a_analyser);
            posOk :posSequence 1;
          end;

          Result := length(Reste_a_analyser) < length(UneSequence); // La séquence s' est bien répétée jusqu' à la fin ...
        end;

    var
      i, s: Integer;
      EtudierSequence: String;
    begin
      Result := '';

     for i := 1 to length(Fuite) do
       for s:= 1 to MaxSequence do
       begin
         EtudierSequence := Copy(Fuite, i, s);

         if SequenceValide(EtudierSequence)
         then
           if (Result = '') or (Length(EtudierSequence) < Length(Result))
           then Result := EtudierSequence;
       end;
    end;

var fuga: String;
begin
  fuga := '_0000000000_0000000_0000_00_0_________000000000000_00______________________________________' +
          '0000000000_0000000_0000_00_0_________000000000000_00______________________________________' +
          '0000000000_0000000_0000_00_0_________000000000000_00______________________________________' +
          '0000000000_0000000_0000_00_0_________000000000000_00______________________________________';

  cySpeedButton2.Caption := Recherche_Sequence_la_plus_petite(Fuga, length(fuga));
end;




Composants Cindy pour Delphi
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
'_0000000000_0000000_0000_00_0_________000000000000_00______________________________________' +
'0000000000_0000000_0000_00_0_________000000000000_00______________________________________' +
'0000000000_0000000_0000_00_0_________000000000000_00______________________________________' +
'0000000000_0000000_0000_00_0_________000000000000_00______________________________________';


...
Ce ne serait pas une fuite de chasse d'eau, ça ?
Messages postés
41
Date d'inscription
vendredi 30 janvier 2004
Statut
Membre
Dernière intervention
18 janvier 2014

whaou!j'en reste baba...je vais tester des que je trouve le temps!
respect!!!

AlcAt
1 2 3