Wyszukiwanie w listbox numerów oddzielanych przecinkiem.

0

Witam.

Posiadając listboxa z różnymi numerami oddzielonymi przecinkiem chciałbym wiedzieć jak zrobić, by te numery wędrowały do spinedit1 i spinedit2.
Listbox1 wygląda mniej więcej tak:

123123, 4234234
123124, 4234235
123125, 4234236

Żeby w spinedit1 było: 123123, a w spinedit2 było: 4234234.
Zupełnie nie wiem jak te liczby rozdzielić. Bez problemu mógłbym przenieść całą pierwszą linię listboxa do jednego spineditu, jednak ja potrzebuję zrobić tak, by było to osobno. Jest na to jakiś sposób?
Dzięki.

3

Skoro możesz pobrać określoną linię (która u Ciebie zawiera dwa numerki oddzielone przecinkiem) to opcje są przynajmniej dwie:

1) skorzystać z ExtractStrings albo innych funkcji do operowania na tekstach
2) samemu sobie przelecieć ten ciąg po kolei, znak po znaku. Jeśli mamy cyfrę, to ją doklejamy do jakiegoś stringa roboczego, jeśli mamy spację to nic nie robimy, a po trafieniu na przecinek wiemy, że skończył się pierwszy numerek, więc go przekazujemy dalej i zaczynamy odczytywanie drugiego (w ten sam sposób - znak po znaku).

4

następne sposoby:

  • funkcja Copy oraz Pos,
  • w nowszych Delphi funkcja Split.
0
cerrato napisał(a):

Skoro możesz pobrać określoną linię (która u Ciebie zawiera dwa numerki oddzielone przecinkiem) to opcje są przynajmniej dwie:

1) skorzystać z ExtractStrings albo innych funkcji do operowania na tekstach
2) samemu sobie przelecieć ten ciąg po kolei, znak po znaku. Jeśli mamy cyfrę, to ją doklejamy do jakiegoś stringa roboczego, jeśli mamy spację to nic nie robimy, a po trafieniu na przecinek wiemy, że skończył się pierwszy numerek, więc go przekazujemy dalej i zaczynamy odczytywanie drugiego (w ten sam sposób - znak po znaku).

Nie rozumiem tej drugiej opcji.
Co do pierwszej natomiast, to wygląda to tak:

extractStrings([',', ';'], [' '],   Pchar(Listbox3.Items[0]), Memo1.Lines);

tak więc te numery pojawiają się w memo1. mniej więcej więcej w ten sposób:

242342
423423

jedna pod drugą.

Mógłbym teraz zrobić np. button z takim czymś:

Edit20.Text := memo1.lines[0];
Edit21.Text := memo2.lines[1]; ale to powoduje mały nieład i nie do końca jest tym co ja chcę. 

Wolałbym, żeby powiedzmyz listbox3 liczby zapisane do przecinka (po lewej stronie) były integerem 'a', a liczby po przecinku po prawej stronie były integerem 'b')
Da radę to zrobić w miarę prosto?

0

Nie rozumiem tej drugiej opcji.

TListBox ma właściwość Items, która jest typu TStrings. Czyli każda z linii jest osobnym stringiem.

Bierzesz takiego stringa i w jakiejś pętli bierzesz po kolei każdy znak i patrzysz, czy jest cyfrą (jeśli tak, to doklejasz to do jakiegoś stringa roboczego), a może przecinkiem - wtedy wiesz, że to, co masz w stringu roboczym jest już gotowe i możesz tą wartość przekazać dalej. A potem wczytujesz i analizujesz kolejny znak - i tak aż do końca tego stringa.

0

Hmmm.. Takie coś działa dobrze :D

Edit21.Text := ( Copy( Listbox3.Items[i], 1, 3 ));
Edit22.Text := ( Copy( Listbox3.Items[i], 6, 3 ));

Pod warunkiem, że te liczby są takiej samej wielkości (mają np. 3 cyfry).

