Solución:
Si te entendí bien, entonces esto debería ser suficiente:
procedure TForm1.FormClick(Sender: TObject);
type
TWordPos = record
Start, &End: integer;
end;
const
ALLOC_BY = 1024;
var
Words: array of TWordPos;
ActualLength, i: integer;
txt: string;
ThisWhite, PrevWhite: boolean;
begin
ActualLength := 0;
txt := Memo1.Text;
PrevWhite := true;
for i := 1 to Length(txt) do
begin
ThisWhite := Character.IsWhiteSpace(txt[i]);
if PrevWhite and not ThisWhite then
begin
if ActualLength = Length(Words) then
SetLength(Words, Length(Words) + ALLOC_BY);
Words[ActualLength].Start := i;
inc(ActualLength);
PrevWhite := false;
end else if (ActualLength>0) and ThisWhite then
Words[ActualLength - 1].&End := i;
PrevWhite := ThisWhite;
end;
SetLength(Words, ActualLength);
StringGrid1.RowCount := Ceil(Length(Words) / StringGrid1.ColCount);
for i := 0 to Length(Words) - 1 do
begin
StringGrid1.Cells[i mod StringGrid1.ColCount, i div StringGrid1.ColCount] :=
Copy(Memo1.Text, Words[i].Start, Words[i].&End - Words[i].Start);
end;
end;
Hay un Tokenizer
(como comenta David) en el RTL. Dividirá un texto en palabras, utilizando un delimitador de su elección.
Este ejemplo es de un comentario de Olaf Moinen en un artículo de Zarko Gaijic: how-to-split-a-delphi-string-to-words-tokens.htm.
uses HTTPUtil;
procedure TForm1.Button1Click(Sender: TObject);
var
LTokenizer: IStringTokenizer;
begin
Memo1.Clear;
LTokenizer := StringTokenizer(Edit1.Text, ' ');
while LTokenizer.hasMoreTokens do
Memo1.Lines.Add(LTokenizer.nextToken);
end;
Tomará el texto del control de edición y lo colocará en una nota. Lo dejaré como ejercicio para hacer lo mismo de una nota a una cuadrícula.
TStringGrid
tiene la característica de llenar inexistente células, células que están más allá ColCount * RowCount
. Por lo tanto, no es necesario contar las palabras antes de completar la cuadrícula de cadenas.
Entonces, un enfoque sencillo da como resultado:
procedure TForm1.Button1Click(Sender: TObject);
var
WordCount: Integer;
WordStart: Integer;
S: String;
I: Integer;
begin
WordCount := 0;
WordStart := 1;
S := Memo.Text + ' ';
for I := 1 to Length(S) do
if S[I] = ' ' then
begin
if WordStart <> I then
begin
Grid.Cells[WordCount mod Grid.ColCount, WordCount div Grid.ColCount] :=
Copy(S, WordStart, I - WordStart);
Inc(WordCount);
end;
WordStart := I + 1;
end;
Grid.RowCount := ((WordCount - 1) div Grid.ColCount) + 1;
end;
Nota: Para evitar la asignación de memoria adicional para el texto (debido a la adición de ' '
), agregue la última palabra a la cuadrícula después del ciclo.
Característica de bonificación:
Para poder ajustar el recuento de columnas, subclasifique la cuadrícula de cadenas de la siguiente manera y todas las celdas se reorganizarán automáticamente:
type
TStringGrid = class(Grids.TStringGrid)
protected
procedure SizeChanged(OldColCount, OldRowCount: Integer); override;
end;
TForm1 = class(TForm)
...
procedure TStringGrid.SizeChanged(OldColCount, OldRowCount: Integer);
var
I: Integer;
begin
if OldColCount < ColCount then
begin
for I := 0 to OldColCount * OldRowCount - 1 do
Cells[I mod ColCount, I div ColCount] :=
Cells[I mod OldColCount, I div OldColCount];
end
else if OldColCount > ColCount then
begin
for I := OldColCount * OldRowCount - 1 downto 0 do
Cells[I mod ColCount, I div ColCount] :=
Cells[I mod OldColCount, I div OldColCount];
end;
if OldColCount <> OldRowCount then
for I := OldColCount * OldRowCount to ColCount * RowCount - 1 do
Cells[I mod ColCount, I div ColCount] := '';
end;