Токенизация строк в C
Я пытаюсь сделать токенизацию строки с использованием SPACE в качестве разделителя, но она не работает. Есть ли у кого-нибудь предложение о том, почему он не работает?
Изменить: токенизация с использованием:
strtok(string, " ");
Код выглядит следующим образом:
- Преобразование разделенной запятой строки в массив в PL / SQL
- Сканер против StringTokenizer против String.Split
- Шаблоны C ++ Угловые скобки Pitfall - Что такое C ++ 11?
- Разделение разделенной запятой строки в PL / SQL хранимой процедуре
- Как лучше всего разбить строки csv в oracle 9i
pch = strtok (str," "); while (pch != NULL) { printf ("%s\n",pch); pch = strtok (NULL, " "); }
- Есть ли функция для разделения строки в PL / SQL?
- Тонирование и сортировка с помощью XSLT 1.0
- Ищете четкое определение того, что такое «токенизатор», «парсер» и «лексеры» и как они связаны друг с другом и используются?
- Как получить токен из Lucene TokenStream?
- Как сделать токенизацию строки в C ++?
- Как использовать stringstream для разделения разделенных запятыми строк
- Ошибка Tokenizing: java.util.regex.PatternSyntaxException, оборванный метасимвол '*'
- Каков самый простой / лучший / самый правильный способ перебора символов строки в Java?
Делай это так:
char s[256]; strcpy(s, "one two three"); char* token = strtok(s, " "); while (token) { printf("token: %s\n", token); token = strtok(NULL, " "); }
Примечание: strtok
изменяет строку на ее токенизацию, поэтому она не может быть const char*
.
Вот пример использования strtok
, имейте в виду, что strtok
разрушает его входную строку (и поэтому никогда не может использоваться для строковой константы
char *p = strtok(str, " "); while(p != NULL) { printf("%s\n", p); p = strtok(NULL, " "); }
В основном следует отметить, что передача NULL
в качестве первого параметра strtok
говорит ему, чтобы он получил следующий токен из строки, которая была ранее маркерной.
strtok может быть очень опасным. Он не является streamобезопасным. Его предполагаемое использование должно вызываться снова и снова в цикле, передавая результат с предыдущего вызова. Функция strtok имеет внутреннюю переменную, которая хранит состояние вызова strtok. Это состояние не уникально для каждого streamа – оно глобально. Если какой-либо другой код использует strtok в другом streamе, у вас возникают проблемы. Не те проблемы, которые вы хотите отслеживать!
Я бы рекомендовал искать реализацию регулярного выражения или использовать sscanf, чтобы разделить строку.
Попробуй это:
char strprint[256]; char text[256]; strcpy(text, "My string to test"); while ( sscanf( text, "%s %s", strprint, text) > 0 ) { printf("token: %s\n", strprint); }
Примечание. Строка «текст» уничтожается по мере ее разделения. Это не может быть предпочтительным поведением =)
Вы можете упростить код, введя дополнительную переменную.
#include #include int main() { char str[100], *s = str, *t = NULL; strcpy(str, "a space delimited string"); while ((t = strtok(s, " ")) != NULL) { s = NULL; printf(":%s:\n", t); } return 0; }
Я сделал некоторые строковые функции, чтобы разделить значения, используя меньшее количество указателей, поскольку я мог, потому что этот код предназначен для работы на процессорах PIC18F. Эти процессоры не очень хорошо справляются с указателями, когда у вас мало свободной оперативной памяти:
#include #include char POSTREQ[255] = "pwd=123456&apply=Apply&d1=88&d2=100&pwr=1&mpx=Internal&stmo=Stereo&proc=Processor&cmp=Compressor&ip1=192&ip2=168&ip3=10&ip4=131&gw1=192&gw2=168&gw3=10&gw4=192&pt=80&lic=&A=A"; int findchar(char *string, int Start, char C) { while((string[Start] != 0)) { Start++; if(string[Start] == C) return Start; } return -1; } int findcharn(char *string, int Times, char C) { int i = 0, pos = 0, fnd = 0; while(i < Times) { fnd = findchar(string, pos, C); if(fnd < 0) return -1; if(fnd > 0) pos = fnd; i++; } return fnd; } void mid(char *in, char *out, int start, int end) { int i = 0; int size = end - start; for(i = 0; i < size; i++){ out[i] = in[start + i + 1]; } out[size] = 0; } void getvalue(char *out, int index) { mid(POSTREQ, out, findcharn(POSTREQ, index, '='), (findcharn(POSTREQ, index, '&') - 1)); } void main() { char n_pwd[7]; char n_d1[7]; getvalue(n_d1, 1); printf("Value: %s\n", n_d1); }
При чтении документации strtok я вижу, что вам нужно передать указатель NULL после первого вызова «инициализации». Может быть, вы этого не сделали. Конечно, конечно.
Вот еще одна реализация strtok()
, которая имеет возможность распознавать последовательные разделители (у strtok()
стандартной библиотеки этого нет)
Эта функция является частью лицензированной библиотеки BSD, называемой zString . Вы более чем рады внести свой вклад 🙂
https://github.com/fnoyanisi/zString
char *zstring_strtok(char *str, const char *delim) { static char *static_str=0; /* var to store last address */ int index=0, strlength=0; /* integers for indexes */ int found = 0; /* check if delim is found */ /* delimiter cannot be NULL * if no more char left, return NULL as well */ if (delim==0 || (str == 0 && static_str == 0)) return 0; if (str == 0) str = static_str; /* get length of string */ while(str[strlength]) strlength++; /* find the first occurance of delim */ for (index=0;index в char *zstring_strtok(char *str, const char *delim) { static char *static_str=0; /* var to store last address */ int index=0, strlength=0; /* integers for indexes */ int found = 0; /* check if delim is found */ /* delimiter cannot be NULL * if no more char left, return NULL as well */ if (delim==0 || (str == 0 && static_str == 0)) return 0; if (str == 0) str = static_str; /* get length of string */ while(str[strlength]) strlength++; /* find the first occurance of delim */ for (index=0;index
Как упоминалось в предыдущих сообщениях, поскольку strtok()
или тот, который я вложил выше, полагается на переменную static *char
чтобы сохранить местоположение последнего разделителя между последовательными вызовами, следует проявлять особую осторожность при работе с многопоточными приложениями.
int not_in_delimiter(char c, char *delim){ while(*delim != '\0'){ if(c == *delim) return 0; delim++; } return 1; } char *token_separater(char *source, char *delimiter, char **last){ char *begin, *next_token; char *sbegin; /*Get the start of the token */ if(source) begin = source; else begin = *last; sbegin = begin; /*Scan through the string till we find character in delimiter. */ while(*begin != '\0' && not_in_delimiter(*begin, delimiter)){ begin++; } /* Check if we have reached at of the string */ if(*begin == '\0') { /* We dont need to come further, hence return NULL*/ *last = NULL; return sbegin; } /* Scan the string till we find a character which is not in delimiter */ next_token = begin; while(next_token != '\0' && !not_in_delimiter(*next_token, delimiter)) { next_token++; } /* If we have not reached at the end of the string */ if(*next_token != '\0'){ *last = next_token--; *next_token = '\0'; return sbegin; } } void main(){ char string[10] = "abcb_dccc"; char delim[10] = "_"; char *token = NULL; char *last = "" ; token = token_separater(string, delim, &last); printf("%s\n", token); while(last){ token = token_separater(NULL, delim, &last); printf("%s\n", token); }
вint not_in_delimiter(char c, char *delim){ while(*delim != '\0'){ if(c == *delim) return 0; delim++; } return 1; } char *token_separater(char *source, char *delimiter, char **last){ char *begin, *next_token; char *sbegin; /*Get the start of the token */ if(source) begin = source; else begin = *last; sbegin = begin; /*Scan through the string till we find character in delimiter. */ while(*begin != '\0' && not_in_delimiter(*begin, delimiter)){ begin++; } /* Check if we have reached at of the string */ if(*begin == '\0') { /* We dont need to come further, hence return NULL*/ *last = NULL; return sbegin; } /* Scan the string till we find a character which is not in delimiter */ next_token = begin; while(next_token != '\0' && !not_in_delimiter(*next_token, delimiter)) { next_token++; } /* If we have not reached at the end of the string */ if(*next_token != '\0'){ *last = next_token--; *next_token = '\0'; return sbegin; } } void main(){ char string[10] = "abcb_dccc"; char delim[10] = "_"; char *token = NULL; char *last = "" ; token = token_separater(string, delim, &last); printf("%s\n", token); while(last){ token = token_separater(NULL, delim, &last); printf("%s\n", token); }
}
Вы можете прочитать подробный анализ в блоге, упомянутом в моем профиле 🙂