Токенизация строк в C

Я пытаюсь сделать токенизацию строки с использованием SPACE в качестве разделителя, но она не работает. Есть ли у кого-нибудь предложение о том, почему он не работает?

Изменить: токенизация с использованием:

strtok(string, " "); 

Код выглядит следующим образом:

 pch = strtok (str," "); while (pch != NULL) { printf ("%s\n",pch); pch = strtok (NULL, " "); } 

Делай это так:

 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); } 

}

Вы можете прочитать подробный анализ в блоге, упомянутом в моем профиле 🙂

  • Вложенная функция функции strtok в C
  • Как читать ввод по-символам в Java?
  • Давайте будем гением компьютера.