スペースを区切り文字として使用して文字列をトークン化しようとしましたが、うまくいきません。なぜそれが機能しないのかについての提案はありますか?
編集:次を使用してトークン化:
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
、最初のパラメーターとしてa を渡すと、strtok
以前にトークン化した文字列から次のトークンを取得するように指示することです。
strtok は非常に危険です。スレッドセーフではありません。その使用目的は、ループ内で何度も呼び出され、前の呼び出しからの出力を渡すことです。strtok 関数には、strtok 呼び出しの状態を格納する内部変数があります。この状態は各スレッドに固有のものではなく、グローバルです。他のコードが別のスレッドで strtok を使用すると、問題が発生します。追跡したい種類の問題でもありません。
正規表現の実装を探すか、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 <string.h>
#include <stdio.h>
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 プロセッサで実行することを目的としているため、可能な限り少ないポインタを使用して、値を分割するためにいくつかの文字列関数を作成しました。これらのプロセッサは、使用可能な空き RAM がほとんどない場合、ポインターをうまく処理できません。
#include <stdio.h>
#include <string.h>
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()
実装です (標準ライブラリstrtok()
にはこれがありません)。
この関数は、zStringと呼ばれる BSD ライセンスの文字列ライブラリの一部です。あなたが貢献することは大歓迎です:)
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<strlength;index++)
if (str[index]==delim[0]) {
found=1;
break;
}
/* if delim is not contained in str, return str */
if (!found) {
static_str = 0;
return str;
}
/* check for consecutive delimiters
*if first char is delim, return delim
*/
if (str[0]==delim[0]) {
static_str = (str + 1);
return (char *)delim;
}
/* terminate the string
* this assignmetn requires char[], so str has to
* be char[] rather than *char
*/
str[index] = '\0';
/* save the rest of the string */
if ((str + index + 1)!=0)
static_str = (str + index + 1);
else
static_str = 0;
return str;
}
以前の投稿で述べたようにstrtok()
、または上記で実装したものは、連続する呼び出し間の最後の区切り文字の位置を保持するために変数に依存しているstatic *char
ため、マルチスレッド アプリケーションを扱うときは特に注意する必要があります。
strtok のドキュメントを読むと、最初の「初期化」呼び出しの後に NULL ポインターを渡す必要があることがわかります。多分あなたはそれをしなかった。もちろん、ただの推測です。