如何将strtok与每个单个非alpha字符一起用作分隔符? (C)

所以我有一个字符串:

**BOB**123(*&**blah**02938*(*&91820**FOO** 

我希望能够使用strtok来消除每个单词。 分隔符是每个不是字母的单个字符。

我被isalpha我们isalpha ,但不知道我会怎么做。 有没有办法在不命名每个非alpha字符的情况下执行此操作?

不幸的是,不允许使用正则表达式库。

 #include  #include  char *strtok_t(char *str, int (*test)(int ch)){ static char *store = NULL; char *token; if(str != NULL){ store = str; } if(store == NULL) return NULL; while(*store && !test(*store)){//skip delimiter ++store; } if(*store == '\0') return NULL; token=store; while(*store && test(*store)){ ++store; } if(*store == '\0'){ store = NULL; } else { *store++ = '\0'; } return token; } int main(void){ char str[128] = "BOB123(&blah02938(*&91820FOO"; char *token; for(token = strtok_t(str, isalpha); token ; token = strtok_t(NULL, isalpha)){ printf("%s\n", token); } return 0; } 

一种可以使这更容易的方法是首先用空格覆盖所有非字母字符:

 for (char *p = str; *p; p++) if (!isalpha(*p)) *p = ' '; 

现在你可以使用strtok(str, " ")

可能会使用strtok ,但它可能更容易推出自己的。 下面是一个使用自定义结构来保存标记符的状态和结果的示例。 状态只是指向字符串的指针,必须使用字符串对其进行初始化。

结果表示该字符串的子字符串为起始指针和长度的组合。 这个结果不是零终止,所以你必须小心。 这种方法的好处是解决方案不会分配额外的内存,也不会覆盖原始字符串,因此与strtok不同,它适用于只读字符串。

使用返回1或0的函数调用tokeniser本身,具体取决于是否找到了新的令牌,这使得循环语法变得简单。

开始:

 #include  #include  #include  /* for isalpha(c) */ struct alpha_t { const char *p; /* Pointer int string; must be initialised */ const char *str; /* start of current token */ int len; /* length of token */ }; /* * Get next alpha token from string; alpha->p must be initialised * to the (possible read-only) string to work on. */ int next_alpha(struct alpha_t *alpha) { if (alpha->p == NULL) return 0; /* Skip non-alpha and check for end of string */ while (*alpha->p && !isalpha(*alpha->p)) alpha->p++; if (*alpha->p == 0) return 0; /* Read token of alpha charactzers */ alpha->str = alpha->p; while (isalpha(*alpha->p)) alpha->p++; alpha->len = alpha->p - alpha->str; return 1; } /* * Example client code */ int main() { char *str = "BOB123(&blah02938(*&91820FOO"; struct alpha_t token = {str}; while (next_alpha(&token)) { printf("'%.*s'\n", token.len, token.str); } return 0; } 

正如您已经建议的那样,此解决方案使用isalpha 。 它很容易扩展到其他函数 – 您甚至可以将非分隔符函数上的分隔符作为参数传递,或者使其成为结构的一部分,以用于可自定义的tokeniser。

首先,您必须创建一个非alpha字符列表:

 char *myString = "fhewuidnjkl123782107381290z890zh"; char nonAlphachars[0xFF]; memset(nonAlphachars, 0, 0xFF); int i = 0; int c = 1; for(; c <= 0xFF; c++) { if(!isalpha(c)) { nonAlphachars[i++] = c; } } 

这将使您能够将strtokmyString一起使用:

 char *tok = strtok(myString, nonAlphachars); 

现在你只需要迭代你的标记就可以了。 请注意:那只是一个未经测试的(!)选秀,但我想你会明白这个想法。 如果你希望你的程序有效:在一个单独的字符串中硬编码所有非alpha-chars,完全丢弃循环并使用它...丑陋但非常快(不像所有其他答案)

顺便说一句:这些都是数字表示中的所有非alpha字符,只是发现了差距......我会把那个留给你;-):

 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 91 92 93 94 95 96 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 

这是一个非常简单的指针方法。

 #include  #include  int main(void) { char *str = "BOB123(&blah02938(*&91820FOO\0"; while (*str != '\0') { if (isalpha(*str)) printf("%c\n", *str); *str++; } }