Антон |
Отправлено: 09.01.2006, 17:48 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 8
|
как заменить один символ другим в Memo.
Я пользовался Replace, но у меня не получилось. |
|
Aptem |
Отправлено: 10.01.2006, 05:33 |
|
Мастер участка
Группа: Участник
Сообщений: 349
|
Вот пример замены в тексте точки на запятую.
CODE | AnsiString Text;
int pos;
Text = Memo1 -> Text;
pos = Text.Pos ( "." ); // здесь символ который нужно заменить
if ( Text.Length () )
{
Text = Text.Insert ( ",", pos ); // а здесь тот символ на который нужно заменить
Text = Text.Delete ( pos+1, 1 );
} |
Отредактировано Aptem — 10/01/2006, 05:34
|
|
AVC |
Отправлено: 10.01.2006, 10:04 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Если вспомнить, что AnsiString можно представить как массив байтов, то все можно сделать намного красивее и эффективнее. |
|
Антон |
Отправлено: 10.01.2006, 20:56 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 8
|
Aptem
Код почему-то не действует, ты наверное что-то недописал. |
|
Grigoriy |
Отправлено: 11.01.2006, 01:18 |
|
Мастер участка
Группа: Участник
Сообщений: 381
|
Здравствуйте.
Экспериментируйте...
"*.h" — файл
CODE |
#ifndef Unit1zamenavmemo1H
#define Unit1zamenavmemo1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMemo *Memo1;
TEdit *Edit1;
TButton *Button1;
TEdit *Edit2;
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
|
"*.cpp" — файл
CODE |
#include <vcl.h>
#pragma hdrstop
#include "Unit1zamenavmemo1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char ch,ch1;
AnsiString str;
int pos1;
ch=Edit1->Text[1];
ch1=Edit2->Text[1];
str=Memo1->Text;
while (pos1=str.Pos(ch)) str[pos1]=ch1;
Memo1->Text=str;
}
|
Отредактировано Grigoriy — 11/01/2006, 01:18
|
|
Aptem |
Отправлено: 11.01.2006, 05:06 |
|
Мастер участка
Группа: Участник
Сообщений: 349
|
QUOTE (Антон @ 10/01/2006, 20:56) | Aptem
Код почему-то не действует, ты наверное что-то недописал. |
Ну могли уж и сами додумать
CODE |
AnsiString Text;
int pos;
Text = Memo1 -> Text;
pos = Text.Pos ( "." ); // здесь символ который нужно заменить
if ( Text.Length () )
{
Text = Text.Insert ( ",", pos ); // а здесь тот символ на который нужно заменить
Text = Text.Delete ( pos+1, 1 );
Memo1 -> Text = Text; // забыли обратно присвоить Memo
} |
|
|
gvg |
Отправлено: 11.01.2006, 09:23 |
|
Машинист паровоза
Группа: Участник
Сообщений: 222
|
QUOTE (AVC @ 10/01/2006, 10:04) | Если вспомнить, что AnsiString можно представить как массив байтов, то все можно сделать намного красивее и эффективнее. |
Вот же подсказка от AVC.
CODE |
for( int i = 1; i <= Memo->Text.Length(); i++ )
if( Memo->Text[i] == '.' )
Memo->Text[i] = ',';
| |
|
AVC |
Отправлено: 11.01.2006, 09:54 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Прошу прощения, вообще то имелось ввиду нечто подобное
CODE |
AnsiString str = Memo->Text;
for (char *cp=str.c_str(); *cp; cp++) if (*cp == '.') *cp = ',';
Memo->Text = str;
|
Если возникнут вопросы по поводу эффективности и допустимости, то можно посмотреть это обсуждение. |
|
gvg |
Отправлено: 11.01.2006, 10:01 |
|
Машинист паровоза
Группа: Участник
Сообщений: 222
|
QUOTE (AVC @ 11/01/2006, 09:54) | Прошу прощения, вообще то имелось ввиду нечто подобное
|
Ну, это уже не принципиально. Во всяком случае, использование связки Pos, Insert, Delete — куда менее эффективно. |
|
AVC |
Отправлено: 11.01.2006, 10:12 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE | использование связки Pos, Insert, Delete — куда менее эффективно. |
Естественно.
Просто хотелось еще раз обратить внимание на использование внутреннего буфера AnsiString — многие этого боятся.
Использование [] AnsiString намного медленнее чем доступ через c_str(). При работе с длинными строками это может стать критичным. |
|
Asher |
Отправлено: 11.01.2006, 11:41 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет.
QUOTE | Просто хотелось еще раз обратить внимание на использование внутреннего буфера AnsiString — многие этого боятся. |
Далее мое ИМХО.
И правильно делают.
Нефиг напрямую во внутренний буфер ходить.
Да, если размер не поменяется, то это, в принципе, легально. Но не до конца.
Во-первых c_str() игнорирует возможную константность строки. Она при этом может быть размещена в области только для чтения и на новых процессорах с битом защиты это вызовет exception. Да и по-любому нарушение константности — плохо.
Во-вторых у Вас изначально может быть несколько одинаковых строк и компилятор при оптимизации может сделать из них одну (Если в опциях компилятора установлено Merge duplicate string). А после, если они будут менятся он мастерит копии. А доступ через sStr.c_str()[itPos] = ',' не отслеживается. Копия не создастся и изменятся все строки.
Я бы лучше сделал так:
CODE | int itPos = sStr.Pos(".");
if(0 < itPos)
sStr[itPos] = ','; |
AnsiString::Pos написана на ассемблере и работает очень быстро.
проверка всего одна.
доступ по индексу всего один.
|
|
avc* |
Отправлено: 11.01.2006, 12:06 |
|
Не зарегистрирован
|
2Asher
С этим не поспоришь. Применять нужно разумно.
PS. Один Pos позволяет сделать только одну замену |
|
Asher |
Отправлено: 11.01.2006, 14:24 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет.
QUOTE | Один Pos позволяет сделать только одну замену |
Это да.
Не могли как в std::string сделать — с указание позиции от которой искать. Все было-бы нормально. вместо if завернул в while и обработал всех.
Но мне все это пофиг. Я в основном работаю с std::string.
В AnsiString и обратно конвертирую только при работе с VCL
|
|
gvg |
Отправлено: 11.01.2006, 15:16 |
|
Машинист паровоза
Группа: Участник
Сообщений: 222
|
QUOTE (Asher @ 11/01/2006, 14:24) | Но мне все это пофиг. Я в основном работаю с std::string.
В AnsiString и обратно конвертирую только при работе с VCL |
Кстати, AnsiString нельзя использовать в качестве параметров функций, размещенных в DLL. А как с std::string? |
|
Gedeon |
Отправлено: 11.01.2006, 15:34 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
QUOTE (gvg @ 11/01/2006, 15:16) | Кстати, AnsiString нельзя использовать в качестве параметров функций, размещенных в DLL. |
Ну почему нельзя, можно, просто надо еще пару dll с собой таскать. Все очень подробно описано в хэлпе.
|
|
Asher |
Отправлено: 11.01.2006, 15:50 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет.
QUOTE | А как с std::string? |
Да как сказать...
Если используется один и тот-же компилятор, одна версия STL и одинаковые настройки компилятора — то работает нормально.
Но если хотя-бы в одном пункте есть сомнения — то лучше сложные объекты, да еще и 'чужие' не передавать.
|
|
Grigoriy |
Отправлено: 11.01.2006, 16:06 |
|
Мастер участка
Группа: Участник
Сообщений: 381
|
QUOTE | Во-вторых у Вас изначально может быть несколько одинаковых строк и компилятор при оптимизации может сделать из них одну (Если в опциях компилятора установлено Merge duplicate string). А после, если они будут менятся он мастерит копии. А доступ через sStr.c_str()[itPos] = ',' не отслеживается. Копия не создастся и изменятся все строки. |
Скопировать одну строку в другую, если физической памяти хватит.
|
|
Asher |
Отправлено: 11.01.2006, 16:14 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
QUOTE | Скопировать одну строку в другую, если физической памяти хватит. |
Кого куда?
И в чем тогда смысл опции компилятора?
|
|
Георгий |
Отправлено: 11.01.2006, 21:47 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
QUOTE (Asher @ 11/01/2006, 17:14) | QUOTE | Скопировать одну строку в другую, если физической памяти хватит. |
Кого куда?
И в чем тогда смысл опции компилятора? |
она только для чисто сишных строк. и с этой опцией работает фокус-мокусCODE | char *a="asd";
char *b="asd";
cout<<a<<b<<endl;
a[1]='*';
cout<<a<<b<<endl; | на выводе некоторые компиляторы дают:
asdasd
a*da*d |
|