c - C 中分割字符串最快的算法?

标签 c string algorithm command-line-interface tokenize

我正在编写一个 CLI 输入解析器,我想知道将字符串拆分为标记的最快算法是什么。

规则:

  • 空格表示 token 结束。
  • 任何字符都可以用反斜杠转义,这意味着我按原样使用它,没有任何特殊含义。 (目前仅用于转义空格)

这是我当前使用的代码:

#define POINTER_ARRAY_STEP 10
#define STRING_STEP 255

char **parse_line(char *line)
{
    char **array;
    size_t array_len;
    size_t array_index;
    size_t token_len;
    size_t token_index;

    array_len = POINTER_ARRAY_STEP;
    array = malloc((array_len + 1) * sizeof(char*)); /* +1 to leave space for NULL */
    array_index = 0;

    token_len = STRING_STEP;
    array[array_index] = malloc(token_len + 1);
    token_index = 0;

    for (; *line; ++line) {
        if (array_index == array_len) {
            array_len += POINTER_ARRAY_STEP;
            array = realloc(array, (array_len + 1) * sizeof(char*));
        }
        if (token_index == token_len) {
            token_len += STRING_STEP;
            array[array_index] = realloc(array[array_index], token_len + 1);
        }
        if (*line == '\\') {
            array[array_index][token_index++] = *++line;
            continue;
        }
        if (*line == ' ') {
            array[array_index][token_index] = 0;
            array[++array_index] = malloc(token_len + 1);
            token_index = 0;
            continue;
        }
        array[array_index][token_index++] = *line;
    }
    /* Null terminate the last array element */
    array[array_index][token_index] = 0;

    /* Null terminate the array */
    array[array_index + 1] = NULL;
    return array;
}

最佳答案

你的方法既不安全又低效:你没有检查内存分配失败,并且调用realloc()次数太多。

这是另一种方法:

  • 进行第一遍计算标记和转义的数量,
  • 为标记分配指针数组和缓冲区
  • 进行第二遍,将字符复制到缓冲区中,分割标记并使指针数组指向标记。
  • 返回数组指针。

稍后可以通过在指针数组及其第一个元素上调用 free() 来释放内存。

这是代码:

#include <stdlib.h>

char **parse_line(const char *line) {
    size_t len, i, j, k, items = 1, escapes = 0;
    char **array;
    char *buf;

    for (len = 0; line[len]; len++) {
        if (line[len] == '\\') {
            escapes++;
            if (line[++len] == '\0')
                break;
        } else
        if (line[len] == ' ') {
            items++;
        }
    }
    if (len == escapes) {
        /* special case empty line */
        array = malloc(sizeof(*array));
        if (array != NULL) {
            array[0] = NULL;
        }
        return array;
    }
    array = malloc((items + 1) * sizeof(*array));
    buf = malloc(len + 1 - escapes);

    if (array == NULL || buf == NULL) {
        free(array);
        free(buf);
        return NULL;
    }
    items[0] = buf;
    k = 1;
    for (i = j = 0; i < len; i++) {
        if (line[i] == '\\') {
            if (++i == len)
                break;
            buf[j++] = line[i];
        } else
        if (line[i] == ' ') {
            buf[j++] = '\0';
            items[k++] = buf + j;
        } else {
            buf[j++] = line[i];
        }
    }
    buf[j] = '\0';
    items[k] = NULL;
    return items;
}

关于c - C 中分割字符串最快的算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42401462/

相关文章:

c - C 中的段错误(使用指针)

string - Clojure 中将字符串转换为整数向量的功能解决方案

c++ - 给定字符串 vector (按长度排序),用于查找等长字符串范围的惯用 C++

c - SQLite C API 中的静态与非静态准备语句

c - tcp 客户端 服务器 p2p

c++ - 在 C++ 中仅使用 std::string 成员在没有循环的情况下反转字符串

javascript - 我将输出作为二叉树的对象,如何将此对象值放入数组中以继续处理进一步的问题

c++ - 时间戳组织的容器

algorithm - 是否有一种算法可以组合来自多个麦克风的音频以提高音频质量?

c - printf 一个文字数字 (int),同时期望一个更短的数字