0

I want to split a string in X partstrings.

This is my code so far:

procedure SplitFile(var a: StringArray; len: integer; fileString: AnsiString; numberParts: integer);
var
  i, Rest, partSize: integer;
  tmp: AnsiString;
begin
  Rest := len mod numberParts;
  SetLength(a, numberParts);
  partSize := (len - Rest) div numberParts;
  numberParts := numberParts - 1;
  for i := 0 to numberParts do
  begin
    // Get access violation here
    CopyMemory(@a[i][1], @filestring[i * partSize], partSize);
  end;
  if Rest <> 0 then
    CopyMemory(@a[numberParts][numberParts*partSize], @filestring[numberParts*partSize], Rest);
end;

I get an access violation on this line:

CopyMemory(@a[i][1], @filestring[i * partSize], partSize);

I am not sure where exactly the error gets caused. How do I get the Address of a[i], sin't it @a[i][1]? and causes it an error anyway when it tries to access @filestring[i* partSize] in the first loop, cause it would be 0?

I hope someone can explain me that.

Thanks

nemoest
  • 81
  • 1
  • 10
  • Why are you using the Win32 `CopyMemory()` function at all, instead of using Delphi's own `Copy()` function? You are misusing `CopyMemory()` which is why you are getting errors. – Remy Lebeau Jul 01 '15 at 03:23

2 Answers2

2

Your code is over-complicated for what you are attempting. Try this simpler code instead:

// assuming StringArray is "array of (Ansi)String"...
procedure SplitFile(var a: StringArray; len: integer; fileString: AnsiString; numberParts: integer);
var
  i, partSize: integer;
begin
  partSize := len div numberParts;
  SetLength(a, numberParts);
  for i := 0 to numberParts-1 do begin
    a[i] := Copy(filestring, (i * partSize)+1, partSize);
  end;
end;

On the last iteration, Copy() will truncate the returned substring for you if the requested count is more than the available number of characters at the requested offset.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

I see three main issues:

  • Overtangled part counting leads to error in array length determination.
  • You have to add 1 to properly address ansistring chars:
  • Must set length of destination strings

    for i := 0 to numberParts {probably - 1} do begin SetLength(a[i], partSize); CopyMemory(@a[i][1], @filestring[i * partSize + 1], partSize); end;

Th same is true for the last piece treatment

MBo
  • 77,366
  • 5
  • 53
  • 86
  • Oh thank you very much! **@filestring[i * partSize + 1]** that part did I notice myself but I totally forgot to SetLength(). Saved my day! But numberparts gets substracted -1 above ;) – nemoest Jul 01 '15 at 03:28