Czy dany ciąg znaków to liczba

0

Jak wyrzucić błąd podczas wczytywania danych do tablicy jeśli skrypt wpisał litere lub znak?
Jeśli będzie to liczba przechodzi dalej.

Bardzo bym prosił o jakąś wskazówkę, najlepiej kawałek skryptu.
Próbowałem try except end ale nie wychodzi. Próbowałem wczytywać wszystko do jednej tablicy a potem kopiować do drugiej z StrToInt ale była kolizja danych.

tablica jest zmiennej integer i dlatego się wszystko wykrzacza przy wpisaniu litery lub znaku. Jak to ominąć?

Bardzo prosze o pomoc.

2

Ech, ręce opadają :/ Przecież Delphi/Pascal to nie jest żaden język skryptowy!!! Co do pytania to najprostszym rozwiązaniem jest pod VCL TryStrToInt lub normalnie użycie Val (z którego i tak pod VCL korzysta tamta funkcja).

Więcej informacji o wspomnianych metodach masz na mnóstwie stron do znalezienia w Google.

0

Siedziałem kombinowałem i nadal był ten sam problem. W szczególności koliduje mi Str z Int. Próbowałem jedna i drugą opcją.

0

Pokaż kod, który niby się "wykrzacza" i opisz problem sensownie, podając dokładną treść błędu(ów).

0
var
a1 = array [0 .. 100000] of integer;
i,n :integer;
w: string;
for i := 1 to N do
    begin
      readln(t, w);
      if TryStrToInt(w) then
      begin
      a[i] := w;
      end
      else
      ShowMessage('blad');
    end;          

unit1.pas(108,10) Error: Wrong number of parameters specified for call to "TryStrToInt"
Error: Found declaration: TryStrToInt(const AnsiString;out LongInt):Boolean;
unit1.pas(110,15) Error: Incompatible types: got "AnsiString" expected "LongInt"

0

Ponownie ręce poadają. Jak można mieć jakikolwiek kłopot z zastosowaniem Val po przejrzeniu opisów z przykładowym kodem w Delphi, na stronach z dwóch pierwszych wyników w Google? Masakra. Ok patrz...

program test;

{$APPTYPE CONSOLE}

var
  S : string;
  V, ErrCode : integer;
begin
  repeat
    Write('Wpisz cokolwiek lub wcisnij Enter aby zakonczyc: ');
    Readln(S);
    if S <> '' then
    begin
      Val(S, V, ErrCode);
      if ErrCode = 0 then
      begin
        Writeln('Podales liczbe: ', V);
      end
      else
      begin
        Writeln('Podany tekst nie jest liczba calkowita!');
      end;
    end;
  until S = '';
end.

Cytując stronę Let Me Google That For You:
"Czy było to takie trudne?" :/

0
for i := 1 to N do
begin
  readln(t, w);
  if TryStrToInt(w) then  // brak drugiego argumentu funkcji
  begin
    a[i] := w;            // próbujesz wpisać String do komórki typu Integer
  end
  else
    ShowMessage('blad');
end;

Poprawiony i sprawny kod:

for i := 1 to N do
begin
  ReadLn(t, w);

  if not TryStrToInt(w, a[i]) then
    ShowMessage('blad');
end;
0

furiousprogramming a jakbyś mi to poprawił pod ten skrypt byłbym bardzo wdzięczny:

type
  a1 = array [0 .. 100000] of string;
var
  LICZ: TStringlist;
  t: text;
  N, i, j, x: integer;
  w: string;
  intLicznikZamian:integer;
  intLicznikPorownan1:integer;
  intLicznikPorownan2:integer;
  por1por2:integer;
  a: a1;
  start, stop, elapsed : cardinal;
