Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Builder
Войти
Регистрация
Восстановить пароль
 
Kolbusdkiy
0 / 0 / 1
Регистрация: 14.10.2013
Сообщений: 112
#1

Удалить символы одной строки с другой - C++ Builder

25.05.2015, 20:40. Просмотров 999. Ответов 17
Метки нет (Все метки)

Помогите пожалуйста.
Задача
Даны две строки. Напишите программу, которая из первой заданной строки удаляет каждый символ, принадлежащий второй заданной строке.

Вот набросал, вылетает.
C++
1
2
3
4
5
6
7
8
9
AnsiString str=edA->Text;
AnsiString st=edB->Text;
mmOut->Lines->Clear();
 
for (int i = 1; i <=str.Length(); i++)
     for (int j = 1; j <=st.Length(); j++)
        if(str[i]==st[i])
                str.Delete(st[i], 1);
     ShowMessage(str);
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.05.2015, 20:40
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Удалить символы одной строки с другой (C++ Builder):

удалить символы из строки
Пытаюсь удалить все символы из строки, кроме символов-цифр. Но не корректно...

Проверка наличия символов одной строки в другой Ансистринг
for(int i=1; i&lt;=alfa.Length()+1;i++) for(int j=1; j&lt;=s.Length();...

Как у строки AnsiString удалить все символы кроме первого?
Как у строки AnsiString удалить все символы кроме первого?

Удалить из RE символы определенного цвета
Здравствуйте!!! Существует ли возможность удалить из RichEdit'a символы,...

Удалить повторяющиеся символы в строке.
Есть отсортированная строка (например, aabbcceee). Нужно получить abce. Я...

Обратиться из одной формы к элементам другой
Можно ли по кнопке Button1, находящейся на форме 2, изменить свойство Caption...

17
Samrisbe
1351 / 721 / 66
Регистрация: 28.01.2011
Сообщений: 1,979
25.05.2015, 23:14 #2
Точно могу сказать что цикл надо сделать в обратную сторону, ибо удаляя символ ты смещаешь номер последующих символов
1
Sasha
4918 / 2383 / 529
Регистрация: 05.06.2008
Сообщений: 7,465
Записей в блоге: 3
26.05.2015, 01:23 #3
Цитата Сообщение от Kolbusdkiy Посмотреть сообщение
if(str[i]==st[i])
тут ещё в этой строке ошибка
1
nick42
Практикантроп
4216 / 2249 / 379
Регистрация: 23.09.2011
Сообщений: 4,821
26.05.2015, 08:39 #4
.. а вылет потому, что строки могут быть разной длины, а вторую шмонают при ограничителе для i по длине первой.
1
SatanaXIII
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 1
26.05.2015, 10:49 #5
C++
1
2
3
4
5
6
7
8
9
10
//AnsiString str=edA->Text;
//AnsiString st=edB->Text;
//mmOut->Lines->Clear();
 
AnsiString str = "abcdef6646";
AnsiString st = "dd4b";
for( int i = 1; i <= str.Length(); i++ )
  if( str.IsDelimiter( st, i ) )
    str.Delete( i, 1 );
ShowMessage( str );
3
_Dimon_
1394 / 557 / 127
Регистрация: 31.10.2011
Сообщений: 1,952
26.05.2015, 11:24 #6
еще вариант с StringReplace
C++
1
2
3
4
5
6
7
String str1 = "qwertyuiop";
String str2 = "wryi";
 
for (int i=1; i <= str2.Length(); i++)
 str1 = StringReplace(str1, str2[i], "", TReplaceFlags() << rfReplaceAll);
 
ShowMessage(str1);
1
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25622 / 17175 / 6830
Регистрация: 22.10.2011
Сообщений: 30,369
Записей в блоге: 6
26.05.2015, 11:29 #7
Цитата Сообщение от Samrisbe Посмотреть сообщение
цикл надо сделать в обратную сторону
Не надо. Это не Дельфи, где конечное значение цикла не пересчитывается на каждой итерации.
1
SatanaXIII
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 1
26.05.2015, 11:31 #8
_Dimon_, мне интересно даже каков подходя окажется быстрее при реальных значениях строк. Что-то я даже не могу спрогнозировать.
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25622 / 17175 / 6830
Регистрация: 22.10.2011
Сообщений: 30,369
Записей в блоге: 6
26.05.2015, 11:34 #9
Самым быстрым будет не удалять символы из строки, а собирать новую строку из символов s1, которых нет в s2... Удаление - дорогая операция.
2
_Dimon_
1394 / 557 / 127
Регистрация: 31.10.2011
Сообщений: 1,952
26.05.2015, 11:44 #10
Цитата Сообщение от volvo Посмотреть сообщение
Самым быстрым будет не удалять символы из строки, а собирать новую строку из символов s1, которых нет в s2
а StringReplace так и делает
Кликните здесь для просмотра всего текста
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
function StringReplace(const S, OldPattern, NewPattern: string;
  Flags: TReplaceFlags): string;
const
  FirstIndex = Low(string);
var
  SearchStr, Patt, NewStr: string;
  Offset, I, L: Integer;
begin
  if rfIgnoreCase in Flags then
  begin
    SearchStr := AnsiUpperCase(S);
    Patt := AnsiUpperCase(OldPattern);
  end else
  begin
    SearchStr := S;
    Patt := OldPattern;
  end;
  NewStr := S;
  Result := '';
  if SearchStr.Length <> S.Length then
  begin
    I := FirstIndex;
    L := OldPattern.Length;
    while I <= High(S) do
    begin
      if string.Compare(S, I - FirstIndex, OldPattern, 0, L, True) = 0 then
      begin
        Result := Result + NewPattern;
        Inc(I, L);
        if not (rfReplaceAll in Flags) then
        begin
          Result := Result + S.Substring(I - FirstIndex, MaxInt);
          Break;
        end;
      end
      else
      begin
        Result := Result + S[I];
        Inc(I);
      end;
    end;
  end
  else
  begin
    while SearchStr <> '' do
    begin
      Offset := AnsiPos(Patt, SearchStr);
      if Offset = 0 then
      begin
        Result := Result + NewStr;
        Break;
      end;
      Result := Result + Copy(NewStr, 1, Offset - 1) + NewPattern;
      NewStr := Copy(NewStr, Offset + Length(OldPattern), MaxInt);
      if not (rfReplaceAll in Flags) then
      begin
        Result := Result + NewStr;
        Break;
      end;
      SearchStr := Copy(SearchStr, Offset + Length(Patt), MaxInt);
    end;
  end;
end;
0
SatanaXIII
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 1
26.05.2015, 11:46 #11
volvo, да, да. Я имею в виду именно вот два этих предложенных подхода. Если приглядеться в них есть координальная разница, но делают они ровно одно и то же. Очень интересно.
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25622 / 17175 / 6830
Регистрация: 22.10.2011
Сообщений: 30,369
Записей в блоге: 6
26.05.2015, 11:52 #12
Цитата Сообщение от _Dimon_ Посмотреть сообщение
а StringReplace так и делает
StringReplace делает еще много ненужного в данном случае, и из-за этого может проиграть даже удалению символов по скорости.
0
_Dimon_
1394 / 557 / 127
Регистрация: 31.10.2011
Сообщений: 1,952
26.05.2015, 11:57 #13
volvo, думаю при компиляции оптимизатор (если он включен) с этим разберется
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25622 / 17175 / 6830
Регистрация: 22.10.2011
Сообщений: 30,369
Записей в блоге: 6
26.05.2015, 12:02 #14
У Билдера? Не смеши меня. К тому же, подпрограмма написана на Дельфи, разберется тебе оптимизатор, как же. Он может только загубить что-нибудь, поэтому приходится его отключать, ни разу пользы от него не было ни на грош. Вред - был.
0
Samrisbe
1351 / 721 / 66
Регистрация: 28.01.2011
Сообщений: 1,979
26.05.2015, 14:31 #15
Цитата Сообщение от volvo Посмотреть сообщение
Не надо. Это не Дельфи
а здесь не похожая задача?
0
SatanaXIII
Супер-модератор
Эксперт С++
5765 / 2763 / 374
Регистрация: 01.11.2011
Сообщений: 6,717
Завершенные тесты: 1
26.05.2015, 14:55 #16
Ладушки. Сам померю.
Код простенького замера
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <time.h>
#include <memory>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
clock_t StartTime, StopTime;
std::auto_ptr< TStringList > sl ( new TStringList );
sl->LoadFromFile( "File53.txt" ); // 53kb
//sl->LoadFromFile( "File123.txt" ); //123kb
AnsiString str = sl->Text;
AnsiString st  = sl->Strings[0];
AnsiString str1 = sl->Text;
AnsiString str2 = sl->Strings[0];
 
/**/
StartTime = GetTickCount( );
 
for( int i = 1; i <= str.Length(); i++ )
  if( str.IsDelimiter( st, i ) )
    str.Delete( i, 1 );
 
StopTime = GetTickCount( );
Memo1->Lines->Add( StopTime-StartTime );
/**/
 
/**/
StartTime = GetTickCount( );
 
for (int i=1; i <= str2.Length(); i++)
 str1 = StringReplace(str1, str2[i], "", TReplaceFlags() << rfReplaceAll);
 
StopTime = GetTickCount( );
Memo1->Lines->Add( StopTime-StartTime );
/**/
}


