Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/12: Рейтинг темы: голосов - 12, средняя оценка - 4.50
nill
10 / 10 / 2
Регистрация: 16.08.2009
Сообщений: 418
1

Как разделить строку(аналог функции explode)

13.01.2014, 21:16. Просмотров 2292. Ответов 12
Метки нет (Все метки)

Есть строка string в которую записаны данные разделенные специальным разделителем например |
Как разделить такую строку и записать полученные данные без разделителя в массив ?

нужна функция на с++ аналог explode на php http://www.php.su/explode

Начал писать

C++
1
2
3
4
5
string msg="1|2|3|4";
string razdelitel="|";
 
size_t pos; 
pos = msg.find(razdelitel);
То есть нашел первое вхождение разделителя в строку, а что дальше делать не пойму, как пройти по всей переменной msg и записать данные разделенные | в массив ?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.01.2014, 21:16
Ответы с готовыми решениями:

Есть ли в С аналог функции explode(или split)?
Есть ли в С аналог или сама функция explode или split, которая позволяет...

Как разделить строку на подстроки
Здравствуйте, возник вопрос по парсингу строк в c++... Как разделить строку на...

Как разделить строку на слова?
Как разделить строку на слова? без использования функций

Как разделить строку на слова?
Помогите написать функцию для разбиения передаваемой строки на слова. Например...

Файл: Как наиболее эффективно разделить строку?
В файле есть например: James 0.8 0.7 0.75 0.5 0.85 J Как наиболее эффективно...

12
Bend3r
149 / 136 / 35
Регистрация: 29.07.2012
Сообщений: 709
13.01.2014, 21:37 2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <windows.h>
#include <string.h>
#include <iostream.h>
//----------------------------------------
using namespace std;
 
//------------------------------------------------------------------------------
void main()
{
 
char *buff[] = {"1|2|3|4"};
 
char * p = strtok(buff[0],"|");
while (p!=0)
{
    std::cout << p << '\n';
    p = strtok(NULL,"|");
}
 
 
system("pause");
}
//---------------------------------------------------------------------------
1
nill
10 / 10 / 2
Регистрация: 16.08.2009
Сообщений: 418
13.01.2014, 21:46  [ТС] 3
Bend3r, А при чем тут char ? у меня же string
Как тогда преобразовать переменную string в char ?
0
Bend3r
149 / 136 / 35
Регистрация: 29.07.2012
Сообщений: 709
13.01.2014, 21:49 4
Цитата Сообщение от nill Посмотреть сообщение
Bend3r, А при чем тут char ? у меня же string
Как тогда преобразовать переменную string в char ?
C++
1
string str = buff;
0
nill
10 / 10 / 2
Регистрация: 16.08.2009
Сообщений: 418
13.01.2014, 21:53  [ТС] 5
Bend3r,
Еще раз, изначально у меня переменная std::string
у нее уже есть значение, откуда я возmму массив char в котором записаны все символы из string???
0
Bend3r
149 / 136 / 35
Регистрация: 29.07.2012
Сообщений: 709
13.01.2014, 22:17 6
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
#include <windows.h>
#include <string.h>
#include <iostream.h>
//----------------------------------------
using namespace std;
 
//------------------------------------------------------------------------------
void main()
{
string str = "1|2|3|4";
char buff[50];
strcpy(buff,str.c_str());  //присвоение string в char
string massiv[10];      //ваш массив
int q = -1;
char * p = strtok(buff,"|");    //разбитие на лексемы
while (p!=0){                    //проверка
    ++q;
    massiv[q] = p;        //присвоение в массив новой лексемы до '|'
    p = strtok(NULL,"|");       //переход к следующей
}
for (int i = 0; i <= q; i++) {
    cout << massiv[i].c_str() << endl;
}
 
system("pause");
}
Добавлено через 1 минуту
Можно конечно и без strtok, а с помощью find и copy, но можно и так т.к это проверенный способ.
1
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
13.01.2014, 22:34 7
Если имеется boost, то очень просто:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>
 