begin
  start := GetTickCount;
  LICZ := TStringlist.Create;
  LICZ.LoadFromFile('przedsortowaniem.txt');
  N := LICZ.Count;
  LICZ.Free;
  begin
    intLicznikZamian:=0;
    intLicznikPorownan1:=0;
    intLicznikPorownan2:=0;
    assignFile(t, 'przedsortowaniem.txt');
    reset(t);
    for i := 1 to N do
    begin
      readln(t, w);
      if not TryStrToInt(w, a[i]) then
    ShowMessage('blad');
    end;
    CloseFile(t);
    for j := N - 1 downto 1 do
    begin
      x := a[j];
      inc(intLicznikPorownan1);
      i := j + 1;
      while (i <= N) and (x > a[i]) do
      begin
        inc(intLicznikPorownan2);
        a[i - 1] := a[i];
        inc(i);
        inc(intLicznikZamian);
      end;
      a[i - 1] := x;
    end;
    assignFile(t, 'posortowaniu.txt');
    ReWrite(t);
    for i := 1 to N do
    begin
      Writeln(t, a[i]);
    end;
    CloseFile(t);
  end;
  por1por2:=intLicznikPorownan1+intLicznikPorownan2;
  Label7.Caption:=FloatToStr(N);
  Label4.Caption:=FloatToStr(por1por2);
  Label5.Caption:=FloatToStr(intLicznikZamian);
  stop := GetTickCount;
  elapsed := stop - start;
  ShowMessage('Czas wykonania sortowania: ' + IntToStr(elapsed) + ' ms.');
end;                                
0

Jak ma to działać. Ty chłopie myśl co robisz najpierw. Programowanie to nie uczenie się na pamięć regułek. Trzeba myśleć co się robi! I znowu pieprzysz o jakimś skrypcie. Pascal to nie skrypt!

I Tak, rozumiem każdego początki i dział Newbie. Ale sorry, z Twojej postawy wynika, że nie chcesz się niczego nauczyć, oczekując jedynie gotowca. A za to wątek powinien polecieć do Kosza.

PS. nie rozumiem też takiego "miksowania" zastosowanych rozwiązań. Raz używasz TStringList, ale później do tworzenia pliku po operacji sortowania korzystasz z konstrukcji tworzenia pliku typowanego. WTF?! Załadować plik do obiektu typu TStringList tylko po to aby uzyskać ilość wierszy? A później już z niego nie korzystać. Dla mnie dziwne.

A i teraz dojrzałem. Zmienna a, typ a1. No brawo za nazewnictwo ;/ Prosisz o pomoc, a sam robisz jakieś "obfuskacje" kodu źródlowego aby był początkowo nie do ogarnięcia. Sam nie ogarniasz jak widzę za bardzo, a robiąc taki bajzel w źródle, sprawiasz, że innym też cięzko odgadnąć co poeta miał na myśli ;/

0

Widzę, że jesteś kolego wielkim znawcą a przypatrz się na te 6 linijek kodu których nie używam a jednak zliczają i przypisuje je pod Label:

LICZ: TStringlist;

LICZ := TStringlist.Create;
  LICZ.LoadFromFile('przedsortowaniem.txt');
  N := LICZ.Count;
  LICZ.Free;

Label7.Caption:=FloatToStr(N);

Do tego przypisane N służy do pętli. Komentować każdy umie a gdybyś się przyjrzał to tam wszystko pisze.

0

Znawcą nie jestem, ale wiem jedno że Twój kod jest napisany bardzo niedbale. Jedyny plus, że jest jakoś sformatowany. Jeśli już używasz TSrringList, to użyj również do stworzenia pliku wynikowego.

A do pracy z plikiem wejściowym również używaj StringListy do której, go wczytałeś. Widzę co pokazałeś. Cytowany powyżej fragment kodu z ustaleniem tylko liczby linijek świadczy o tym, że kod jest niedbały, nieoptymalny i piszesz wszystko po omacku. Jak to kiedyś mawiano, wiesz że dzwoni w jakimś kościele, tylko nie wiesz w którym.

No ale skoro sam wiesz najlepiej to rób jak uważasz, ale nie żądaj od nas pomocy, skoro wiesz lepiej :/

0

@Buuuubaaaa - jeżeli mam coś doradzić, to w pierwszej kolejności podziel ten kod na mniejsze fragmenty, bo w obecnej postaci nie spełnia założenia pojedynczej odpowiedzialności, przez co jest nieczytelny (ale nie tylko przez to);