Три замера для строки, размером в 53 кб:
IsDelimiter StringReplace
438 3140
391 3047
375 3047

Три замера для строки, размером в 123 кб:
IsDelimiter StringReplace
2578 20718
2594 20938
2844 21656
1
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25622 / 17175 / 6830
Регистрация: 22.10.2011
Сообщений: 30,369
Записей в блоге: 6
26.05.2015, 15:59 #17
Цитата Сообщение от Samrisbe Посмотреть сообщение
а здесь не похожая задача?
Похожая. Но обрати внимание, что там происходит. Как раз-таки конечное значение цикла берется сразу, в начале, а не вычисляется на каждой итерации. Поэтому там обязателен обратный цикл, а здесь - не обязателен. Ну, или убрать инициализацию i_limit, и использовать вместо этой переменной Error->Count
1
_Dimon_
1394 / 557 / 127
Регистрация: 31.10.2011
Сообщений: 1,952
27.05.2015, 20:06 #18
SatanaXIII, и все-таки твой код неправильный
C++
1
2
3
4
5
6
AnsiString str = "abcdef6646";
AnsiString st = "dd4b";
for( int i = 1; i <= str.Length(); i++ )
  if( str.IsDelimiter( st, i ) )
    str.Delete( i, 1 );
ShowMessage( str );
Если в входной строке будет 2 подряд "неугодных" символа, то один из них будет пропущен.
Тогда или
C++
1
str.Delete( i--, 1 );
или
Цитата Сообщение от Samrisbe Посмотреть сообщение
Точно могу сказать что цикл надо сделать в обратную сторону, ибо удаляя символ ты смещаешь номер последующих символов
Добавлено через 4 часа 48 минут
Цитата Сообщение от volvo Посмотреть сообщение
Самым быстрым будет не удалять символы из строки, а собирать новую строку из символов s1, которых нет в s2... Удаление - дорогая операция.
Я даже удивился на сколько!

