如何在没有随机符号的情况下正确标记 C 中的字符串?

How to properly tokenize strings in C without random symbols?

我目前正在学习 C 并尝试编写一个函数来标记由空格分隔的 paragraph/string 和包含所有标记的数组 return。我被卡住了,因为我无法弄清楚为什么某些令牌会携带原始字符串中没有的符号。有人可以帮我弄清楚我的代码有什么问题吗?另外,我不想在代码中添加额外的库或使用像 strtok() 这样的函数。

char **tokenizeParagraph(char *paragraph) {
    char *ptr = paragraph;
    char words[MAX_WORDS][MAX_WORDLENGTH];
    int wordIndex = 0;
    int wordLen = 0;

    while (*ptr) {
        wordLen = 0;

        while (*ptr && *ptr != ' ') {
            wordLen++;
            ptr++;
        }

        if (wordLen > 0) {
            strncpy(words[wordIndex], paragraph, wordLen);
            printf("%s\n", words[wordIndex]);
            wordIndex++;
        }

        ptr++;
        paragraph = ptr;
    }
    return words;
}

这是一个演示结果:

tokenizeParagraph("I'm currently learning C and trying to write a function to tokenize a paragraph/string delimited by spaces and return an array with all the tokens.");

Error Demo

非常感谢!

已编辑:

@Sourav Kannantha B 和@Finxx 建议的动态内存方法非常有帮助。然而,由于我不想添加 库,我将数组声明移出函数并将其作为参数传入,因此数组不会在函数 [= 之后用堆栈内存擦除28=]s.

char words[MAX_WORDS][MAX_CHARS];
void tokenizeParagraph(char words[MAX_WORDS][MAX_CHARS], char *paragraph)

您正在堆栈上创建变量 words 并在堆栈上 return 指向它的指针。但是,当您从函数 return 时,堆栈不再局限于您的程序,这意味着您的指针指向的某些内容可能会发生变化,从而导致未定义的行为。为了防止这种情况,更改此代码:

char words[MAX_WORDS][MAX_WORDLENGTH];

有了这个:

char** words = calloc(MAX_WORDS * MAX_WORDLENGTH, sizeof(char));

这将在堆上而不是堆栈上分配内存,尽管您需要 stdlib.h 才能包括在内。

@Finxx 已经建议的已经足够好了。但如果 wordLen 变化很大,你仍然可以改进它。

char **tokenizeParagraph(char *paragraph) {
    char *ptr = paragraph;
    char** words = malloc(sizeof(char*) * MAX_WORDS);
    int wordIndex = 0;
    int wordLen;

    while (*ptr) {
        wordLen = 0;

        while (*ptr && *ptr == ' ') {
            ptr++;
        }

        paragraph = ptr;

        while (*ptr && *ptr != ' ') {
            wordLen++;
            ptr++;
        }

        if (wordLen > 0) {
            words[wordIndex] = malloc(sizeof(char) * wordLen+1);
            strncpy(words[wordIndex], paragraph, wordLen);
            words[wordIndex][wordLen] = '[=10=]';
            printf("%s\n", words[wordIndex]);
            wordIndex++;
        }
    }

    for(;wordIndex < MAX_WORDS; wordIndex++) {
        words[wordIndex] = NULL;
    }
    return words;
}

另外,请注意 strncpy 不添加终止 NUL 字符。这可能是输出中出现随机字符的原因。

此外,不要忘记 free 从调用函数分配的内存。:

int main() {
    ...
    char** words = tokenizeParagraph(para);
    ...
    for(int i = 0; i < MAX_WORDS; i++) {
        free(words[i]);
    }
    free(words);
    ...
    return 0;
}