【问题标题】:Reimplementing split function in C在 C 中重新实现 split 函数
【发布时间】:2019-11-25 11:54:40
【问题描述】:

我一直在尝试编写一个函数,它将字符串作为一行并返回一个指向单词数组的指针。下面写的函数做了类似的事情 我如何重写以下代码1,但它应该比代码2更好,因为它能够更改分隔符。但是,code1 可以工作,但在内存分配期间,为 words 数组复制了相同的内存。从而造成单词重复。

代码 1

char *split(const char *string) {
    char *words[MAX_LENGTH / 2];
    char *word = (char *)calloc(MAX_WORD, sizeof(char));
    memset(word, ' ', sizeof(char));
    static int index = 0;
    int line_index = 0;
    int word_index = 0;

    while (string[line_index] != '\n') {
        const char c = string[line_index];
        if (c == ' ') {
            word[word_index+ 1] = '\0';
            memcpy(words + index, &word, sizeof(word));
            index += 1;
            if (word != NULL) {
                free(word);
                char *word = (char *)calloc(MAX_WORD, sizeof(char));
                memset(word, ' ', sizeof(char));
            }
            ++line_index;
            word_index = 0;
            continue;
        }
        if (c == '\t')
            continue;
        if (c == '.')
            continue;
        if (c == ',')
            continue;

        word[word_index] = c;
        ++word_index;
        ++line_index;
    }

    index = 0;
    if (word != NULL) {
        free(word);
    }
    return *words;
}

代码 2

char **split(char *string) {
    static char *words[MAX_LENGTH / 2];
    static int index = 0;
    // resetting words 
    for (int i = 0; i < sizeof(words) / sizeof(words[0]); i++) {
         words[i] = NULL;
    }
    const char *delimiter = " ";
    char *ptr = strtok(string, delimiter);
    while (ptr != NULL) {
        words[index] = ptr;
        ptr = strtok(NULL, delimiter);
        ++index;
    }
    index = 0;
    return words;
}

但是我注意到word+index 的内存被重新分配到相同的位置,从而导致单词重复。

【问题讨论】:

  • 您的问题是什么?在拆分过程中为函数或内存问题提供分隔符? BTW:标题不用大喊大叫。
  • 代码 2 没有 word 变量。您的问题是代码 1 还是代码 2?
  • 代码 2 有效,但我无法更改分隔符,因为它是 const char* 但我想使用代码 1,因为可以发现检查所有类型的非单词字符,但内存已再次重新分配,从而导致 char* word[] 中的单词重复,方法是在其索引中复制相同的内存位置

标签: c arrays string pointers


【解决方案1】:

strtok() 总是返回一个指向初始字符串的不同指针。这不会产生重复,除非您使用相同的输入字符串(可能使用新内容)调用它两次。

但是,您的函数返回一个指向 static 数组的指针,该数组在每次调用 split() 时都会被覆盖,从而使之前所有调用的结果无效。为了防止这种情况,

  • 在每次调用中分配新内存(必须由调用者释放):

    char *words = calloc(MAX_LENGTH / 2, 1);
    
  • 或者返回一个struct(它总是按值复制):

    struct wordlist { char *word[MAX_LENGTH / 2]; };
    
    wordlist split(char *string)
    {
        wordlist list = {};
        /* ... */
        list.word[index] = /* ... */;
        /* ... */
        return list;
    }
    

【讨论】:

    猜你喜欢
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 2010-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    相关资源
    最近更新 更多