使用 '\0' 分割字符串

splitting a string using '\0'

假设我有一个 char* ./a.out[=11=]a[=11=]b[=11=][=11=]。 我想拆分它,结果是一个 char** of value

{
    "./a.out[=10=]",
    "a[=10=]",
    "b[=10=]",
    "[=10=]"
}

我使用的是纯 c + POSIX,但如果答案包含 c++STL 的一部分,我不介意,只要避免像 std::string[= 这样的内存效率低下的答案12=]

假设您知道有多少个字符串是相邻的,这是从复合字符串填充指针数组的简单方法:

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

int main() {
    const char *str = "./a.out[=10=]a[=10=]b[=10=]";  // 3 strings
    const char *args[3];

    const char *p = str;
    for (int i = 0; i < 3; i++) {
        args[i] = p;
        p += strlen(p) + 1;
    }

    for (int i = 0; i < 3; i++) {
        printf("args[%d] = \"%s\"\n", i, args[i]);
    }

    return 0;
}

输出:

args[0] = "./a.out"
args[1] = "a"
args[2] = "b"

这里有一个封装成函数的替代方案,分配一个数组,扫描字节数组判断字符串的个数,依靠2个连续的空字节来表示链表结束:

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

const char **split(const char *str) {
    const char **array;
    const char *p;
    int count = 0, i;

    // count the number of strings
    for (p = str; *p; p += strlen(p) + 1) {
        count++;
    }
    // allocate the array with an extra element for a NULL terminator
    array = calloc(sizeof(*array), count + 1);
    if (array != NULL) {
        // populate the array with pointers into the string
        for (i = 0, p = str; i < count; i++, p += strlen(p) + 1) {
            array[i] = p;
        }
        // set the NULL terminator
        array[i] = NULL;
    }
    return array;
}

int main() {
    const char *str = "./a.out[=12=]a[=12=]b[=12=]";  // 4 strings
    const char **args = split(str);

    for (int i = 0; args[i] != NULL; i++) {
        printf("args[%d] = \"%s\"\n", i, args[i]);
    }
    return 0;
}

输出:

args[0] = "./a.out"
args[1] = "a"
args[2] = "b"