Перейти к содержанию
    

C18 Функция strtok

Добрый день. У меня возникла необходимость парсить большое количество строк и вычленять числа из строки, разделенные между собой точкой (например, "15.23.10"). Стал копать в эту сторону и набрел на функцию strtok, которая призвана разделять строку на подстроки, разделенные маркером, передаваемым в функцию в виде параметра. Нашел готовый пример

#include <string.h>

int main()
{
    char str[] = "192.168.0.1";
    unsigned char bytes[4];
    int i = 0;

    char* buff = malloc(10);
    buff = strtok(str,".");
    while (buff != NULL)
    {
       //if you want to print its value
       printf("%s\n",buff);
       //and also if you want to save each byte
       bytes[i] = (unsigned char)atoi(buff);
       buff = strtok(NULL,".");
       i++;
    }
    free(buff);
    return 0;
}

Чуть-чуть переделал его под себя

char sc[] = "150.156.16";
byte bytes[3] = "  ";
int i = 0;
char* buff;
buff = strtok(sc,(const char*)'.');
while (buff != NULL)
{
    bytes[i] = (byte)atoi(buff);
    buff = strtok(NULL,(const char*)'.');
    i++;
}

Но считывается только первое число (150), а дальше происходит выход из цикла, и я не пойму, почему. Подскажите, пожалуйста, какие условия из описания я не выполнил (P.S. ниже я привел описание функции, взятое из самого компилятора)?

 

/** @name strtok

* ``A sequence of calls to the {\bf strtok} function breaks the

* string pointed to by {\bf s1} into a sequence of tokens, each of

* which is delimited by a character from the string pointed to by

* {\bf s2}. The first call in the sequence has {\bf s1} as its

* first argument, and is followed by calls with a null pointer

* as their first argument. The separator string pointed to by {\bf s2}

* may be different from call to call.

*

* ``The first call in the sequence searches the string pointed to

* by {\bf s1} for the first character that is {\it not} contained in

* the current separator string {\bf s2}. If no such character is found,

* then there are no tokens in the string pointed to by {\bf s1} and the

* {\bf strtok} function returns a null pointer. If such a character is

* found, it is the start of the first token.

*

* ``The {\bf strtok} function then searches from there for a character

* that {\it is} contained in the current separator string. If no such

* character is found, the current token extends to the end of the

* string pointed to by {\bf s1}, and subsequent searches for a token

* will return a null pointer. If such a character is found, it is

* overwritten by a null character, which terminates the current token.

* The {\bf strtok} function saves a pointer to the following character,

* from which the next search for a token will start.

*

* ``Each subsequent call, with a null pointer as the first argument,

* starts searching from the saved pointer and behaves as described

* above.

*

* ``The implementation shall behave as if no library function calls the

* {\bf strtok} function.

*

* ``This function is implemented in C, is not re-entrant and calls the

* functions: strspn, strpbrk, memchr.''

*

* @param s1 pointer to a string to begin searching, or null to continue

* searching a prior string

* @param s2 pointer to a string containing the set of separator characters

* @return ``The {\bf strtok} function returns a pointer to the first

* character of a token, or a null pointer if there is no token.''

*/

char *strtok (auto char *s1, auto const char *s2);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#include <stdlib.h>
#include <stdio.h>

const char frr[]="141.14.14.56.00.82.43";
int main(void)
{
    char *head = frr;
    char *tail;
    int what;
    for(;;)
    {
        what = strtol(head, &tail, 10);
        printf("parsed: %d \n",what,tail);
        if((tail == NULL)||(*tail == 0)) break;
        head = ++tail;
    }
}

а вообще нафига такие сложности, если можно умножением на 10 обойтись ...

 

#include <stdlib.h>
#include <stdio.h>

const char frr[]="141.14.14.56.00.82.43";
int main(void)
{
    char *head = frr;
    int res=0;
    char c,m=0;
    do
    {
        c = *head++;
        switch(c)
        {
            case ' ':
            case '\t':
                break;
            case '.':
            case 0:
                if(m) res = -res;
                printf("parsed: %d\n",res);
                res = 0;
                m=0; 
                break;
            case '-':
                m=1;
                break;
            default:    
                if((c <= '9') && (c >='0'))
                {
                    res = res * 10 + c - '0';
                }
                break;
        }
        
    } while(c);
}

Изменено пользователем _Pasha

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Способ 1: в C18 нет такой функции strtol

Способ 2: это совсем не то, что мне нужно. У меня стоит задача разбить 2 строки дд.мм.гг и чч.мм.сс (дату и время соответственно) на 6 переменных, хранящих отдельно каждое значение. Т.е. я предполагал при помощи функции strtok разбить на подстроки, а дальше при помощи функции atoi переконвертировать эти строки в число. Не хотелось бы изобретать некрасивый велосипед, когда есть готовая функция. Вот только разобраться с ней не удается.

Изменено пользователем Auratos

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Надо передавать строку с разделителями -

","

а не тот кошмар что сделан (вместо запятой в мамяти по адресу 0x002d что-то конечно лежит):

(const char*)'.'

В примере ведь было правильно.

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Надо передавать строку с разделителями -

","

а не тот кошмар что сделан (вместо запятой в мамяти по адресу 0x002c что-то конечно лежит):

(const char*)'.'

В примере ведь было правильно.

Все верно. Я допустил эту ошибку вчера под конец рабочего дня. Сегодня утром я ее исправил, но результат не изменился. Проблема именно в том, что в цикле while совершается ровно одна итерация, после которой происходит выход из цикла. А, судя по логике, должны пройти 3 итерации. Вот моя функция

void ParseDateTime(void)
{
    char date[] = "30.10.15";
    byte bytes[3] = "  ";
    int i = 0;

    char* buff;
    buff = strtok(date,(const char*)".");
    while (buff != NULL)
    {
       bytes[i] = (byte)atoi(buff);
       buff = strtok(NULL,(const char*)".");
       i++;
    }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сегодня утром я ее исправил, но результат не изменился

 

наверное из-за того что массив bytes не правильно описали, и попортили стек

 

вот это работает

 

или же CRT область не определена ( ведь где то должна strtok хранить значение адреса, и по этому и нереентерабельная )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

наверное из-за того что массив bytes не правильно описали, и попортили стек

 

вот это работает

 

или же CRT область не определена ( ведь где то должна strtok хранить значение адреса, и по этому и нереентерабельная )

Byte у меня unsigned char

typedef unsigned char byte;

Вот результат на выходе цикла

post-83032-1446201916_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

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

×
×
  • Создать...