посоветуйте аналог strtok
От: Аноним  
Дата: 03.11.04 13:14
Оценка:
мне нужно парсить строки с разделителями.
для этого я использовал функцию strtok.
теперь появилась необходимость парсить строки в цикле по несколько штук,
а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
Посоветуйте как выкрутиться
Re: посоветуйте аналог strtok
От: korzhik Россия  
Дата: 03.11.04 13:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>мне нужно парсить строки с разделителями.

А>для этого я использовал функцию strtok.
А>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>Посоветуйте как выкрутиться

я бы использовал класс токенайзера (взял бы готовый или использовал свой)
  for (int i = 0; i < N; ++i)
  {
    tokenizer tk1;
    tokenizer tk2;
    tokenizer tk3;

    tk1.set_str(str1);
    tk2.set_str(str2);
    tk3.set_str(str3);
    
    // ...
  }
Re[2]: посоветуйте аналог strtok
От: Аноним  
Дата: 03.11.04 13:29
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, Аноним, Вы писали:


А>>мне нужно парсить строки с разделителями.

А>>для этого я использовал функцию strtok.
А>>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>>Посоветуйте как выкрутиться

K>я бы использовал класс токенайзера (взял бы готовый или использовал свой)

K>
K>  for (int i = 0; i < N; ++i)
K>  {
K>    tokenizer tk1;
K>    tokenizer tk2;
K>    tokenizer tk3;

K>    tk1.set_str(str1);
K>    tk2.set_str(str2);
K>    tk3.set_str(str3);
    
K>    // ...
K>  }
K>


Так я про то и спрашивал.Где его взять?
Re: посоветуйте аналог strtok
От: kmn Украина  
Дата: 03.11.04 13:32
Оценка:
Здравствуйте, Аноним, Вы писали:

А>мне нужно парсить строки с разделителями.

А>для этого я использовал функцию strtok.
А>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>Посоветуйте как выкрутиться

см. strpbrk и strspn

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

int main( void )
{
   char string[100] = "The 333 men and 222 boys ate 555 pigs\n";
   char *result;

   printf( "1: %s\n", string );
   result = strpbrk( string, "0123456789" );
   printf( "2: %s\n", result);
   result += strspn(result, "0123456789");

   result = strpbrk( result, "0123456789" );
   printf( "3: %s\n", result );
   result += strspn(result, "0123456789");

   result = strpbrk( result, "0123456789" );
   printf( "4: %s\n", result );
}


Output
1: The 333 men and 222 boys ate 555 pigs

2: 333 men and 222 boys ate 555 pigs

3: 222 boys ate 555 pigs

4: 555 pigs
Re[3]: посоветуйте аналог strtok
От: korzhik Россия  
Дата: 03.11.04 13:34
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Так я про то и спрашивал.Где его взять?


так я ж сказал, взять готовый или самому написать.
можно взять boost::tokenizer, но он слишком универсальный, за это ты будешь платить скоростью.
можно взять токенайзер от C_SMILE в форуме "Исходники", но я его не использовал ничего сказать не могу.

всё зависит от твоих требований.

работаешь только с ANSI строками?
или нужна поддержка Unicode?

разделитель является символом или строкой?
Re[2]: посоветуйте аналог strtok
От: Аноним  
Дата: 03.11.04 13:40
Оценка:
Здравствуйте, kmn, Вы писали:

kmn>Здравствуйте, Аноним, Вы писали:


А>>мне нужно парсить строки с разделителями.

А>>для этого я использовал функцию strtok.
А>>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>>Посоветуйте как выкрутиться

kmn>см. strpbrk и strspn


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

kmn>int main( void )
kmn>{
kmn>   char string[100] = "The 333 men and 222 boys ate 555 pigs\n";
kmn>   char *result;

kmn>   printf( "1: %s\n", string );
kmn>   result = strpbrk( string, "0123456789" );
kmn>   printf( "2: %s\n", result);
kmn>   result += strspn(result, "0123456789");

kmn>   result = strpbrk( result, "0123456789" );
kmn>   printf( "3: %s\n", result );
kmn>   result += strspn(result, "0123456789");

kmn>   result = strpbrk( result, "0123456789" );
kmn>   printf( "4: %s\n", result );
kmn>}
kmn>


