Загрузка StringGrid из текстового файла

Как я могу загрузить текстовый файл с целыми числами, разделенными пробелом, в StringGrid? Каждое число в каждую ячейку. Сетка должна быть прямоугольной, поэтому, если какое-то число отсутствует, оно должно быть заполнено 0.

Вот что я сделал до сих пор, но для этого нужно уже установить количество строк и столбцов.

  while not eof(f) do
  begin
    while not eoln(f) do
    begin
      read(f, data);
      StringGrid1.Cells[p, l] := data;
      inc(p);
    end;
    p := 0;
    readln(f);
    inc(l);
  end;

person yoahim    schedule 05.02.2012    source источник
comment
Почему вы используете Pascal IO? Почему бы вам просто не загрузить файл в список строк и не использовать SplitString функция разделения каждой строки?   -  person David Heffernan    schedule 06.02.2012
comment
Игнорируйте банду NO PASCAL I/O, это нормально для этой задачи. Ваша формулировка проблемы непоследовательна, как бы вы определили позиции, если пропущено более одного последовательного числа?   -  person OnTheFly    schedule 06.02.2012
comment
@ user539484 Чистый яд и злоба. Не классный.   -  person David Heffernan    schedule 06.02.2012


Ответы (3)


Лично я бы предпочел не использовать здесь Pascal IO. Если вы хотите, чтобы ваш код мог читать данные Unicode, тогда Pascal IO вам не поможет.

Вы можете сделать то, что вы описываете, используя список строк для загрузки файла, а затем SplitString из модуля StrUtils для анализа строки.

procedure PopulateStringGrid(Grid: TStringGrid; const FileName: string);
var
  Strings: TStringList;
  Row, Col: Integer;
  Items: TStringDynArray;
begin
  Grid.RowCount := 0;//clear any previous data
  Strings := TStringList.Create;
  try
    Strings.LoadFromFile(FileName);
    Grid.RowCount := Strings.Count;
    for Row := 0 to Strings.Count-1 do
    begin
      Items := SplitString(Strings[Row], ' ');
      for Col := 0 to Grid.ColCount-1 do
        if Col<Length(Items) then
          Grid.Cells[Col, Row] := Items[Col]
        else
          Grid.Cells[Col, Row] := '0';
    end;
  finally
    Strings.Free;
  end;
end;

Обратите внимание, что SplitString может быть не совсем тем, что вам нужно. Например, он не объединяет повторяющиеся разделители в один. Чтобы понять, что я имею в виду, рассмотрим следующий ввод:

Hello    World

Между двумя словами есть 4 пробела, и SplitString вернет следующий массив:

'Hello'
''
''
''
'World'

Если вы хотите рассматривать последовательные разделители как один разделитель, вы можете использовать свойство DelimitedText списка строк:

procedure PopulateStringGrid(Grid: TStringGrid; const FileName: string);
var
  TextFile, Line: TStringList;
  Row: Integer;
begin
  Grid.RowCount := 0;//clear any previous data
  TextFile := TStringList.Create;
  try
    Line := TStringList.Create;
    try
      Line.Delimiter := ' ';
      TextFile.LoadFromFile(FileName);
      Grid.RowCount := TextFile.Count;
      for Row := 0 to TextFile.Count-1 do
      begin
        Line.DelimitedText := TextFile[Row];
        for Col := 0 to Grid.ColCount-1 do
          if Col<Line.Count then
            Grid.Cells[Col, Row] := Line[Col]
          else
            Grid.Cells[Col, Row] := '0';
      end;
    finally
      Line.Free;
    end;
  finally
    TextFile.Free;
  end;
end;
person David Heffernan    schedule 06.02.2012

Я бы посоветовал попробовать этот код.
Это просто, но я уверен, что вы сможете решить свою проблему.

procedure LoadFile(FileName: string; StringGrid: TStringGrid);
var
  temp, fName, sName, eMail: string;
  sgItem: TStringList;
  f: textfile;
begin
  assignfile(f, FileName);
  reset(f);
  sgItem := TStringList.Create;
  StringGrid.RowCount := 2;
  while not eof(f) do
  begin
    readln(f, temp);
    fName := copy(temp, 1, pos('|', temp) - 1);
    delete(temp, 1, pos('|', temp));
    sName := copy(temp, 1, pos('|', temp) - 1);
    delete(temp, 1, pos('|', temp));
    eMail := temp;
    sgItem.Clear;
    sgItem.Add(fName);
    sgItem.Add(sName);
    sgItem.Add(eMail);
    StringGrid.Rows[StringGrid.RowCount - 1].AddStrings(sgItem);
    StringGrid.RowCount := StringGrid.RowCount + 1;
  end;
  sgItem.Free;
  closefile(f);
end;

Применение :

LoadFile('File.txt', StringGrid1);

Бени

person Beny    schedule 05.02.2012

Попробуй это

    procedure FillStringgrid;
        // Split the line of text into individual entries
        procedure Split(const Delimiter: Char;Input: string;const Strings:TStrings);
        begin
            Assert(Assigned(Strings)) ;
            Strings.Clear;
            Strings.Delimiter := Delimiter;
            Strings.DelimitedText := Input;
        end;
    var
      strlst  : Tstringlist;
      myfile  : TextFile;
      search  : string;
      i,j     : integer;
    begin
      i:= 0;
      AssignFile(myfile,'filepath');   // specify your file path here
      Reset(myFile);
      while not eof(myfile) do
      begin
          Readln(myfile,search);
          strlst:= Tstringlist.Create;
          Split(' ',search,strlst);    // get the no's separated by the delimiter  
          //adjust your column count based on no of entries
          if StringGrid1.ColCount < strlst.Count then
             StringGrid1.ColCount := strlst.Count;
          StringGrid1.Rows[i]:=strlst; // adjust the row count
          Inc(i);
          StringGrid1.RowCount := i;
      end;
      // free stringlist and textfile      
      CloseFile(myfile) ;
      strlst .free;

      // fill in the blank entries with 0
      for i := 0 to StringGrid1.RowCount - 1 do
        begin
        for j := 0 to StringGrid1.ColCount - 1 do
          begin
          if StringGrid1.Cells[j,i]='' then
            StringGrid1.Cells[j,i]:='0';
          end;
        end; 
    end;
person Shirish11    schedule 06.02.2012