C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Замена текста
Антон
  Отправлено: 09.01.2006, 17:48


Ученик-кочегар

Группа: Участник
Сообщений: 8



sad.gif как заменить один символ другим в 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
Код почему-то не действует, ты наверное что-то недописал. sad.gif
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
Код почему-то не действует, ты наверное что-то недописал. sad.gif

Ну могли уж и сами додумать smile.gif
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)
Прошу прощения, вообще то имелось ввиду нечто подобное

Ну, это уже не принципиально. smile.gif Во всяком случае, использование связки Pos, Insert, Delete — куда менее эффективно.
AVC
Отправлено: 11.01.2006, 10:12


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE
использование связки Pos, Insert, Delete — куда менее эффективно.

Естественно. smile.gif
Просто хотелось еще раз обратить внимание на использование внутреннего буфера AnsiString — многие этого боятся. ohmy.gif
Использование [] AnsiString намного медленнее чем доступ через c_str(). При работе с длинными строками это может стать критичным.
Asher
Отправлено: 11.01.2006, 11:41


Мастер участка

Группа: Модератор
Сообщений: 550



Привет.
QUOTE
Просто хотелось еще раз обратить внимание на использование внутреннего буфера AnsiString — многие этого боятся.

Далее мое ИМХО.
И правильно делают. wink.gif
Нефиг напрямую во внутренний буфер ходить.
Да, если размер не поменяется, то это, в принципе, легально. Но не до конца. cool.gif
Во-первых 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 и обработал всех. sad.gif
Но мне все это пофиг. Я в основном работаю с 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 и одинаковые настройки компилятора — то работает нормально. biggrin.gif
Но если хотя-бы в одном пункте есть сомнения — то лучше сложные объекты, да еще и 'чужие' не передавать.
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

Вернуться в Вопросы программирования в C++Builder