Board index » cppbuilder » Incorrect length of strings taken from TStringList

Incorrect length of strings taken from TStringList

By means of the BCB internal debgger, the incorrect result of
TStringList::IndexOf which I reported before could be traced down to
the following result :

When a string is taken from the StringList and passed to functions
like CompareString or AnsiCompareString, the length is always 100
although the strings are much shorter.

For unknown reasons, this might effect the result of the comparison in
certain (unknown) situations under some versions of Windows.
In my case the function IndexOf sometimes couldn't find a string
although it was in the list.

I had to overcome the problem as follows but I am not happy with the
fact that TStringList is so unpredictable !!!

int __fastcall TMyStringList::IndexOf(const AnsiString AString)
{
  AnsiString Tmp;
  int lng,count = Count;
  for (int idx=0;idx<count;++idx)
  {
    Tmp = Strings[idx];
    lng = strlen(Tmp.c_str());   // Tmp.Length() would give 100 which
is not correct

    // following line is essential to make comparison work correctly
!!!
    Tmp.SetLength(lng);  // set length of string to its 'real' length

    if(!CompareText(AString,Tmp))
      return idx;
  }
  return -1;

Quote
}

 

Re:Incorrect length of strings taken from TStringList


Quote
Uwe Barthoff wrote...
>By means of the BCB internal debgger, the incorrect result of
>TStringList::IndexOf which I reported before could be traced down to
>the following result :

>When a string is taken from the StringList and passed to functions
>like CompareString or AnsiCompareString, the length is always 100
>although the strings are much shorter.

How do you fill the StringList? Could it be that the AnsiStrings you fill
it with have that size?

There is a fundamental difference between the length you get with strlen
and the length of an AnsiString (the one you get with Length()). An
AnsiString can hold any number of any character, also multiple #0
characters. The length is the count stored in one of its fields. If you
store a zero delimited string into it (by writing to the pointer returned
by c_str()), this doesn't change the length of the AnsiString. To make
the length of the AnsiString match the length of the C style string, you
shouldn't write to the c_str() buffer but assign to the AnsiString
instead. This will set the length returned by Length().

  So don't:

    strncpy(MyStr.c_str(), myCString, 100);

  But just:

    MyStr = myCString;

If you fill the AnsiString buffer with an API function, you should do
something like you do, immediately afterwards:

    MyStr.SetLength(SOME_VALUE);
    bla = ApiFunc(MyStr.c_str(), MyStr.Length());
    MyStr.SetLength(strlen(MyStr.c_str()));

Others might even say you shouldn't use the internal buffer for writing
(it should be const like in std::string). However, it's done this way in
Delphi, and even recommended partice there. I don't want to fight that
out <g>.

--
Rudy Velthuis

Re:Incorrect length of strings taken from TStringList


: "Uwe Barthoff" <Uwe.Barth...@ibm.net> wrote:

Quote
>    Tmp = Strings[idx];
>    lng = strlen(Tmp.c_str());   // Tmp.Length() would give 100 which
>is not correct

You have a bug in your application. The code below will generate plenty of
strings and will never return 100 as the length.

****************************************

#include <cstdlib>

AnsiString NewRandomString(void)
{
  AnsiString Result;

  int StringLength = random(90);
  for (int i = 0; i < StringLength; ++i)
    Result = Result + char(random(26) + 'A');

  return Result;

Quote
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  const int RunCount = 1000;

  TStringList* SomeThing;
  AnsiString ReadString;

  SomeThing = new TStringList();
  for (int i = 0; i < RunCount; ++i)
    SomeThing->Add(NewRandomString());

  for (int i = 0; i < SomeThing->Count; ++i)
  {
    ReadString = SomeThing->Strings[i];
    if (ReadString.Length() == 100)
      throw "Whoops";
  }

  ShowMessage("Done");

Quote
}

--
General information:
  * Post to the right group - http://www.borland.com/newsgroups/
    * Do not cross- or multipost
      * Research at http://www.mers.com/searchsite.html

Stefan Hoffmeister - http://www.econos.de/
TeamB - http://www.teamb.com/

Re:Incorrect length of strings taken from TStringList


Thank you very much for your help.
I created the problem myself , simply because I wanted to limit the
size of the strings to a maximum of 100 characters.

#define MAX_STRING_SIZE 100

  :
CurIdentifier.SetLength(MAX_STRING_SIZE);
CurValue = StringList->Add(CurIdentifier);
  :

Other Threads