Odczyt integerów z pliku tekstowego

0

Załóżmy,że mam do rozwiązania taki problem.
Jest dany plik tekstowy w którym cyklicznie pojawia sie kilka linii stringów oraz para liczb typu integer na końcu każdego bloku.NP:

  • string1.1
  • string1.2
  • integer integer
  • string2.1
  • string2.2
  • integer integer

Zadaniem jest odczytać te dane do recordu.Każdy string do osobnego pola recordu,a do ostatniego pola średnia arytmetyczna integerów na końcu.
Moim pytaniem jest:Jak odczytać wartości liczbowe z pliku do zmiennych typu integer lub real?Jeżeli są w pliku tekstowym to są chyba interpretowane jak string prawda?Jeżeli się myle,albo jest jakieś rozwiązannie tego prosiłbym o wskazówki lub powiedzenie jak to zrobić.

0

odczytać jako string i zamienić na integer

0

Już znalazłem procedure strToInt(); ale pojawił się problem,bo wywala mi wyjątek jeżeli liczby znajdują się obok siebie a nie jedna pod drugą.Jak to w jakiś mądry sposób obejść?

0

gościu weź pomyśl przez chwilę - jak są dwie obok siebie to trzeba je rozbić na dwa ciągi, w których są te liczby osobno.
Jak to jest do szkoły/studia to powinieneś mieć podstawy na zajęciach, jak to jest hobbystycznie to zacznij od jakiegoś kursu z podstawami

1

Istnieje możliwość bezpośredniego odczytu liczb całkowitych i zmiennoprzecinkowych z pliku tekstowego, nawet jeśli kilka liczb zawartych jest w jednej linii; Do tego celu służy uniwersalna procedura Read; Ilość liczb w jednej linii nie musi być znana, dlatego że istnieje prosty sposób na czytanie danych aż do końca linii:

{ dla każdej linii pliku }
while not EoF(LInputFile) do
begin
  { aż do końca bieżącej linii pliku }
  while not EoLn(FInputFile)
  begin

  end;
end;

Powyższy schemat można wykorzystać tylko w przypadku, gdy każda linia zawiera co najmniej jedną dowolną liczbę oraz wtedy, gdy w każdej linii znajdują się tylko i wyłącznie liczby; Ty natomiast nie możesz czytać w ten sposób danych, dlatego że przeszkadzają te ciągi pomiędzy liczbami;

Jeśli te ciągi znaków - string1.1, string1.2, string2.1 i string2.2 - nie mogą posiadać białych znaków, czyli przykładowa linia z takiego pliku tekstowego wygląda tak:

String String Integer Integer String String Integer Integer

to możesz wczytać całą linię to zmiennej łańcuchowej, podzielić ją na składowe za pomocą ExtractStrings, a następnie przepisać wartości podciągów z wynikowej listy do pól rekordu (dodatkowo konwertując ciągi liczbowe na liczby natywne);


Inne rozwiązanie to napisanie sobie procedurki, która to będzie potrafiła wczytać podciąg znajdujący się wewnątrz linii, tak aby wczytywała dotąd, aż natrafi albo na znak końca linii, albo na biały znak; Przykład takiej procedury poniżej:

procedure ReadStrFromFile(var AFile: TextFile; out AString: String);
var
  LChar: Char;
begin
  AString := '';

  if not EoLn(AFile) then
  begin
    Read(AFile, LChar);

    if LChar <> ' ' then
      AString += LChar;
  end;

  while not EoLn(AFile) do
  begin
    Read(AFile, LChar);

    if LChar = ' ' then
      Exit()
    else
      AString += LChar;
  end;
end;

Pierwszy warunek służy do pominięcia znaku separatora składowych linii - jest to konieczne, dlatego że po odczytaniu liczby, kursor w pliku ustawiony jest przed znakiem separatora i znak ten (jeśli na niego wskazuje) należy pominąć; Dalej jest pętla, która czyta znaki dotąd aż napotka na biały znak lub na znak końca linii; Do argumentu dodaje wczytane znaki - wszystkie oprócz białych;

Do kompletu można sobie napisać dwa pozostałe wrappery, coby zwiększyć czytelność kodu:

procedure ReadIntFromFile(var AFile: TextFile; out AInt: Integer);
begin
  Read(AFile, AInt);