int main()
{
   std::string s = "1234|5678|ABCD|0000";
   std::vector<std::string> result;
 
   boost::split(result, s, boost::algorithm::is_any_of("|"));
   for(auto& str : result) std::cout << str << "\n";
}
Добавлено через 49 секунд
А иначе надо повозится.

Добавлено через 6 минут
Еще такое надумал:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
#include <string>
#include <algorithm>
 
int main()
{
   std::string s = "1234|5678|ABCD|0000";
 
   std::replace(s.begin(), s.end(), '|', ' ');
   std::istringstream iss(s);
   std::vector<std::string> result;
   std::copy(std::istream_iterator<std::string>(iss),
             std::istream_iterator<std::string>(),
             std::back_inserter(result));
 
   for(auto& str : result) std::cout << str << "\n";
}
0
nill
10 / 10 / 2
Регистрация: 16.08.2009
Сообщений: 418
13.01.2014, 22:40  [ТС] 8
Bend3r,
Работает только если разделитель из одного символа, а у меня он минимум из 4 символов
попробовал вставить свой разделитель в strtok(); но функция не принимает строку string

DiffEreD,
Спасибо, но пока хочется без boost, как то по простому чтобы
0
Bend3r
149 / 136 / 35
Регистрация: 29.07.2012
Сообщений: 709
13.01.2014, 22:50 9
Цитата Сообщение от nill Посмотреть сообщение
Работает только если разделитель из одного символа, а у меня он минимум из 4 символов
попробовал вставить свой разделитель в strtok(); но функция не принимает строку string
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
#include <windows.h>
#include <string.h>
#include <iostream.h>
//----------------------------------------
using namespace std;
 
//------------------------------------------------------------------------------
void main()
{
string str = "Hello1234kak dela1234ahah1234";
char buff[50];
strcpy(buff,str.c_str());  //присвоение string в char
string massiv[10];      //ваш массив
int q = -1;
char * p = strtok(buff,"1234");    //разбитие на лексемы
while (p!=0){                    //проверка
    ++q;
    massiv[q] = p;        //присвоение в массив новой лексемы до '|'
    p = strtok(NULL,"1234");       //переход к следующей
}
for (int i = 0; i <= q; i++) {
    cout << massiv[i].c_str() << endl;
}
 
system("pause");
}
1
nill
10 / 10 / 2
Регистрация: 16.08.2009
Сообщений: 418
13.01.2014, 23:07  [ТС] 10
Bend3r,
Моя ошибка, не заметил у тебя там два раза нужно вводить разделитель. Все работает!
0
nill
10 / 10 / 2
Регистрация: 16.08.2009
Сообщений: 418
16.01.2014, 00:01  [ТС] 11
Bend3r,

С функцией проблема
она не работает если разделитель не писать текстом "1234", а передавать через переменную
C++
1
2
3
4
5
6
7
8
9
10
11
12
string razdelitel="1234";
char razdelitel_ch[5];
strcpy(buff,str.c_str());  //присвоение string в char
strcpy(razdelitel_ch,razdelitel.c_str());  //присвоение string в char
 
    int q = -1;
    char * p = strtok(buff,razdelitel_ch);    //разбитие на лексемы
    while (p!=0){                    //проверка
        ++q;
        result_mass[q] = p;        //присвоение в массив новой лексемы до '|'
        p = strtok(NULL,razdelitel_ch);       //переход к следующей
    }
И еще даже если писать разделитель тестом, то функция работает с ошибкой, она разделяет строку даже когда встретит какой то один символ из тех что входят в разделитель, а нужно делить только когда встречаются все символы которые входят в разделитель.

Подскажи плз что не так и как исправить ?

