通过在不使用strtok的情况下对字符串进行标记来学习C.

时间:2018-02-23 03:14:53

标签: c strtok

我正在通过查看斯坦福大学和其他大学的作业来学习C(我在任何地方都不是学生)。

其中一项任务是实现更简单的strtok,但是我无法正确完成。以下是我到目前为止的情况:

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

int tokenize(const char **input, const char *delimmter, char buf[], int buf_size)
{
    int i = strcspn(*input, delimmter);
    strncpy(buf, *input, i > buf_size ? buf_size : i);
    *input += i+1;

    if (i == strlen(*input))
        return 0;

    return 1;
}

int main(int argc, char *argv[])
{
    const char *input = "super-duper-awesome-magnificent";
    char buf[11];
    while (tokenize(&input, "-", buf, sizeof(buf)))
    {
        printf("Next Token : %s\n", buf);
    }

    return 0;
}

Next Token : super
Next Token : duper
Next Token : awesome
Next Token : magnificent
Next Token : Next Token

如果我正确理解指针和内存(堆栈/堆),那么我实现的错误就是:

  

1)它不正确:它打印所有标记后跟短语   &#34;下一个令牌&#34;因为那是程序中的下一块内存。   它只会停止,因为堆栈上没有任何东西

     

2)我没有正确使用buf_size。任何长于11的令牌   字符会引起问题。

但我现在的目标只是解决第一个问题,即如何终止while循环。

1 个答案:

答案 0 :(得分:3)

执行此操作时:

int i = strcspn(*input, delimmter);

i将具有段的长度,该段完全由不在的字节组成 delimmter。如果delimmter中的charatcer在*input中,则i会更短 比strlen(*input)

strncpy(buf, *input, i > buf_size ? buf_size : i);

此行最多复制i > buf_size ? buf_size : i中的buf个字符, 我们说i大于buf_size,这意味着您将复制buf_size buf中的元素,但它不会被\0&#39; - 终止,因为strncpy不会 写'\0' - 如果找不到则终止。所以必须设置 '\0'终止字节。

strncpy(buf, *input, i > buf_size ? buf_size : i);
buf[(i >= buf_size ? buf_size - 1: i)] = 0;

如果i小于buf_size,则位置i就是'\0' i - 应该终止字节。如果buf_size大于或等于buf_size-1, 然后'\0'是缓冲区中的最后一个位置 *input += i+1; - 应该终止字节。

*input

对所有情况都不正确。如果在i中找不到分隔符,则strlen(*input)input相同。在这种情况下,您需要'\0'点 到i - 终止字节而不是通过它,因为你将访问它 内存超出下一次迭代的范围。如果*input += i + (i != strlen(*input)); 小于长度, 然后增量很好。所以,正确的版本将是

if (i == strlen(*input))
    return 0;

*input

应该删除。在这种情况下,整个*input字符串必须是 返回并且函数应该返回1.这就是为什么你可以删除它。但 您需要测试的是strcspn是否为空字符串。在那种情况下,所有 令牌已被退回,你应该返回0.这个检查prioir到 int tokenize(const char **input, const char *delimmter, char buf[], int buf_size) { if(**input == 0) return 0; int i = strcspn(*input, delimmter); strncpy(buf, *input, i > buf_size ? buf_size : i); buf[(i > buf_size ? buf_size - 1: i)] = 0; *input += i + (i != strlen(*input)); return 1; } 致电。

所以

main

这会给你想要的结果。如果您更改buff功能 char buf[3]Next Token : su Next Token : du Next Token : aw Next Token : ma 的声明,这将是输出:

threshold

这是正确的。