Zrób sobie jedną metodę do ładowania zawartości pliku źródłowego do macierzy, drugą do jej sortowania, a trzecią do zapisu zawartości macierzy do pliku docelowego; W ten sposób kod automatycznie zrobi się bardziej czytelny; Do tego pozbądź się zbędnych zmiennych, a to które pozostawisz - nazwij sensownie; Żadnych jednoznakowych identyfikatorów - polskich nazw też unikaj.

0

Na pewno zastosowany kod sortowania jest mało wydajny. Trzeba by było tutaj użyć QuickSorta, skoro i tak niemal wszystkie zmienne licznikowe są zwiększane to trzeba było by to z głową umieścić w jakimś QuickSortowym algo żeby to miało ręce i nogi. Ja zrobiłem tak jak poniżej. Na pewno jest lepiej niż było. Zasada sortowania jest taka jak pokazał pytający. No ale to On jest znawcą nie ja, więc pewnie wie jak wszystko samemu udoskonalić.

Tylko po co wtedy by pisał na forum? Polecam zatem Bubie zapoznać się z podstawami języka oraz zasadami sensownego nazewnictwa zmiennych i elementów takich jak kontrolki typu TLabel i w ogóle wszystkiego. Bo z tym w Twoich kodach na prawdę jest masakra. I nie trzeba być znawcą żeby to zauważyć. Oczywiście dopiero w poniższym kodzie tak naprawdę jest zliczany faktyczny czas sortowania, a nie też wczytywanie z pliku i tworzenie wyniku.

A jeszcze tak na koniec w kwestii "znastwa". Nie jestem ekspertem ani zawodowym programistą. Ale na pewno siedzę na tym formu dłuzej od Ciebie. Widziałem więcej kodów tutaj, a i podejrzewam że i więcej w życiu napisałem w Delphi. Dlatego wiem, że można zrobić to, co chcesz zrobić tak jak poniżej. Albo w ogóle przepisać wszystko na nowo z wydajnym algorytmem sortującym i wedle zaleceń Poprzednika.

Oczywiście do posortowania wierszy można wykorzystać sam obiekt TStringList. Istnieją do tego gotowe metody. Więcej opisów znajdź w Google.

//...
const
  Output_FileName = 'posortowaniu.txt';
  Input_FileName = 'przedsortowaniem.txt';
var
  I, J, N, X : integer;
  InputSL, OutputSL : TStringlist;
  Start, Stop, Elapsed : Cardinal;
  Arr : array[0..100000] of integer;
  IntLicznikZamian, IntLicznikPorownan1, IntLicznikPorownan2 : integer;
begin
  if not FileExists(Input_FileName) then
  begin
    ShowMessage('Plik: "' + Input_FileName + '" nie istnieje!');
  end
  else
  begin
    InputSL := TStringlist.Create;
    InputSL.LoadFromFile(Input_FileName);
    if InputSL.Count > Length(Arr) then
    begin
      ShowMessage('Plik: "' + Input_FileName + '" zawiera zbyt dużą ilośc linii!');
    end
    else
    begin
      N := 0;
      for I := 0 to InputSL.Count - 1 do
      begin
        if not TryStrToInt(InputSL[I], Arr[N]) then
        begin
          ShowMessage('Błąd w linii: ' + IntToStr(I + 1) + '! "' + InputSL[I] + '" nie jest liczbą całkowitą!');
        end
        else
        begin
          N := N + 1;
        end;
      end;
      InputSL.Free;
      IntLicznikZamian := 0;
      IntLicznikPorownan1 := 0;
      IntLicznikPorownan2 := 0;
      Start := GetTickCount;
      for J := N - 1 downto 0 do
      begin
        X := Arr[J];
        Inc(IntLicznikPorownan1);
        I := J + 1;
        while (I < N) and (X > Arr[I]) do
        begin
          Inc(IntLicznikPorownan2);
          Arr[I - 1] := Arr[I];
          Inc(I);
          Inc(IntLicznikZamian);
        end;
        Arr[I - 1] := X;
      end;
      Stop := GetTickCount;
      Elapsed := Stop - Start;
      OutputSL := TStringList.Create;
      for I := 0 to N - 1 do
      begin
        OutputSL.Add(IntToStr(Arr[I]));
      end;
      OutputSL.SaveToFile(Output_FileName);
      OutputSL.Free;
      RowsCountLab.Caption := IntToStr(N);
      NumberOfDifferencesLab.Caption := IntToStr(IntLicznikPorownan1 + IntLicznikPorownan2);
      NumberOfChangesLab.Caption := IntToStr(IntLicznikZamian);
      ShowMessage('Czas wykonania sortowania: ' + IntToStr(Elapsed) + ' ms.');
    end;
  end;
