0

我有当前的 C 代码:

#include <string.h> // strdup
#include <stdio.h> // printf
#include <stdlib.h> // free

int main(int argc, char *argv[])
{
  const char isostr[] = "\\ISO 2022 IR 13\\ISO 2022 IR 87";

  char *query = strdup( isostr );
  char *token;
  char *str1;
  char *saveptr1;
  const char delim[] = "\\";

  for (str1 = query; ; str1 = NULL)
    {
    token = strtok_r(str1, delim, &saveptr1);
    if (token == NULL)
      break;
    printf(" --> %s\n", token);
    }
  free( query );

  return 0;
}

但是它正在返回:

 --> ISO 2022 IR 13
 --> ISO 2022 IR 87

虽然我需要返回:

 --> [null/empty]
 --> ISO 2022 IR 13
 --> ISO 2022 IR 87

strtok_r 似乎在字符串“AA\BB\CC”和“AA\BB\CC\”或“\AA\BB\\CC”之间没有任何区别。

4

3 回答 3

2

如果分隔符只有 1 个字符,您可以使用 strchr 来搜索它而不是进行标记。strtok 将所有分隔符作为分隔符。

str1 = query;
while (1)
{
    char * sep = strchr(str1, '\\')
    if (sep != NULL) *sep = 0;
    printf(" --> %s\n", str1);
    if (sep == NULL) break;
    str1 = sep + 1;
}
于 2013-09-16T14:27:44.193 回答
1

如果分隔符始终是单个字符,您可以这样做:

char isostr[] = "\\ISO 2022 IR 13\\ISO 2022 IR 87";
char *p = isostr;
for (;;) {
    char *next = strchr(p, '\\');
    int len = next ? next-p : strlen(p);
    // This code makes a copy and frees it right away.
    // You may prefer your approach of `strdup`-ing, and setting '\0' in place.
    char *s = malloc(len+1);
    memcpy(s, p, len);
    s[len] = '\0';
    printf("--> '%s'\n", s);
    free(s);
    if (!next) break;
    p = next+1;
}

这会处理前导和尾随空标记,只要中间有空标记。这是关于 ideone 的演示

于 2013-09-16T14:37:09.543 回答
0

您可以自己轻松实现strtok具有该行为的类似函数:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


/* \short tokenize a string
 * \param delim a delimiter char
 * \param str the string to tokenize or NULL for the next result
 * \return the current token or NULL if end of tokens.
 */
char* tokenize(char delim, char *str) {
    static char *stat_str = NULL;
    static char *position = NULL;
    static char *end;
    char *c;

    /* Add some assertions here... */

    if (str != NULL) {
        stat_str = str;
        end = stat_str + strlen(str) + 1;
    }
    position = stat_str;

    /* If the current position is the end of the original string, return NULL */
    if (position == end) {
        return NULL;
    }

    /* Search for the next occurence of the delimiter and change it to a null char */
    for (c = position; *c != 0; c++) {
        if (*c == delim) {
            *c = 0;
            break;
        }
    }

    /* Set the position to the next char */
    stat_str = c + 1;

    /* return the current token */
    return position;
}

int main() {
    const char str[] = "\\ISO 2022 IR 13\\ISO 2022 IR 87";

    char *query = strdup(str);

    for (char *token = tokenize('\\', query); token != NULL;token = tokenize('\\', NULL)) {
        printf("Token [%s]\n", token);
    }

    free(query);
}
于 2013-09-16T15:02:12.803 回答