1
Edit21.Text:=Copy(ListBox3.Items[i], 1, Pos(',', ListBox3.Items[i]);

Drugie sam się domyśl, podpowiem że możesz jeszcze użyć funkcji Length.

0

Widzialem proporcje 6 do 7. Czy zmienna będzie zawsze taka sama? Widzę że korzystasz z permutacji lub kombinatoryki. Jesli chcesz kod fachowy musisz dokładnie napisać czego oczekujesz.

1

Wyrażeniami regularnymi da się to zrobić szybciej, krócej i wygodniej.

0
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Spin;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    SpinEdit1: TSpinEdit;
    SpinEdit2: TSpinEdit;
    procedure FormCreate(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.Add('123123, 4234234');
  ListBox1.Items.Add('123124, 4234235');
  ListBox1.Items.Add('123125, 4234236');
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
i : integer;
sl : TStringList;
begin
  sl := TStringList.Create;

  i := ListBox1.ItemIndex;

  sl.Delimiter := ',';
  sl.DelimitedText := ListBox1.Items[i];
  SpinEdit1.Text := sl[0];
  SpinEdit2.Text := sl[1];

  sl.free;
end;

end.
0

Śmiga, a jeszcze mam jedno pytanie. Mianowicie. Mając:

A:= (StrToInt( Copy( Form1.Listbox3.Items[i], 1, 3 ))) 
B:= (StrToInt( Copy( Form1.Listbox3.Items[i], 6, 3 )))

i powiedzmy 10 linijek w listboxie z takimi numerami to mając

Memo3.Lines.Add(inttostr(a) + ', ' + inttostr(b));
edit24.Text := (inttostr(a) + ', ' + inttostr(b));

do memo zapisywane są wszystko liczby tak jak leci (10 linijek), a do edit tylko ostatnia linka. Jak zrobić, by do memo3 były dodawane liczby poczynając od pierwszej linijki listboxa?

1
{ Nie baw DroniC się w copy ani pos, gdy masz tylko dwie zmienne o tej samej ilości znaków.
Tak jak napisał cerrato do tego sluży np. extractStrings, gdy znajdą się ine wartości 
sam napisałeś, że dla 3 Tobie działa. Lepiej rozdzielać stringi a nie je rozdrabniać w
jakimś niewiadomym celu}

// Kod w Delphi  i w Lazarusie działa

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.Add('123123, 4234234');
  ListBox1.Items.Add('123124, 4234235');
  ListBox1.Items.Add('123125, 4234236');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
A, B : integer; // DroniC
sl, sl1 : TStringList;
begin
  sl := TStringList.Create;
  sl1 := TStringList.Create;

  for i := 0 to Listbox1.Items.Count -1 do
  begin
    sl.Delimiter := ',';
    sl.DelimitedText := ListBox1.Items[i];

    sl1.Add('Integer A : '+sl[0]);  // A strtoint(A)
    sl1.Add('Integer B : '+sl[1]);  // B strtoint(B)

    Showmessage('Integer A : '+sl[0]);
    Showmessage('Integer B : '+sl[1]);
  end;

  Showmessage('Razem zmiennych integer: '#13#10#13#10+sl1.Text+#13#10+' = '+inttostr(sl1.Count));

  sl.free;
  sl1.free;
end;

end.
0

@Bruno(M):
dla bezpieczeństwa (memory leaks) pasowało by to opakować w sekcję try ... finally

sl := TStringList.Create;
sl1 := TStringList.Create;
try 
  ...............
 ...................
finally
  sl.free;
  sl1.free;
end ;
3

@Bruno(M):

"dane wejściowe tworzą algorytmy, które nie mają prawa się pomylić,"

Takie założenie jest błędne.
Masz jakieś dane wejściowe i Twój algorytm powinien być odporny na błędy w danych.

0

grzegorz_so "w każdym elemencie listboxa jest string dający się podzielić na minimum dwa substringi"

function CountPos(const subtext: string; Text: string): Integer;
 begin
   if (Length(subtext) = 0) or (Length(Text) = 0) or (Pos(subtext, Text) = 0) then
     Result := 0
   else
     result := (Length(Text) - Length(StringReplace(Text, subtext, '', [rfReplaceAll]))) div
       Length(subtext);
end;
0

@Bruno(M): ale to jest zupełnie inny kod

3

Ogólnie zgadzam się z @grzegorz_so – jeśli kod może się wykrzaczyć, to sekcja try finally zapobiega wyciekom pamięci. Poza tym do kompletu używa się bloków try except, aby nie utracić kontroli nad przepływem sterowania w razie pojawienia się wyjątku. Jest to szczególnie ważne w temacie operowania na danych wejściowych, które mogą być prawidłowe, ale nie muszą.


Spotkałem się też z takimi mistrzami inżynierii, którzy we Free Pascalu (czyli technologii nie wspierającej GC), nigdy nie zwalniają dynamicznie alokowanej pamięci. Tzn. robią to tylko w trybie debug (zwalnianie opatrzone {$IFDEF}-ami), aby heaptrc nie wariował na koniec sesji ze zgłaszaniem co i gdzie wyciekło – zamykania komunikatów nie byłoby końca.

Po prostu program operuje na ograniczonej puli obiektów, przez co w teorii maksymalny łączny rozmiar wszystkich wycieków w danej sesji jest ograniczony, jednocześnie nie martwiąc się o wołanie Free dla każdej dynamicznie tworzonej instancji. W końcu na koniec sesji, OS sam sprzątnie pamięć zużytą przez proces. Tak stworzony program działa ciut szybciej, o koder w teorii nie przejmuje się zwalnianiem czegokolwiek.

Dla mnie to rozwiązanie jest idiotyczne i niebezpieczne – dokłada tylko roboty, wydłuża kod (dodatkowe dyrektywy) i przy braku ostrożności, pamięć może cieknąć bez końca, a więc całkowicie wykrzaczyć aplikację. Nadmienię, że takie rozwiązanie jest wykorzystywane w jednym z większych projektów, AFAIR w sofcie dla placówek medycznych (ale nie pamiętam dokładnie). No ale są ludzie i parapety.

0

tsz utwórz taką pętlę. Czy integer na to pozwoli lub extended?

O czym Panowie rozmawiamy. Ja korzystam z bigInteger, Kiedy Wam mówię, że korzystam z wielkich liczb, śmieszy Was to. Korzystam i jestem specjalistą algorytmów brute force.

1
Bruno(M) napisał(a):

tsz utwórz taką pętlę. Czy integer na to pozwoli lub extended?

Ale czemu mnie tu wzywasz na dojo? Miliardów iteracji nie udźwignie żaden komputer w sensownym czasie.

Z BigIntami pracowałem, ale nie rozumiem jakby to miało świadczyć o moje wielkości.

5
Bruno(M) napisał(a):

Ja korzystam z bigInteger, Kiedy Wam mówię, że korzystam z wielkich liczb, śmieszy Was to.

Nie, śmieszy nas to, że robisz z siebie durnia, wypisując brednie. Typ danych dobiera się według wymagań i nieistotne czy używasz liczb 8-bitowych, 16-bitowych, 32-bitowych, 64-bitowych, Big Integerów czy GUID-ów, nie czyni cię to ani lamą, ani kozakiem.

Twoje przechwałki przypominają mi dzieciaki na osiedlu – „patrz, mam cztery kółka w rowerku – jestem lepszy, bo ty masz tylko dwa!” Poważnemu człowiekowi nie wypada takich rzeczy wypisywać, bo to bardzo źle o nim świadczy, przede wszystkim z programistycznego punktu widzenia.

Korzystam i jestem specjalistą algorytmów brute force.

Każdy newbie/script-kiddie jest specjalistą od algorytmów siłowych. W końcu to najbardziej czasochłonne podejście, jakie tylko istnieje w algorytmice/programowaniu. I też nie widzę powodu, aby się tym chwalić – tym bardziej, że sporo algorytmów można zoptymalizować i znacząco zmniejszyć złożoność obliczeniową.

1 użytkowników online, w tym zalogowanych: 0, gości: 1