end;
//...
0

Przydałoby się zastanowić nad tym co robić, gdy podczas wczytywania zawartości pliku wystąpi błąd konwersji; Do tej pory był on obsługiwany jedynie przez wyświetlenie komunikatu; Pomimo tego pętla działa dalej, pozostawiając dziurawą macierz - tyle będzie w niej dziur, ile wystąpi błędów konwersji;

Dlatego też polecam podzielić kod na mniejsze fragmenty i jeżeli konwersja nie powiedzie się - nie wykonywać kolejnych kroków (czyli sortowania macierzy i jej zapisu do pliku docelowego).

0

Yyy, wydaje się mi, że macierz nie będzie dziurawa. Zrobiłem plik wejściowy w postaci:

9
5
a
3

I otrzymałem komunikat o błędzie w linii trzeciej. To co dalej z tym zrobić to już sobie sam pytający niech dopracuje wedle uznania, bo pewnie i tak wie lepioej niż my. Ale plik wynikowy zawiera:

3
5
9

Czyli według mnie jest ok, ponieważ zmienna N nie zwiększa się gdy nastapi błąd konwersji. Dlatego nie wiem skąd wnioskujesz, że będą dziury w tablicy. Chyba, że coś jeszcze przeoczyłem albo źle zakodowałem u siebie.

EDIT: chyba, że masz na mysli mnóstwo niewykorzystanych elementów tablicy. Oczywiście przy tak prostym programie ja osobiście posłużył bym się samym sortującymi roziązaniami, jakie udostępnia TStringList, nie tworząc niepotrzebnie aż tak dużej macierzy. Ewentualnie tablica dynamiczna,

0

@olesio - chodzi mi konkretnie o ten fragment kodu:

for i := 1 to N do
begin
  readln(t, w);

  if not TryStrToInt(w, a[i]) then
    ShowMessage('blad');
end;

Pochodzi on z kodu pytacza, tego długiego z posta z poprzedniej strony; Właśnie nie dość, że używana jest macierz o statycznym rozmiarze i mnóstwo komórek nie jest używanych (macierz zajmuje 400KB, jeżeli Integer jest 4-bajtowy), to dodatkowo użycie pętli For powoduje pominięcie uzupełnienia komórki, jeżeli wystąpi błąd konwersji; A z tego co pamiętam, funkcja ta nie modyfikuje parametru Value jeśli wystąpi błąd konwersji - stąd wspomniane wcześniej dziury;

Bezpieczniejszym rozwiązaniem jest użycie pętli While:

var
  fInput: TextFile;
  arrNumbers: array [0 .. 99] of Integer;
  strLine: String;
  intCount: Integer = 0;
begin
  AssignFile(fInput, 'input.txt');
  Reset(fInput);
  try
    while not EoF(fInput) do
    begin
      ReadLn(fInput, strLine);

      if TryStrToInt(strLine, arrNumbers[intCount]) then
        Inc(intCount);
    end;
  finally
    CloseFile(fInput);
  end;
end;

Taka mała propozycja, jeśli chodzi o samo ładowanie danych do pamięci; Przy czym i tak sugeruję stworzyć sobie trzy metody w klasie formularza oraz kilka pól, które trzymać będą dane, zamiast zmiennych globalnych czy gigantycznego bloku zmiennych lokalnych;

PS: Tak przy okazji - używajcie funkcji Concat i Format :]

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