在 C 中不使用 strtok 来提取事件的更简单方法

Simpler way to extract occurrences without using strtok in C

我正在尝试从给定字符串中提取第一个逗号前后的字符串。但是,我觉得一定有比下面的方法更好的方法,也许我什至不需要 strdup 调用。谢谢

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

int extract_names(const char *str)
{
    char *name, *last, *p1, *p2, *p3;

    name = strdup(str);
    last = strdup(str);

    p1 = strchr(name, ',');
    if (p1)
    {
        *p1 = '[=10=]';
        printf("%s\n", name);
    }

    p2 = strchr(last, ',');
    p2++;
    if (p2)
    {
        p3 = strpbrk(p2 + 1, " [=10=]");
        if (p3)
            *p3 = '[=10=]';
        printf("%s\n", p2);
    }
    free(name);
    free(last);

    return 0;
}

int main()
{
    // strings should at least contain last,name.
    // but can contain several words
    const char *str1 = "jones,bob age,12";
    extract_names(str1);
    const char *str2 = "smith,peter";
    extract_names(str2);
    return 0;
}

输出

jones
bob
smith
peter

既然你显然在努力学习,我只会给你一些指导,而不是 "better working solution"。

strdup 在这里是一个有用的想法。正如您所做的那样,它允许您覆盖字符串(const char *str 是 "readonly")。

这个组合:

p2 = strchr(last, ',');
p2++;
if (p2) {

错了。调用后 p2 等于 return 值。如果你在 if 之前推进它,你就没有测试任何东西(如果 NULL 是 returned,那么当你测试它时它是 1)。

不需要两次 strdup,也不需要搜索两次。 p1 已经指向 name 中的正确位置,您可以将其用于其余的逻辑。

使用strchr求出姓氏和名字的界限。然后,您可以使用 printf 中的精度说明符来仅打印您感兴趣的字符串部分。

例如:

int extract_names(const char *str)
{
    const char *comma = strchr(str, ',');
    const char *name_end = strchr(str, ' ');

    /* name ends at space or end of string */
    if (!name_end) {
        name_end = str + strlen(str);
    }

    /* print last name */
    printf("%.*s\n", (comma - str), str);

    /* print first name */
    printf("%.*s\n", name_end - comma, comma + 1);

    return 0;
}