kmn>Output

kmn>1: The 333 men and 222 boys ate 555 pigs

kmn>2: 333 men and 222 boys ate 555 pigs


kmn>3: 222 boys ate 555 pigs


kmn>4: 555 pigs


Похоже,что не очень подходит
У меня строка 1234_4321_8765_6789
в цикле надо получить
1234
4321
8765
6789
Re[4]: посоветуйте аналог strtok
От: Аноним  
Дата: 03.11.04 13:43
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, Аноним, Вы писали:


А>>Так я про то и спрашивал.Где его взять?


K>так я ж сказал, взять готовый или самому написать.

K>можно взять boost::tokenizer, но он слишком универсальный, за это ты будешь платить скоростью.
K>можно взять токенайзер от C_SMILE в форуме "Исходники", но я его не использовал ничего сказать не могу.

K>всё зависит от твоих требований.


K>работаешь только с ANSI строками?

K>или нужна поддержка Unicode?
Работаю только в Unicode(wcstok).

K>разделитель является символом или строкой?

Разделитель символ '_'
Re[5]: посоветуйте аналог strtok
От: korzhik Россия  
Дата: 03.11.04 14:22
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Работаю только в Unicode(wcstok).

А>Разделитель символ '_'

ну требования достаточно простые

я бы написал свой
типа такого
#include <cstring>
class tokenizer
{
    private:  // noncopyable
        tokenizer(const tokenizer&);
        tokenizer& operator=(const tokenizer&);
    public:
        struct token
        {
            const char* ptr;
            unsigned    len;
        };

    public:
        tokenizer(const char* sep = " \t\n\r") :
            m_src_string(0),
            m_start(0),
            m_separator(sep),
            m_sep_len(sep ? (int)std::strlen(sep) : 0)
        {
        }

        void set_str(const char* str )
        { 
            m_src_string = str; 
            m_start = 0;
        }

        bool next(); // throw()

        token current_token() const
        {
            return m_token;
        }
    
    private:
        bool check_chr(const char* str, char chr) const
        {
            return !!std::strchr(str, chr); 
        }
    
    private:
        char const *        m_src_string;
        int                    m_start;
        char const * const    m_separator;
        int    const             m_sep_len;
        token                m_token;
};

//-----------------------------------------------------------------------
bool tokenizer::next()
{
    unsigned count = 0;
    
    m_token.ptr = 0;
    m_token.len = 0;

    if (m_src_string == 0 || m_start == -1) 
        return false;

    const char *pstr = m_src_string + m_start;

    if (*pstr == 0) 
    {
        m_start = -1;
        return false;
    }

    while (*pstr && check_chr(m_separator, *pstr)) 
    {
        ++pstr;
        ++m_start;
    }

    if (*pstr == 0) 
    {
        m_start = -1;
        return false;
    }

    for (count = 0;; ++count) 
    {
        char c = *pstr;
        int found = 0;

        found = check_chr(m_separator, c);

        ++pstr;

        if (c == 0 || found) 
        {
            m_token.ptr = m_src_string + m_start;
            m_token.len = count;

            m_start += count;
            if (c) 
            {
                ++m_start;
                while (check_chr(m_separator, m_src_string[m_start])) 
                {
                    ++m_start;
                }
            }
            break;
        }
    }
    return true;
}

только надо переделать под wchar_t

использование:
int main( )
{
    tokenizer tok("_");

    tok.set_str("112_23_4_556_2");

    while (tok.next())
    {
        tokenizer::token tk = tok.current_token();

        std::cout << std::string(tk.ptr, tk.len) << std::endl;
    }
}
Re[3]: посоветуйте аналог strtok
От: e-smirnov  
Дата: 03.11.04 14:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Похоже,что не очень подходит

