Проблема с переводом Ansistring

  • Автор темы Mad_LIR
  • Дата начала
Статус
Закрыто для дальнейших ответов.
M

Mad_LIR

Гость
#1
Есть такой код в C++ 5. В заремленой строке масив указателей на char задаёться статически. Мне нужно определять его динамически.
Вот возникла дурацкая проблема с переводом 2-х AnsiString в char * sta[2].
Код:
// char * sta[2] = {"servise.dll", "ShowForm"}; Это работает нормально


AnsiString qw = "servise.dll";
AnsiString qw1 = "ShowForm";
char * sta[2];
// sta[0]=qw.c_str(); - даёт "servise.~"
// sta[1]=qw1.c_str(); - даёт "ShowForm~"
// StrLCopy(sta[0], qw.c_str(), qw.Length()); - не работает
// StrLCopy(sta[1], qw1.c_str(), qw1.Length()); - не работает
~ - квадрат :)

Вопрос в том, что мне нужен именно массив указвтелей на char для передачи параметров. Help me please!
 

Psixo

Member
21.06.2006
11
0
#2
Код:
AnsiString str1 = "_Vivat!_";
AnsiString str2 = "Aloxa!";

char *p[2] = {str1.c_str(), str2.c_str()};

cout<< p[0];
cout<<"\n";
cout<< p[1];
 
M

Mad_LIR

Гость
#3
Я уже всё перепробовал. Это не работает. Результат будет тот же, с "квадратами". Последний символ лишний.
Можно обойти через объявление двух char[20] - допустим. А потом уже на него дать указатель, но это просто не серьёзно. Может кто поможет и объяснит проблему. Почему не могу через StrLCopy или как правильно.

Заранее благодарен.
 

Kmet

Well-Known Member
Java Team
25.05.2006
1 036
8
#4
Код:
 sta[0]=qw.c_str(); - даёт "servise.~"
sta[1]=qw1.c_str(); - даёт "ShowForm~"
должно ругаться на каст const char* к char*

Код:
// StrLCopy(sta[0], qw.c_str(), qw.Length()); - не работает
// StrLCopy(sta[1], qw1.c_str(), qw1.Length()); - не работает
А память кто выделять будет? И чем не устраивает strcpy?
 
F

Fossil Code

Гость
#5
А почему не ?

AnsiString qw = "servise.dll";
AnsiString qw1 = "ShowForm";
char * sta[2];
sta[0]=&qw;
sta[1]=&qw1;
 

Kmet

Well-Known Member
Java Team
25.05.2006
1 036
8
#7
Для: Fossil Code
Потому при таком способе не гарантируется, что мы пролучим указатель на нультерменированную строку
 

Psixo

Member
21.06.2006
11
0
#8
Код:
 AnsiString qw = "servise.dll";
AnsiString qw1 = "ShowForm";
char * sta[2];
sta[0]=qw.c_str(); - даёт "servise.~"
sta[1]=qw1.c_str(); - даёт "ShowForm~"
Вот этот код,как ни странно,у меня работает вполне корректно.
 
04.09.2006
2 566
2
#9
Не знаю как для AnsiString, но для std::string (std::basic_string) в MSDN сказано:
A pointer to the C-style version of the invoking string. The pointer value is not valid after calling a non-const function, including the destructor, in the basic_string class on the object.
 

Kmet

Well-Known Member
Java Team
25.05.2006
1 036
8
#10
Для: Psixo
этот код и должен работать. Но нормальный компилятор обязательно поругаеться на приведение типов от сonst char* к char*.
 
B

BreakPointMAN

Гость
#11
c_str() всего-навсего возвращает указатель на char*-буфер, в котором хранится строка, представляемая данным AnsiString'ом. И с ним надо быть поосторожнее... Тут вариантов того, что может произойти, - масса. Например:
Код:
AnsiString a="Hello, ";
AnsiString b="World!";
char *c=(a+b).c_str(); // так делать нельзя!
Безымянный объект типа AnsiString, полученный в результате конкатенации переменных a и b, является временным, он будет уничтожен после выполнения строки с инструкцией "char *c=(a+B).c_str();", а указатель c будет указывать неведомо куда (хотя, с первого взгляда, он должен указывать на строку "Hello, World!").

Еще могут быть глюки, связанные с тем, что AnsiString поддерживает технологию "copy-on-write" - кажется, так это называется... %) Суть в том, что если две или более строк типа AnsiString имеют одинаковое содержимое, то они могут пользоваться одним и тем же буфером для хранения данных, т.е. буфер у них является разделяемым. Но как только нужно будет изменить какую-либо из этих строк, то под ее содержимое выделяется отдельный буфер, в который копируется предыдущее значение разделяемого буфера, и все операции ведутся уже с новым буфером, не затрагивая при этом старый. Тут тоже могут быть такие приколы, типа:

Код:
AnsiString A="Hello, world!";
AnsiString B=A;
AnsiString C(B);

char *cptr=A.c_str();
cptr[0]='*';
Ну и какой тут будет результат? Строки B и C будут содержать "Hello, world!", а строка A будет равна "*ello, world!"? Не-а! Все три строки будут равны "*ello, world!", ибо буфер один и тот же, и объект A класса AnsiString не узнал о том, что должен выделить отдельный кусок памяти под изменяемую строку, ибо изменяли мы ее не методами класса AnsiString, а напрямую образаясь к буферу.


и т.д., и т.п. Поэтому, если в результате каких-то операций с AnsiString'ами нам, в конце концов, надо получить строку типа char*, то делать это надо как-то так:

Код:
AnsiString X; // допустим, это - то, что нам надо заиметь в виде char*
int L=X.Length(); // определяем длину строки
char *cptr=new char[L+1]; // подготавливаем буфер, достаточный для хранения строки
strcpy(cptr,X.c_str()); // копируем строку в буфер
...
delete []cptr; // освобождаем память
 
Статус
Закрыто для дальнейших ответов.