C strtok,如果我想保留分隔符怎么办?
C strtok, what if I want to keep the delimiter?
我正在尝试拆分以下类型的行:
GM 1 2 3 ! this is a comment
把评论区分开来。有几种可能的注释定界符,!、' 和 #。 strtok
是显而易见的解决方案:
card->card_str = strtok(line_buf, "!'#");
生产 GM 1 2 3
和 this is a comment
。但是,对于这个角色,我需要将分隔符保留在第二个字符串中,因此在本例中为 ! this is a comment
。有没有简单的方法来做到这一点?
strtok
很少是解析作业的正确工具,因为它有很多怪癖和副作用。
为了您的目标,您可以使用 strcspn()
:
void parse_input_line(const char *line) {
size_t len = strcspn(line, "!'#");
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, line, len);
p[len] = '[=10=]';
card->card_str = p;
card->card_comment = p[len] ? strdup(p + len) : NULL;
}
}
或者,您可以使用 strpbrk
:
void parse_input_line(const char *line) {
const char *sep = strpbrk(line, "!'#");
if (sep == NULL) {
// no comment
card->card_str = strdup(line);
card->card_comment = NULL;
} else {
size_t len = sep - line;
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, line, len);
p[len] = '[=11=]';
card->card_str = p;
card->card_comment = strdup(sep);
}
}
}
您可以使用 strndup
使代码更具可读性:
void parse_input_line(const char *line) {
size_t len = strcspn(line, "!'#");
if (p[len] == '[=12=]') {
/* no comment */
card->card_str = strdup(line);
card->card_comment = NULL;
} else {
card->card_str = strndup(line, len);
card->card_comment = strdup(p + len);
}
}
strndup
可能不是在所有系统上都可用,这里有一个简单的实现:
size_t strnlen(const char *s, size_t n) {
size_t len;
for (len = 0; len < n; len++) {
if (s[len] == '[=13=]')
break;
}
return len;
}
char *strndup(const char *s, size_t n) {
size_t len = strnlen(s, n);
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, s, len);
p[len] = '[=13=]';
}
return p;
}
我正在尝试拆分以下类型的行:
GM 1 2 3 ! this is a comment
把评论区分开来。有几种可能的注释定界符,!、' 和 #。 strtok
是显而易见的解决方案:
card->card_str = strtok(line_buf, "!'#");
生产 GM 1 2 3
和 this is a comment
。但是,对于这个角色,我需要将分隔符保留在第二个字符串中,因此在本例中为 ! this is a comment
。有没有简单的方法来做到这一点?
strtok
很少是解析作业的正确工具,因为它有很多怪癖和副作用。
为了您的目标,您可以使用 strcspn()
:
void parse_input_line(const char *line) {
size_t len = strcspn(line, "!'#");
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, line, len);
p[len] = '[=10=]';
card->card_str = p;
card->card_comment = p[len] ? strdup(p + len) : NULL;
}
}
或者,您可以使用 strpbrk
:
void parse_input_line(const char *line) {
const char *sep = strpbrk(line, "!'#");
if (sep == NULL) {
// no comment
card->card_str = strdup(line);
card->card_comment = NULL;
} else {
size_t len = sep - line;
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, line, len);
p[len] = '[=11=]';
card->card_str = p;
card->card_comment = strdup(sep);
}
}
}
您可以使用 strndup
使代码更具可读性:
void parse_input_line(const char *line) {
size_t len = strcspn(line, "!'#");
if (p[len] == '[=12=]') {
/* no comment */
card->card_str = strdup(line);
card->card_comment = NULL;
} else {
card->card_str = strndup(line, len);
card->card_comment = strdup(p + len);
}
}
strndup
可能不是在所有系统上都可用,这里有一个简单的实现:
size_t strnlen(const char *s, size_t n) {
size_t len;
for (len = 0; len < n; len++) {
if (s[len] == '[=13=]')
break;
}
return len;
}
char *strndup(const char *s, size_t n) {
size_t len = strnlen(s, n);
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, s, len);
p[len] = '[=13=]';
}
return p;
}