Проверял так-же, какSatanaXIII. Загнал файл ~173 кб. Выбрал строку для фильтра побольше...
Код

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <time.h>
#include <memory>
void __fastcall TfMain::Button3Click(TObject *Sender)
{
//
 clock_t StartTime, StopTime;
 std::auto_ptr< TStringList > sl ( new TStringList );
 sl->LoadFromFile( "D:\\__TEST\\test.txt" ); // 173kb
 
 String str_delete = sl->Text;
 String str_replace = sl->Text;
 String str_new = sl->Text;
 String filter_str  = sl->Strings[25]; // взял строку побольше
 
/***************************************************************************/
 StartTime = GetTickCount();
 
 for(int i = 1; i <= str_delete.Length(); i++)
  if(str_delete.IsDelimiter( filter_str, i ))
    str_delete.Delete(i--, 1);
 
 StopTime = GetTickCount();
 Memo1->Lines->Add("DeleteString: "+String(StopTime-StartTime));
/***************************************************************************/
 StartTime = GetTickCount();
 
 for (int i=1; i <= filter_str.Length(); i++)
  str_replace = StringReplace(str_replace, filter_str[i], "", TReplaceFlags() << rfReplaceAll);
 
 StopTime = GetTickCount();
 Memo1->Lines->Add("StringReplace: "+String(StopTime-StartTime));
/***************************************************************************/
 StartTime = GetTickCount();
 String str_output;
 
 for(int i = 1; i <= str_new.Length(); i++)
  if(!str_new.IsDelimiter(filter_str, i))
    str_output+=str_new[i];
 
 StopTime = GetTickCount();
 Memo1->Lines->Add("NewString: "+String(StopTime-StartTime));
/***************************************************************************/
 
}


Результат
DeleteString: 3682
StringReplace: 7285
NewString: 110
1
27.05.2015, 20:06
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.05.2015, 20:06
Привет! Вот еще темы с решениями:

Запуск одной программы из-под другой
Пытаюсь написать программу - службу, которая в нужный момент будет запускать...

Как передавать данные от одной программы к другой?
Искал темы похожие, не нашел, простите если не туда. Такая задача: написать 2...

Переход из одной формы к другой форме и обратно
Здравствуйте Форумчани. Вопрос в следующем. Я создал три формы. Первая форма...

Как связать Builder XE, установленный на одной ОС, с другой ОС?
У меня на Windows7 установлен BuilderXE. Хочу сделать так, чтобы он же работал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru