Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Разбить строку в массив, аналог explode в php 
:(
    Опции темы
icewind
Дата 6.5.2009, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 11.4.2009
Где: Ростов-на-Дону

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



Помогите, пожалуйста. Необходимо разбить строку на слова по пробелу. Тип строки обязательно char. Пытался сделать так

Код

 char ** _explode( char * context )
                {
                        int i = 0, j = 0, l = 0;
                        char buffer[100];
                        char ** result;
                        while( context[i] != '\0' )
                        {
                                if( ' ' == context[i] )
                                {
                                        result[l++] = (char*)malloc(sizeof(buffer));
                                        strcpy(result[l], buffer);
                                        memset(buffer, 0, 100);
                                        j = 0;
                                }
                                else
                                {
                                        buffer[j++] = context[i];
                                }
                                i++;
                        }
                }


но вываливается с segmentation fault. Как лучше реализовать эту задачу?


--------------------
user posted image
PM MAIL Skype   Вверх
Alca
Дата 6.5.2009, 12:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код

std::vector<std::string> vecsSplit(CHAR cDelimiter, const std::string &csStr) {
    assert(false == csStr.empty(), std::vector<std::string>()); 
    
    std::vector<std::string> vecRes;
    std::size_t              uiPos    = 0;    //start of string    
    std::size_t              uiOldPos = 0;    //start of string
   
   while (std::string::npos != (uiPos = csStr.find_first_of(cDelimiter, uiOldPos))) {
        vecRes.push_back(csStr.substr(uiOldPos, uiPos - uiOldPos));
        uiOldPos = uiPos + 1;
   }
   vecRes.push_back(csStr.substr(uiOldPos, - 1));
   
   return vecRes;
}



--------------------
PM WWW ICQ Skype Jabber   Вверх
zim22
Дата 6.5.2009, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



Код

#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

int main()
{  
  std::string str("hello my very beautiful string");
  std::istringstream is(str);
  std::vector<std::string> vs((std::istream_iterator<std::string>(is)),
                              (std::istream_iterator<std::string>()));
  std::copy(vs.begin(), 
            vs.end(), 
            std::ostream_iterator<std::string>(std::cout, "\n"));
    return 0;
}





--------------------
PM MAIL   Вверх
icewind
Дата 6.5.2009, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 11.4.2009
Где: Ростов-на-Дону

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



Спасибо за совет, но string и vector не пойдет. Не смотря на то что пишу на c++ нужны на входе обязательно char *, а на выходе char**. Знаю что в с++ лучше использовать STL, но мне дальше эти данные обрабатывать именно как char. Переписывать все не хочется.


--------------------
user posted image
PM MAIL Skype   Вверх
Alca
Дата 6.5.2009, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}


Добавлено через 21 секунду
http://www.cplusplus.com/reference/clibrary/cstring/strtok/


--------------------
PM WWW ICQ Skype Jabber   Вверх
zim22
Дата 6.5.2009, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



Цитата(icewind @  6.5.2009,  13:08 Найти цитируемый пост)
Спасибо за совет, но string и vector не пойдет

С-функция strtok()


--------------------
PM MAIL   Вверх
Alca
Дата 6.5.2009, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Код

std::vector<std::string> vecsSplitEx(CHAR *pszStr, CHAR *pszDelimiter) {
    std::vector<std::string> vecRes;
    std::size_t              uiPos     = 0; 
    std::size_t              uiPrevPos = 0;
    std::string              sCopy     = std::string(pszStr);

    while (std::string::npos != (uiPos = sCopy.find(pszDelimiter, uiPos))) {
        vecRes.push_back(std::string(sCopy, uiPrevPos, uiPos - uiPrevPos));
        uiPrevPos = ++ uiPos;
    }
    vecRes.push_back(std::string(sCopy, uiPrevPos, sCopy.size() - uiPrevPos));

    return vecRes;
}



--------------------
PM WWW ICQ Skype Jabber   Вверх
zim22
Дата 6.5.2009, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



...

Это сообщение отредактировал(а) zim22 - 6.5.2009, 13:14


--------------------
PM MAIL   Вверх
icewind
Дата 6.5.2009, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 11.4.2009
Где: Ростов-на-Дону

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



