5

指定された構造、つまり(各行に対して)char、space、char、space、double value、endlineのテキストファイルがあります。例えば

q w 1.23
e r 4.56
t y 7.89

Free Pascalでこれらの値を「抽出」する適切な方法は何ですか?

4

3 に答える 3

6

FreePascal には SysUtils に関数 SScanF があります (他の言語の場合はご存知かもしれません..)

使用方法を示すために RRUZ の例を修正しました。

uses SysUtils;

type
  TData=object
    Val1 ,
    Val2 : String;
    Val3 : Double;
  end;

procedure ProcessFile(aFileName:String);
var
  F     : Text;
  LData : TData;
  Line  : String;
begin
  DecimalSeparator:='.';
  AssignFile(F,aFileName);
  Reset(F);
  while not eof(F) do
  begin
    ReadLn(F,Line);
    SScanf(Line,'%s %s %f',[@LData.Val1,@LData.Val2,@LData.Val3]);

    //do something with the data
    WriteLn(LData.Val1);
    WriteLn(LData.Val2);
    WriteLn(LData.Val3);
  end;
end;

begin
  ProcessFile('C:\Bar\Foo\Data.txt');
  Writeln('Press Enter to exit');
  Readln;
end.
于 2012-03-22T23:57:53.093 に答える
3

クラスを使用しTStringListてファイルとDelimitedTextプロパティをロードし、値を別のTStringListに分割してから、値をレコードに格納できます。

このサンプルを確認してください

{$mode objfpc}{$H+}

uses
  Classes, SysUtils;

{$R *.res}

type
  TData=record
    Val1: Char;
    Val2: Char;
    Val3: Double;
  end;

procedure ProcessFile;
var
  LFile  : TStringList;
  Line   : TStringList;
  i      : Integer;
  LData  : TData;
  LFormat: TFormatSettings;
begin
  //set the propert format for the foat values
  LFormat:=DefaultFormatSettings;
  LFormat.DecimalSeparator:='.';

  LFile:=TStringList.Create;
  Line :=TStringList.Create;
  try
   //load the file
   LFile.LoadFromFile('C:\Bar\Foo\Data.txt');
   Line.Delimiter:=' ';
    for i:=0 to LFile.Count-1 do
    begin
      //read the line and split the result
      Line.DelimitedText:=LFile[i];
      //some basic check
      if Line.Count  <> 3 then raise Exception.Create('Wrong data length');

      //you can add additional check here    
      LData.Val1:=Line[0][3]; 
      LData.Val2:=Line[1][4];
      LData.Val3:=StrToFloat(Line[2],LFormat);

      //do something with the data
      WriteLn(LData.Val1);
      WriteLn(LData.Val2);
      WriteLn(LData.Val3);
    end;
  finally
    Line.Free;
    LFile.Free;
  end;
end;

begin
 try
    ProcessFile;
 except on E:Exception do Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.
于 2012-03-22T23:19:22.753 に答える
1

スイッチの後のコマンドライン引数によって提供され、文字の置換重みを含むファイルを読み取ることに関心があるとしましょう。

program WeightFileRead;
uses SysUtils, StrUtils;
var
   MyFile : TextFile;
   FirstChar, SecondChar, DummyChar : Char;
   Weight : Double;
begin
   if GetCmdLineArg ('editweights', StdSwitchChars) = ''
   then begin
      WriteLn ('Syntax: WeightFileRead -editweights filename'); exit
   end;
   AssignFile (MyFile, GetCmdLineArg ('editweights', StdSwitchChars));
   Reset (MyFile);
   try
      while not EOF (MyFile) do
      begin
         ReadLn (MyFile, FirstChar, DummyChar, SecondChar, Weight);
         WriteLn ('A: ', FirstChar, '; B: ', SecondChar, '; W: ', Weight:0:1);
      end
   finally
      CloseFile (MyFile)
   end
end.

より一般的な設定では、最初の 2 つのエントリがより長い文字列になる可能性がある場合、文字列内の空白で区切られた th 番目の単語をExtractWord検索する (または複数の空白をまとめて空の単語として扱う) を使用して、3 番目のエントリを次のように変換できます。数。nExtractSubstr

program WeightFileRead2;
uses SysUtils, StrUtils;
var
   MyFile : TextFile;
   FileLine : String;
begin
   if GetCmdLineArg ('editweights', StdSwitchChars) = ''
   then begin
      WriteLn ('Syntax: WeightFileRead -editweights filename'); exit
   end;
   AssignFile (MyFile, GetCmdLineArg ('editweights', StdSwitchChars));
   Reset (MyFile);
   try
      while not EOF (MyFile) do
      begin
         ReadLn (MyFile, FileLine);
         WriteLn ('A: ', ExtractWord (1, FileLine, [' ']),
                  '; B: ', ExtractWord (2, FileLine, [' ']),
                  '; W: ', StrToFloat (ExtractWord (3, FileLine, [' '])):0:1);
      end
   finally
      CloseFile (MyFile)
   end
end.

を使用したくないので、[' ']ではなくを使用することに注意してください。StdWordDelimsまたは 、単語区切り文字になります。

于 2012-03-23T16:43:40.117 に答える