Написал свою функцию все работает,
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
string explode(string text, string razdelitel, string result_mass[200]){
    string result;
    int i=0, n=0, j=0;
 
    //_cprintf(" text= %s", text.c_str());_cprintf("\n");
 
 
    for (i=0; i<sizeof(result_mass); i++){result_mass[i]="";}
    char text_ch[65535];
    char razdelitel_ch[15];
 
    strcpy(text_ch, text.c_str()); 
    strcpy(razdelitel_ch, razdelitel.c_str());
    ev_time_start =clock();
    for (i=0; i<sizeof(text_ch); i++){
        if(text_ch[i]==0){break;}
        if(text_ch[i]==razdelitel_ch[0]&&text_ch[i+1]==razdelitel_ch[1]&&text_ch[i+2]==razdelitel_ch[2]&&text_ch[i+3]==razdelitel_ch[3]){
 
 
            for (j=i+4; j<sizeof(text_ch); j++){
 
                if(text_ch[j]==razdelitel_ch[0]&&text_ch[j+1]==razdelitel_ch[1]&&text_ch[j+2]==razdelitel_ch[2]&&text_ch[j+3]==razdelitel_ch[3]){n++;break;}
 
 
                result_mass[n]=result_mass[n]+text_ch[j];
                i=j;
            }}}
    ev_time_end =clock();
    ev_time = (double)(ev_time_end-ev_time_start)/1000;
    _cprintf("sikl:%f ", ev_time);_cprintf("sec");_cprintf("\n");
 
    return result;
}
но медленно около 2 сек на 1 функцию и хотелось бы отладить твой быстрый способ.
0
Bend3r
149 / 136 / 35
Регистрация: 29.07.2012
Сообщений: 709
16.01.2014, 17:59 12
Цитата Сообщение от nill Посмотреть сообщение
Bend3r, С функцией проблема
она не работает если разделитель не писать текстом "1234", а передавать через переменную
Вы как всегда не внимательны. Вот я вам переделал чтоб разделитель был в виде переменной.
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
#include <windows.h>
#include <string.h>
#include <iostream.h>
//----------------------------------------
using namespace std;
 
//------------------------------------------------------------------------------
void main()
{
string str = "Hello1234kak dela1234ahah1234";
string razdel = "1234";
char buff[50];
strcpy(buff,str.c_str());  //присвоение string в char
string massiv[10];      //ваш массив
int q = -1;
char * p = strtok(buff,razdel.c_str());    //разбитие на лексемы
while (p!=0){                    //проверка
    ++q;
    massiv[q] = p;        //присвоение в массив новой лексемы до '|'
    p = strtok(NULL,razdel.c_str());       //переход к следующей
}
for (int i = 0; i <= q; i++) {
    cout << massiv[i].c_str() << endl;
}
 
system("pause");
}
Добавлено через 7 минут
По поводу того как решить проблему, если встречается первый символ разделителя и он разделяет, я пока думаю, но возможно этот способ и не подойдет. А так лучше разберитесь с регулярными выражениями.
1
nill
10 / 10 / 2
Регистрация: 16.08.2009
Сообщений: 418
17.01.2014, 13:46  [ТС] 13
Bend3r,
Сейчас проверил, передача разделителя в функцию через переменную работает, а если встречается символ разделителя опять то же самое.

Моя функция работает как надо, но это почему то очень медленный способ не знаю как его оптимизировать.

С регулярными выражениями я еще больше буду разбираться лучше как то отладить одну из двух функций.

Добавлено через 17 часов 37 минут
В общем разобрался сам
использовать преобразование char в string было ошибкой нужно использовать функции самого string

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
void explode_string(string str, string razdelitel, string result_mass[200]){
 
    int dlinna_razdelitela=razdelitel.length();
    size_t pos;
    size_t pos1;
    int n=0, ot=0, doo=0, dlinna=0;
 
    for (int i=0; i<str.length(); i++){
 
        pos = str.find(razdelitel, i);
        if (pos != string::npos){
 
            pos1 = str.find(razdelitel, pos+1);
 
            ot=pos+dlinna_razdelitela;
            doo=pos1;
            dlinna=doo-ot;
 
            if (pos1 != string::npos){result_mass[n] = str.substr (ot,dlinna);}
            else{result_mass[n] = str.substr (ot);}
 
            n++;
            
 
            i=pos+dlinna_razdelitela;}
 
    }
 
}
1
17.01.2014, 13:46
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.01.2014, 13:46

Как лучше всего разделить строку на несколько подстрок?
Есть строка вида параметр1*параметр2*параметр3*параметр4. Как разделить эту...

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

Как разделить программу на функции
Не могу понять как мне разделить прогу на функции и вообще плохо понимаю что...


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

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

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