我正在通过查看斯坦福大学和其他大学的作业来学习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循环。
答案 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
这是正确的。