А>У меня строка 1234_4321_8765_6789
А>в цикле надо получить
А>1234
А>4321
А>8765
А>6789

Почему не подходит?
Еще подойдет
pStr = strstr(pStr, "_");
if (pStr)
{
   pStr += strlen ("_");
   int n;
   //Вытаскивать числа можешь, например так
   sscanf (result , "%[^_]_", &n);
Re: посоветуйте аналог strtok
От: McSeem2 США http://www.antigrain.com
Дата: 03.11.04 14:33
Оценка:
А>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>Посоветуйте как выкрутиться

Проще всего взять исходник strtok.c (находится в гугле на раз-два) и добавить туда малую толику реентерабельности...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: посоветуйте аналог strtok
От: Bell Россия  
Дата: 03.11.04 14:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>мне нужно парсить строки с разделителями.

А>для этого я использовал функцию strtok.
А>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>Посоветуйте как выкрутиться

int main()
{
   istringstream is("1234_4321_8765_6789");
   string str;
   while(getline(is, str, '_'))
      cerr << str << '\n';

   return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re[3]: посоветуйте аналог strtok
От: kmn Украина  
Дата: 03.11.04 15:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Похоже,что не очень подходит

А>У меня строка 1234_4321_8765_6789
А>в цикле надо получить
А>1234
А>4321
А>8765
А>6789

так в чем проблема?

char * string = "1234_4321_8765_6789";
std::vector<std::string> words;

while (*string)
{
   char * end_word = strpbrk(string, "_");
   if (end_word)
   {
       words.push_back(std::string(string, end_word - string));
       string = end_word + strspn(end_word, "_");
   }
   else
   {
       words.push_back(std::string(string));
       break;
   }
}


BTW: почему все strxxxx функции, с логикой поиск, возвращают NULL а не указатель на "\0"?
Re: посоветуйте аналог strtok
От: _AK_ Россия  
Дата: 03.11.04 17:08
Оценка:
Здравствуйте, Аноним, Вы писали:

А>мне нужно парсить строки с разделителями.

А>для этого я использовал функцию strtok.
А>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>Посоветуйте как выкрутиться

boost::split
Re[2]: посоветуйте аналог strtok
От: yxiie Украина www.enkord.com
Дата: 03.11.04 17:33
Оценка:
Здравствуйте, _AK_, Вы писали:

_AK>Здравствуйте, Аноним, Вы писали:


А>>мне нужно парсить строки с разделителями.

А>>для этого я использовал функцию strtok.
А>>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>>Посоветуйте как выкрутиться

_AK>boost::split


имеется ввиду boost::spirit? а то что-то я такого не видел. это в какой версии?
... << RSDN@Home 1.1.3 stable >>
Re[3]: посоветуйте аналог strtok
От: _AK_ Россия  
Дата: 03.11.04 20:38
Оценка:
Здравствуйте, yxiie, Вы писали:

Y>Здравствуйте, _AK_, Вы писали:


_AK>>Здравствуйте, Аноним, Вы писали:


А>>>мне нужно парсить строки с разделителями.

А>>>для этого я использовал функцию strtok.
А>>>теперь появилась необходимость парсить строки в цикле по несколько штук,
А>>>а функцию strtok нельзя вызывать для другой строки пока не обработал текущую
А>>>Посоветуйте как выкрутиться

_AK>>boost::split


Y>имеется ввиду boost::spirit? а то что-то я такого не видел. это в какой версии?


именно boost::split — качать последнею версию с CVS или draft-тарболлы версии 1.32, boost::split — часть библиотеки для работы со строками, которая появилась в версии 1.32. очень правильная и удобная библиотека.
Re[4]: посоветуйте аналог strtok
От: yxiie Украина www.enkord.com
Дата: 03.11.04 21:33
Оценка:
_AK>именно boost::split — качать последнею версию с CVS или draft-тарболлы версии 1.32, boost::split — часть библиотеки для работы со строками, которая появилась в версии 1.32. очень правильная и удобная библиотека.

это замена tokenizer, или как?
а то этот токенизер, мало того что медленный, дак еще глючил у меня очень странно.
да, когда зарелизят 1.32 испытаем во всем ее величии
... << RSDN@Home 1.1.3 stable >>
Re[5]: посоветуйте аналог strtok
От: _AK_ Россия  
Дата: 03.11.04 22:21
Оценка: +1
Здравствуйте, yxiie, Вы писали:


_AK>>именно boost::split — качать последнею версию с CVS или draft-тарболлы версии 1.32, boost::split — часть библиотеки для работы со строками, которая появилась в версии 1.32. очень правильная и удобная библиотека.


Y>это замена tokenizer, или как?

Y>а то этот токенизер, мало того что медленный, дак еще глючил у меня очень странно.
Y>да, когда зарелизят 1.32 испытаем во всем ее величии

да, tokenizer это вообще писец. тому кто его внёс в состав boost-а надо поотрывать всё что отрывется...
Re: посоветуйте аналог strtok
От: Аноним  
Дата: 04.11.04 12:40
Оценка:
Второй день пытаюсь применить на практике
полученные советы.Получается все очень некрасиво
У меня есть 3 строки
TCHAR str1[]=_T("1342_45_5678_7895_67677_1");
TCHAR str2[]=_T("1542_445_45678_47895_467677_41");
TCHAR str3[]=_T("13425_455_56785_78955_676775_15");
TCHAR seps[]=_T("_");
TCHAR * ptchtoken = function(str1,seps);
TCHAR * ptchtoken1 = function(str2,seps);
TCHAR * ptchtoken2 = function(str3,seps);

for(int i=0;i<6;i++)
{
....
ptchtoken = function(NULL,seps);
ptchtoken1 = function(NULL,seps);
ptchtoken2 = function(NULL,seps);
.....
}

function — это нужная мне функция(аналог strtok)

korzhik предложил использовать свой класс,но в конце использует
для выделения подстроки еще один класс — string
Bell предложил вариант,но с двумя классами istringstream и string
Где взять boost и как его использовать я не знаю.
Посоветуйте,пожалуйста, более простое и удобное решение
Re[2]: посоветуйте аналог strtok
От: korzhik Россия  
Дата: 04.11.04 13:31
Оценка:
Здравствуйте, Аноним, Вы писали:

А>korzhik предложил использовать свой класс,но в конце использует

А>для выделения подстроки еще один класс — string
в своём примере я использую класс std::string только для вывода в поток, так то он не нужен.
Плюс моего подхода в том что он самый быстрый, не делает никаких выделений памяти.

А>Bell предложил вариант,но с двумя классами istringstream и string

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

А>Где взять boost и как его использовать я не знаю.

ну и не надо пока с ним связываться
Re[3]: посоветуйте аналог strtok
От: Аноним  
Дата: 04.11.04 13:49
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, Аноним, Вы писали:


А>>korzhik предложил использовать свой класс,но в конце использует

А>>для выделения подстроки еще один класс — string
K>в своём примере я использую класс std::string только для вывода в поток, так то он не нужен.
K>Плюс моего подхода в том что он самый быстрый, не делает никаких выделений памяти.

Может я чего не допонял,но tk.ptr не кончается на \0
И как же мне выделить нужную подстроку не вызывая никаких функций с tk.len
Re[4]: посоветуйте аналог strtok
От: korzhik Россия  
Дата: 04.11.04 14:10
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Может я чего не допонял,но tk.ptr не кончается на \0

правильно

А>И как же мне выделить нужную подстроку не вызывая никаких функций с tk.len

структура token уже содержит всю нужную информацию:
— указатель на подстроку в исходной строке и
— её длину

ты можешь работать с ней используя функции принимаюшие количество символов, например,
в случае сравнения строк, вместо использования функции strcmp надо использовать strncmp:
  tokenizer::token tk1 = tok1.current_token();
  tokenizer::token tk2 = tok2.current_token();
  if (std::strncmp(tk1.ptr, tk2.ptr,std::min(tk1.len,tk2.len)) == 0)
  {
  }


если же тебе всё таки надо получать подстроки как отдельный строки, то можно делать например так:
  str::string str(tk.ptr, tk.len):
Re[5]: посоветуйте аналог strtok
От: Аноним  
Дата: 04.11.04 14:25
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, Аноним, Вы писали:


А>>Может я чего не допонял,но tk.ptr не кончается на \0

K>правильно

А>>И как же мне выделить нужную подстроку не вызывая никаких функций с tk.len

K>структура token уже содержит всю нужную информацию:
K> — указатель на подстроку в исходной строке и
K> — её длину

K>ты можешь работать с ней используя функции принимаюшие количество символов, например,

K>в случае сравнения строк, вместо использования функции strcmp надо использовать strncmp:
K>
K>  tokenizer::token tk1 = tok1.current_token();
K>  tokenizer::token tk2 = tok2.current_token();
K>  if (std::strncmp(tk1.ptr, tk2.ptr,std::min(tk1.len,tk2.len)) == 0)
K>  {
K>  }
K>


K>если же тебе всё таки надо получать подстроки как отдельный строки, то можно делать например так:

K>
K>  str::string str(tk.ptr, tk.len):
K>


Мне нужно использовать atoi для преобразования подстроки в целое число

Если я использую str::string str(tk.ptr, tk.len),то какой смысл было писать
свой класс,чтобы потом использовать еще один класс.
Re[6]: посоветуйте аналог strtok
От: kmn Украина  
Дата: 04.11.04 14:38
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Мне нужно использовать atoi для преобразования подстроки в целое число



for (int i = 0; i < 6; ++i)
{
    int iValue1 = strtol(string1, end, 10);
    string1 = end + 1;

    int iValue2 = strtol(string2, end, 10);
    string2 = end + 1;

...

    int iValueN = strtol(stringN, end, 10);
    stringN = end + 1;

}
Re[6]: посоветуйте аналог strtok
От: korzhik Россия  
Дата: 04.11.04 14:55
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Мне нужно использовать atoi для преобразования подстроки в целое число


#include <tokenizer.h> //
#include <iostream>    // for std::cout, std::endl 
#include <cstdio>      // for _snscanf

int main()
{
  tokenizer tok1("_");
  tok.set_str("112_23_4_556_2");

  while (tok.next())
  {
    tokenizer::token tk = tok.current_token();

   
    int i;
    _snscanf(tk.ptr, tk.len, "%d", &i);
    std::cout << i << std::endl;

  }
Re[3]: посоветуйте аналог strtok
От: korzhik Россия  
Дата: 04.11.04 15:01
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, Аноним, Вы писали:


А>>korzhik предложил использовать свой класс,но в конце использует

А>>для выделения подстроки еще один класс — string
K>в своём примере я использую класс std::string только для вывода в поток

я забыл что у потоков есть очень удобная функция write
с помошью неё можно избавиться от использования std::string
  tokenizer::token tk = tok.current_token();

  //std::cout << std::string(tk.ptr, tk.len) << std::endl;
  std::cout.write(tk.ptr, tk.len) << std::endl;
Re[7]: посоветуйте аналог strtok
От: Аноним  
Дата: 04.11.04 15:12
Оценка:
Здравствуйте, kmn, Вы писали:

kmn>Здравствуйте, Аноним, Вы писали:


А>>Мне нужно использовать atoi для преобразования подстроки в целое число


kmn>

kmn>for (int i = 0; i < 6; ++i)
kmn>{
kmn>    int iValue1 = strtol(string1, end, 10);
kmn>    string1 = end + 1;

kmn>    int iValue2 = strtol(string2, end, 10);
kmn>    string2 = end + 1;

kmn>...

kmn>    int iValueN = strtol(stringN, end, 10);
kmn>    stringN = end + 1;

kmn>}

kmn>

Спасибо большое.Отличное решение.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.