Board index » cppbuilder » Storing strings in std::vector

Storing strings in std::vector


2006-11-08 06:40:49 PM
cppbuilder25
Hi,
I've got a problem with the treatment of strings in BDS 2006 C++.
Everything seems to be all right until the last sequence STRING
RETRIEVE on the output.
What I'm waiting for there is the following sequence:
===== STRING RETRIEVE =====
STR 6
STR 5
STR 4
STR 3
STR 2
STR 1
What's happing here is that the last stored string in sequence STRING
STORE
is being copied to each S_arr[x].c_str() and the result you get is:
===== STRING RETRIEVE =====
STR 6
STR 6
STR 6
STR 6
STR 6
STR 6
Why? Can anybody explain what is wrong in my code.
Thanks in advance
Regards
Mac
===== SOURCE CODE =======
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <share.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <dir.h>
#include <dos.h>
#include <string.h>
#include <conio.h>
#include <signal.h>
#include <vector>
#include <mem.h>
//---------------------------------------------------------------------------
typedef std::vector<int>Int_arr;
typedef std::vector<AnsiString>Str_arr;
Int_arr I_arr;
Str_arr S_arr;
int main(int argc, char* argv[])
{
char buff[5];
printf("\n===== INTEGER STORE ======");
for (int a=1; a <= 6 ; a++)
{ I_arr.resize(a);
I_arr[a-1]=a;
printf("\nINT");
printf(" %d", I_arr[a-1]);
}
printf("\n===== INTEGER RETRIEVE ======");
for(int x= 5; x>=0 ; x--)
{ printf("\nINT");
printf(" %d", I_arr[x]);
}
printf("\n===== STRING STORE ======");
for (int b=1; b<=6 ; b++)
{ S_arr.resize(b);
itoa(b, buff, 10);
memcpy(S_arr[b-1].c_str(), buff, 3);
printf("\nSTR");
printf(" %s", S_arr[b-1].c_str());
}
printf("\n===== STRING RETRIEVE ======");
for (int x= 5; x>=0 ; x--)
{ printf("\nSTR");
printf(" %s", S_arr[x].c_str());
}
return 0;
}
//---------------------------------------------------------------------------
OUTPUT:
=======
===== INTEGER STORE ======
INT 1
INT 2
INT 3
INT 4
INT 5
INT 6
===== INTEGER RETRIEVE ======
INT 6
INT 5
INT 4
INT 3
INT 2
INT 1
===== STRING STORE ======
STR 1
STR 2
STR 3
STR 4
STR 5
STR 6
===== STRING RETRIEVE ======
STR 6
STR 6
STR 6
STR 6
STR 6
STR 6
 
 

Re:Storing strings in std::vector

"Mac" < XXXX@XXXXX.COM >wrote:
Quote
Hi,
I've got a problem with the treatment of strings in BDS 2006 C++.
Everything seems to be all right until the last sequence STRING
RETRIEVE on the output.
Looking at the code, I'm surprised it worked that far!
Quote
===== SOURCE CODE =======
[snipping unimportant stuff]
Quote
typedef std::vector<AnsiString>Str_arr;
Why use AnsiString rather than std::string?
Quote
Str_arr S_arr;

int main(int argc, char* argv[])
{
char buff[5];
Not big enough to hold all integers, but not a problem here.
[snip integer array stuff]
Quote
printf("\n===== STRING STORE ======");
for (int b=1; b<=6 ; b++)
{ S_arr.resize(b);
This is pretty hideous, but not actually erroneous. Since you know how
large the array will be before you start, why not resize it once,
outside the loop?
Quote
itoa(b, buff, 10);
memcpy(S_arr[b-1].c_str(), buff, 3);
This, mate, is where the whole thing goes kerbloey. You have an empty
AnsiString returned by your rather odd indexing system. You then get the
c_str() pointer (which is completely broken for AnsiString, since it
returns a char*, rather than a const char*. This brokenness allows you
to do the memcpy(), which is copying 3 bytes via a pointer to something
weird.
Why, why, WHY didn't you just use the C++ option?
S_arr[b-1] = buff;
It's SO much shorter.
(Any time you use memcpy() or strcpy(), the chances are you're doing
something wrong. Or memcmp(), or strcmp(). Using memcpy() with string
data is almost always wrong.)
If anything after this point does anything sane at all, it's pure luck.
Alan Bellingham
--
ACCU Conference: 11-14 April 2007 - Paramount Oxford Hotel
 

Re:Storing strings in std::vector

Thank you very much Alan!
Your explanation was very bright and helpful so the test program is
working now.
Best regards
Mac
Alan Bellingham skrev:
Quote
"Mac" < XXXX@XXXXX.COM >wrote:

>Hi,
>I've got a problem with the treatment of strings in BDS 2006 C++.
>Everything seems to be all right until the last sequence STRING
>RETRIEVE on the output.

Looking at the code, I'm surprised it worked that far!

>===== SOURCE CODE =======

[snipping unimportant stuff]

>typedef std::vector<AnsiString>Str_arr;

Why use AnsiString rather than std::string?

>Str_arr S_arr;
>
>int main(int argc, char* argv[])
>{
>char buff[5];

Not big enough to hold all integers, but not a problem here.

[snip integer array stuff]

>printf("\n===== STRING STORE ======");
>for (int b=1; b<=6 ; b++)
>{ S_arr.resize(b);

This is pretty hideous, but not actually erroneous. Since you know how
large the array will be before you start, why not resize it once,
outside the loop?

>itoa(b, buff, 10);
>memcpy(S_arr[b-1].c_str(), buff, 3);

This, mate, is where the whole thing goes kerbloey. You have an empty
AnsiString returned by your rather odd indexing system. You then get the
c_str() pointer (which is completely broken for AnsiString, since it
returns a char*, rather than a const char*. This brokenness allows you
to do the memcpy(), which is copying 3 bytes via a pointer to something
weird.

Why, why, WHY didn't you just use the C++ option?

S_arr[b-1] = buff;

It's SO much shorter.

(Any time you use memcpy() or strcpy(), the chances are you're doing
something wrong. Or memcmp(), or strcmp(). Using memcpy() with string
data is almost always wrong.)

If anything after this point does anything sane at all, it's pure luck.

Alan Bellingham
--
ACCU Conference: 11-14 April 2007 - Paramount Oxford Hotel
 

{smallsort}

Re:Storing strings in std::vector

"Mac" < XXXX@XXXXX.COM >wrote:
Quote
Thank you very much Alan!
Your explanation was very bright and helpful so the test program is
working now.
Glad to be of assistance.
BTW - we'd prefer it if you didn't quote the whole of long messages.
Alan Bellingham
--
ACCU Conference: 11-14 April 2007 - Paramount Oxford Hotel