C - 在空格处拆分字符串

3
我需要将一个字符串按空格分割(例如字符串:Hello this is an example string.),并将其拆分为单词数组。我不确定我漏掉了什么,也想知道测试此函数的最佳方法。唯一允许使用的库函数是malloc
任何帮助都将不胜感激!
#include <stdlib.h>

char **ft_split(char *str) {
    int wordlength;
    int wordcount;
    char **wordbank;
    int i;
    int current;

    current = 0;
    wordlength = 0;
    //while sentence
    while (str[wordlength] != '\0') {
        //go till letters
        while (str[current] == ' ')
            current++;
        //go till spaces
        wordlength = 0;
        while (str[wordlength] != ' ' && str[wordlength] != '\0')
            wordlength++;
         //make memory for word
        wordbank[wordcount] = malloc(sizeof(char) * (wordlength - current + 1));

        i = 0;
        //fill wordbank current
        while (i < wordlength - current) {
            wordbank[wordcount][i] = str[current];
            i++;
            current++;
        }

        //end word with '\0'
        wordbank[wordcount][i] = '\0';

        wordcount++;
    }
    return wordbank;
}

为什么不使用strchr()函数? - Iharob Al Asimi
还是使用strtok_s/strtok_r - Useless
2
你现在正在参加“piscine”吗? - Gam
除非您只打算将其用于英语,否则您可能需要查看 ICU(Unicode 国际组件)。其他语言可以具有多字节字符(如果使用标准 UTF-8 编码),单词可能不会由空格分隔,这使得情况相当复杂。使用 ICU 库,您可以轻松获取单词的起始和结束指针,而不必担心令人讨厌的细节。 - Fabel
2个回答

1

你需要使用malloc()来分配单词库的空间。你可以统计单词数量,然后

wordbank = malloc((count + 1) * sizeof(*wordbank));
if (wordbank == NULL)
    return NULL;

注意:根据定义,sizeof(char)的大小为1。而且sizeof *pointer总是你想要的。


是的,这个 sizeof(*pointer) 技巧看起来很酷,我也见过有人像你一样向别人推荐它,但是如何解引用未初始化的指针呢?据我所知,这是未定义的行为... - ForceBru
@ForceBru sizeof 在不需要时不会评估参数。请参见演示 - BLUEPIXY
@BLUEPIXY,确实,这真是相当聪明。谢谢! - ForceBru
2
应该为wordbank分配比单词数量多一个位置的空间,并在最后一个位置存储一个空指针,以便调用者可以从数组内容中确定单词数量。 - chqrlie

1

您的代码存在多个问题:

  • 您没有为 wordbank 分配一个数组,对未初始化的指针进行引用具有未定义的行为。
  • 您扫描字符串的方法不正确:在循环内重置 wordlength,因此您会一直从字符串开头重新扫描。
  • 您应该在数组中分配一个额外的条目来放置一个尾随的空指针,以向调用者指示数组的结尾。

这是一个修改后的版本:

#include <stdlib.h>

char **ft_split(const char *str) {
    size_t i, j, k, wordcount;
    char **wordbank;

    // count the number of words:
    wordcount = 0; 
    for (i = 0; str[i]; i++) {
        if (str[i] != ' ' && (i == 0 || str[i - 1] == ' ')) {
            wordcount++;
        }
    }

    // allocate the word array
    wordbank = malloc((wordcount + 1) * sizeof(*wordbank));
    if (wordbank) {
        for (i = k = 0;;) {
            // skip spaces
            while (str[i] == ' ')
                i++;
            // check for end of string
            if (str[i] == '\0')
                break;
            // scan for end of word
            for (j = i++; str[i] != '\0' && str[i] != ' '; i++)
                continue;
            // allocate space for word copy
            wordbank[k] = p = malloc(i - j + 1);
            if (p == NULL) {
                // allocation failed: free and return NULL
                while (k-- > 0) {
                    free(wordbank[k]);
                }
                free(wordbank);
                return NULL;
            }
            // copy string contents
            memcpy(p, str + j, i - j);
            p[i - j] = '\0';
        }
        // set a null pointer at the end of the array
        wordbank[k] = NULL;
    }
    return wordbank;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接