end;

procedure ReadRealFromFile(var AFile: TextFile; out AReal: Real);
begin
  Read(AFile, AReal);
end;

Liczby całkowite i zmiennoprzecinkowe można wczytywać bezpośrednio, więc to tylko wrappery; Mając już przygotowane procedurki wczytujące, wystarczy ich użyć w odpowiedniej kolejności; Załóżmy, że plik źródłowy posiada linie zbudowane według poniższego schematu:

String String Integer Integer String String Real Real

Przykładowa linia wygląda np. tak:

first second 100 200 third fourth 23.45 67.89

Mamy też przygotowany typ rekordu, do którego chcemy wczytać dane z pliku:

type
  TSomeRec = record
    StrFirst: String;
    StrSecond: String;
    IntFirst: Integer;
    IntSecond: Integer;
    StrThird: String;
    StrFourth: String;
    RealFirst: Real;
    RealSecond: Real;
  end;

Aby załadować dane z jednej linii pliku źródłowego bezpośrednio do rekordu, bez używania ExtractStrings, należy skorzystać z poniższego schematu:

var
  LInputFile: TextFile;
  LSomeRec: TSomeRec;
begin
  AssignFile(LInputFile, 'C:\Input.txt');
  Reset(LInputFile);
  try
    ReadStrFromFile(LInputFile, LSomeRec.StrFirst);     // składowa "first"
    ReadStrFromFile(LInputFile, LSomeRec.StrSecond);    // składowa "second"
    ReadIntFromFile(LInputFile, LSomeRec.IntFirst);     // składowa "100"
    ReadIntFromFile(LInputFile, LSomeRec.IntSecond);    // składowa "200"
    ReadStrFromFile(LInputFile, LSomeRec.StrThird);     // składowa "third"
    ReadStrFromFile(LInputFile, LSomeRec.StrFourth);    // składowa "fourth"
    ReadRealFromFile(LInputFile, LSomeRec.RealFirst);   // składowa "23.45"
    ReadRealFromFile(LInputFile, LSomeRec.RealSecond);  // składowa "67.89"
  finally
    CloseFile(LInputFile);
  end;

Jeśli teraz wyświetlimy sobie zawartość rekordu LSomeRec w taki sposób:

WriteLn('StrFirst    ', LSomeRec.StrFirst);
WriteLn('StrSecond   ', LSomeRec.StrSecond);
WriteLn('IntFirst    ', LSomeRec.IntFirst);
WriteLn('IntSecond   ', LSomeRec.IntSecond);
WriteLn('StrThird    ', LSomeRec.StrThird);
WriteLn('StrFourth:  ', LSomeRec.StrFourth);
WriteLn('RealFirst   ', LSomeRec.RealFirst:2:2);
WriteLn('RealSecond  ', LSomeRec.RealFirst:2:2);

zobaczymy na ekranie to:

StrFirst    first
StrSecond   second
IntFirst    100
IntSecond   200
StrThird    third
StrFourth:  fourth
RealFirst   23.45
RealSecond  23.45

Czyli jak widać, na ekranie wyświetlone zostaną prawidłowo wczytane dane; Aby procedura ReadStrFromFile działała prawidłowo, separatorem składowych w linii muszą być znaki spacji (składowa, jeden znak spacji, składowa, jeden znak spacji itd.); Taką procedurkę można bardziej rozbudować, aby potrafiła więcej;

Edit: Podany kod jest odpowiedni dla FPC, został też sprawdzony, więc jest w pełni działający.

0

pokaż jakiś przykładowy plik txt

0

w ostateczności zrobiłem to tak

 i,j,t:integer;
  s,ss:string;
  tab:array[0..9]of string; 

(...) //odczyt konkretnej linii pliku do zmiennej s

 ss := '';
  s := s + ' ';
  for i := 1 to length(s) do
    if s[i] in ['0'..'9'] then
      ss := ss + s[i]
    else if ss <> char(32) then    //char(32) = spacja
    begin
      tab[t]:=ss; ss := '';
      t:=t+1;
    end; 

Przepraszam że to tylko wycinek kodu,ponieważ jest to robione tylko na potrzeby przetestowania i nie byłoby sensu zaśmiecać resztą(działa).

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