Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Аналог php::explode для C++ 
:(
    Опции темы
szz
Дата 2.7.2007, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1289
Регистрация: 31.5.2005
Где: Moscow, Jerusalem

Репутация: 1
Всего: 33



Вот.

Класс для резделения строки на части, используя разделитель - произвольную строку (строку, заметьте, а не букву!)

Путем небольших модификаций зависимость от BCB можно убрать.

Используем так:
Код

// суем:
#include "string_array.h"
....
// создаем обьект:
StringArray z;
// разбиваем:
z.explode("::", "aa::bb::cc");

// используем как хотим, например:
for(int i = 0; i < z.length(); ++i){
   std::string s = z.get(i);
   printf("строка номер %d такая: %s", i, s.c_str());
}
....
 

Сам исходник:
string_array.h
Код

//---------------------------------------------------------------------------

#ifndef string_arrayH
#define string_arrayH

#include <vcl.h>
#include <string>
#include <stdio.h>

#ifndef AS
#define AS AnsiString
#endif


AnsiString s2as(std::string a){
  AS b = a.c_str();
  return b;
}
std::string s2as(AS a){
  std::string b = a.c_str();
  return b;
}
AnsiString std_str2as(std::string a){
  return s2as(a);
}



class StringArray{
public:
    StringArray(){
        len=0;
        allocated=false;
    }
    void explode(std::string delim, std::string cont){
      if(delim=="")return;
        signed int sum=0;
        signed int loc = - signed(delim.length());
        signed int locs=0;
        do{
            locs = loc+delim.length();
            loc = cont.find( delim, locs);
            sum++;
        }while(loc != std::string::npos);
        if(allocated){
            delete [] strs;
        }
        strs = new std::string[sum];
        len = sum;
        allocated=true;
        if(cont.find( delim, 0) == std::string::npos){
            strs[0] = cont;
            return;
        }
        // now parcing again and putting all the parts:
        sum = 0;
        loc = - signed(delim.length());
        do{
            locs = loc+delim.length();
            loc = cont.find( delim, locs);
            strs[sum] = cont.substr(locs, loc-locs);
            sum++;
        }while(loc != std::string::npos);
    }
  std::string implode(std::string delim=""){
      std::string r="";
      if(!allocated)return "ERROR:not allocated";
      int i;
      for(i=0;i<length()-1;++i){
         r+=strs[i]+delim;    
      }
      return r+strs[i];
  }
    void dump(){
        printf("\nelemelts num: %d\n", len);
        if(!allocated)return;
        for(int i=0;i<length();++i){
            printf("str[%d] = %s\n", i, strs[i].c_str());
        }
    }
  std::string str(int i){
    if(allocated && i>=0 && i < length())
      return strs[i];
    return "";
  }
  std::string get(int i){ return str(i); }
  int length(){ return len; }
private:
    bool allocated;
    int len;
    std::string    *strs;
};
// и как бонус - функция - точный аналог phpшной str_replace:
AS str_replace(AS search, AS replace, AS s){
  if(!s.Pos(search)) return s;
  StringArray sa;
  sa.explode(s2as(search), s2as(s));
  return s2as(sa.implode(s2as(replace)));
}

//---------------------------------------------------------------------------
#endif

 


--------------------
PM   Вверх
NFL
Дата 13.8.2011, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



Отлично, как раз в bcb она мне пригодилась smile 
Спасибо  smile 
PM MAIL   Вверх
borisbn
Дата 14.8.2011, 17:04 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 18
Всего: 135



Если автор открыт для критики, то их есть у меня smile и ооооч. много:

1. Нет деструктора, который очищал бы память выделенную под
Цитата
std::string    *strs;

2. Такой класс нельзя копировать
StringArray a;
a.explode( "::", "aa:smile::cc" );
StringArray b = a;
b.explode( " ", "aa bb cc" ); // удаление массива, выделенного для a
Цитата

        if(allocated){
            delete [] strs;
        }

3. Зачем этот изврат с динамическим массивом строк ? Почему не вектор ? Тогда бы и не нужно было бы дважды проходться по строке, деструктор сам бы всё почистил и не было бы проблемы с копированием (п.2)
4. Почему нет const
Цитата
int length() const { return len; }
и
std::string get(int i) const { return str(i); }

5. Почему строки передаются по значению, а не по ссылке ?
Цитата
void explode(std::string delim, std::string cont)

6. Что будет, если подать такую строку и разделитель
Цитата
explode( ":", "a:::b:::c" );

7. Неплохо было бы ввести флаг "выдавать пустые секции" для вариантов
Цитата
explode( ":", "a:b:c:" );
или
explode( ":", ":a:b:c" );

8. Лучше было бы, если б в классе было несколько перегруженных функций для разных разделителей: для строки (уже есть), для одиночного символа, для регулярного выражения.

Посмотри, как у профи это сделано
http://doc.qt.nokia.com/latest/qstring.html#split


NFL, не используй этот код. Он нерабочий и опасный


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
xvr
Дата 15.8.2011, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



И еще - помесь AnsiString'а и std::string'а в одном классе выглядит несколько эклектично  smile 

PM MAIL   Вверх
volatile
Дата 15.8.2011, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 3
Всего: 85



Дата: 2.7.2007
PM MAIL   Вверх
NFL
Дата 16.8.2011, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 137
Регистрация: 5.5.2009

Репутация: нет
Всего: нет



Как бы работает smile 
Моя задача настолько примитивна, что его вполне достаточно smile 
PM MAIL   Вверх
borisbn
Дата 17.8.2011, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 18
Всего: 135



вот вариант какбэ получше smile
http://liveworkspace.org/code/187229067096...5bae250e1e4cfec
Код

#include <string>
#include <vector>
#include <deque>
#include <list>

template< typename CharT,
          class ContainerType = std::vector< std::basic_string< CharT > >
        >
class basic_string_array : public ContainerType
{
public:
    typedef std::basic_string< CharT > string_t;
    typedef typename ContainerType::iterator iterator;
    typedef typename ContainerType::const_iterator const_iterator;

    basic_string_array() {}
    basic_string_array( const string_t & inStr )
        : m_string( inStr )
    {}
    void setString( const string_t & inStr )
    {
        m_string = inStr;
    }
    string_t string() const
    {
        return m_string;
    }
    void split( const string_t & sep, bool skipEmpty = true )
    {
        split( m_string, sep, *this, skipEmpty );
    }
    static void split( const string_t & inStr, const string_t & sep, ContainerType & v, bool skipEmpty = true )
    {
        unsigned int start = 0;
        unsigned int pos = string_t::npos;
        v.clear();
        while ( ( pos = inStr.find( sep, start ) ) != string_t::npos )
        {
            string_t s = inStr.substr( start, pos - start );
            if ( ! s.empty() || ! skipEmpty )
            {
                v.push_back( s );
            }
            start = pos + sep.length();
        }
        string_t s = inStr.substr( start, pos );
        if ( ! s.empty() || ! skipEmpty )
        {
            v.push_back( s );
        }
    }
    const string_t join( const string_t & sep, bool skipEmpty = true )
    {
        m_string = join( *this, sep, skipEmpty );
        return m_string;
    }
    const string_t join( const ContainerType & v, const string_t & sep, bool skipEmpty = true )
    {
        string_t result;
        const_iterator it = v.begin();
        const_iterator theEnd = v.end();
        while ( it != theEnd )
        {
            if ( ! (*it).empty() || ! skipEmpty )
            {
                result += (*it);
                break;
            }
            ++it;
        }
        ++it;
        for ( ; it != theEnd; ++it )
        {
            const string_t & s = (*it);
            if ( ! s.empty() || ! skipEmpty )
            {
                result += sep + s;
            }
        }
        return result;
    }

private:
    string_t m_string;
};

typedef basic_string_array< char > string_vector;
typedef basic_string_array< wchar_t > wstring_vector;
typedef basic_string_array< char, std::deque< std::string > > string_deque;
typedef basic_string_array< wchar_t, std::deque< std::wstring > > wstring_deque;
typedef basic_string_array< char, std::list< std::string > > string_list;
typedef basic_string_array< wchar_t, std::list< std::wstring > > wstring_list;

#include <iostream>

int main()
{
    string_deque v( "-qwe---ewq--" );
    v.split( "-", false );
    for ( string_deque::const_iterator it = v.begin(); it != v.end(); ++it )
    {
        std::cout << (*it) << std::endl;
    }
    std::cout << v.join( "-" ) << std::endl;
}

Цитата

qwe


ewq


qwe-ewq



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mihailpp
Дата 18.8.2011, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 18.8.2011

Репутация: нет
Всего: нет



Спасибо за информацию была кое какая проблема, исправил.
PM MAIL WWW   Вверх
ZVano
Дата 14.9.2011, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 259
Регистрация: 11.12.2006
Где: Украина, Кривой Р ог

Репутация: 1
Всего: 4



Я сделал так (builder 2010)
Код

#include <vector.h>
#include <classes.hpp>

typedef vector<UnicodeString>TVectorOfUnicodeString;

        int Explode(UnicodeString str, UnicodeString separators, bool addEmpty, TVectorOfUnicodeString & out_result) {
            out_result.clear();
            UnicodeString curPart = "";
            int cntSeparators = 0;
            for (int cnrChars = 1; cnrChars <= str.Length(); cnrChars++) {
                UnicodeString curChar = str[cnrChars];
                if (separators.Pos(curChar) > 0) {
                    cntSeparators++;
                    if (addEmpty || (curPart.Length() > 0)) {
                        out_result.push_back(curPart);
                    }
                    curPart = "";
                    continue;
                }
                curPart += curChar;
            }
            // Докидываем последнюю часть, которая без разделителя
            if ((addEmpty & (cntSeparators > 0)) || (curPart.Length() > 0)) {
                out_result.push_back(curPart);
            }

            return out_result.size();
        }



--------------------
НЕ ФЛУДИМ. Пользуемся кнопками "+" или "-" для выражения своего отношения к теме или сообщению.
Гуглим "Как правильно задавать вопросы"
PM MAIL Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.1116 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.