Спасибо. Но strtok я уже смотрел и статический буфер при обработке строки не очень подходит. 
У меня уже сложилось впечатление что я с самого начала не туда копать начал... 
Вот вроде перебор по символам придумал, но не вышло... Думаю с памятью накосячил. Если просто распечатывать буфер, то все работает


Это сообщение отредактировал(а) icewind - 6.5.2009, 13:25


--------------------
user posted image
PM MAIL Skype   Вверх
Alca
Дата 6.5.2009, 13:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Вот еще ссылочка:
Аналог php::explode для C++


--------------------
PM WWW ICQ Skype Jabber   Вверх
icewind
Дата 6.5.2009, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 11.4.2009
Где: Ростов-на-Дону

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



Цитата(Alca @ 6.5.2009,  13:28)
Вот еще ссылочка:
Аналог php::explode для C++

Спасибо, но это опять не в мою кассу... До того как задаться этим вопросом я думал есть рабочая сишная функция для этого, а не те учебные примеры если у нас не больше 10 слов и в каждом слове по 8 символов тогда в цикле печатаем... Странновато...  smile 


--------------------
user posted image
PM MAIL Skype   Вверх
math64
Дата 6.5.2009, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



По строке пожно пройтись и в два прохода - это не файл.
Первый проход - подсчёт числа слов, выделение памяти для результата
strtok() портит исходную строку
Используй strchr(), strspn(), strcspn()
Код

int split(const char* str, const char* delim, char** outbuf, int buflen) {
  int n = 0;
  int offset = 0;
  for(int n=0; n < buflen;) {
     ...
     // нашли слово
     if (outbuf != NULL) {
       char* p = new char[len+1];
       strncpy(p, str + offset, len);
       p[len]= 0; 
       outbuf[n] = p;
     }
     n++;
     offset += len;
  }
  return n;
}

int main() {
   char* s;
   int n = split(s, " ", NULL, 0);
   char**res = new int[n];
   split(s, " ", res, n);
   ...
   for(int i=0; i < n; i++)
      delete[] res[i];
   delete res;
}


Это сообщение отредактировал(а) math64 - 6.5.2009, 14:38
PM   Вверх
icewind
Дата 6.5.2009, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 393
Регистрация: 11.4.2009
Где: Ростов-на-Дону

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



Спасибо за совет! Я о двух проходах не думал. Попробую


--------------------
user posted image
PM MAIL Skype   Вверх
Dov
Дата 6.5.2009, 17:49 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(icewind @  6.5.2009,  13:24 Найти цитируемый пост)
Но strtok я уже смотрел и статический буфер при обработке строки не очень подходит. 

Не понял в чём проблема, но, по-моему, strtok  прекрасно справляется со своей задачей.
Код
char ** _explode( char * str, int & count )
{
    char** result;
    char * buf    = strdup(str);
    char * p      = buf;
    char * sep    = " ";
    
    for(count = 1; *p; p++)
        count += (*p == *sep);

    result  = (char **)malloc(sizeof(char *) * count);
    p       = strtok(buf, sep); 
    for(int i  = 0; p != NULL; i++)
    {
        result[i] = strdup(p);
        p         = strtok(NULL, sep);
    }

    free(buf);
    return result;
}


int main()
{
    char      str[] = "1 22 333 4444 55555";
    int       cnt;
    char **   pp;

    cout << str << endl << endl;

    pp = _explode(str, cnt);

    for(int i = 0; i < cnt; i++)
        cout << pp[i] << endl;

    for(int i = 0; i < cnt; i++)
        free(pp[i]);
    free(pp);

    return 0;
}



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
math64
Дата 7.5.2009, 08:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Dov @  6.5.2009,  17:49 Найти цитируемый пост)
Не понял в чём проблема, но, по-моему, strtok  прекрасно справляется со своей задачей.

Перед его использованием ты делаешь strdup() оригинальной строки и делаешь strdup() найденных слов - то что портится КОПИЯ исходной строки, роли не влияет.
Но вот размер массива result вычисляется неточно (если будут два пробела подряд - выделяется больше чем нужно).
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

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

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

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

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


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

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


 




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


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

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