Auratos 0 29 октября, 2015 Опубликовано 29 октября, 2015 · Жалоба Добрый день. У меня возникла необходимость парсить большое количество строк и вычленять числа из строки, разделенные между собой точкой (например, "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); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 29 октября, 2015 Опубликовано 29 октября, 2015 (изменено) · Жалоба #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); } Изменено 29 октября, 2015 пользователем _Pasha Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Auratos 0 30 октября, 2015 Опубликовано 30 октября, 2015 (изменено) · Жалоба Способ 1: в C18 нет такой функции strtol Способ 2: это совсем не то, что мне нужно. У меня стоит задача разбить 2 строки дд.мм.гг и чч.мм.сс (дату и время соответственно) на 6 переменных, хранящих отдельно каждое значение. Т.е. я предполагал при помощи функции strtok разбить на подстроки, а дальше при помощи функции atoi переконвертировать эти строки в число. Не хотелось бы изобретать некрасивый велосипед, когда есть готовая функция. Вот только разобраться с ней не удается. Изменено 30 октября, 2015 пользователем Auratos Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 30 октября, 2015 Опубликовано 30 октября, 2015 (изменено) · Жалоба Надо передавать строку с разделителями - "," а не тот кошмар что сделан (вместо запятой в мамяти по адресу 0x002d что-то конечно лежит): (const char*)'.' В примере ведь было правильно. Изменено 30 октября, 2015 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Auratos 0 30 октября, 2015 Опубликовано 30 октября, 2015 · Жалоба Надо передавать строку с разделителями - "," а не тот кошмар что сделан (вместо запятой в мамяти по адресу 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++; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 3 30 октября, 2015 Опубликовано 30 октября, 2015 · Жалоба Сегодня утром я ее исправил, но результат не изменился наверное из-за того что массив bytes не правильно описали, и попортили стек вот это работает или же CRT область не определена ( ведь где то должна strtok хранить значение адреса, и по этому и нереентерабельная ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Auratos 0 30 октября, 2015 Опубликовано 30 октября, 2015 · Жалоба наверное из-за того что массив bytes не правильно описали, и попортили стек вот это работает или же CRT область не определена ( ведь где то должна strtok хранить значение адреса, и по этому и нереентерабельная ) Byte у меня unsigned char typedef unsigned char byte; Вот результат на выходе цикла Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться