我从很多程序员那里听到,strtok的使用可能会在不久的将来被弃用。有人说它还在。为什么这是一个糟糕的选择? strtok()在标记给定字符串时效果很好。它是否必须对时间和空间的复杂性做任何事情? 我在互联网上找到的最佳链接是this。但这似乎并没有解决我的好奇心。如果可能,建议任何替代方案。
答案 0 :(得分:18)
为什么这是一个糟糕的选择?
通过编程解决问题的基本技术是构造抽象,可以可靠地解决子问题,然后撰写解决这些子问题成为解决更大问题的方法。
strtok的行为以各种方式直接反对这些目标;这是一个糟糕的抽象,不可靠,因为它组成很差。标记化的基本问题是:在字符串中给出一个位置,给出从该位置开始的标记结尾的位置。如果strtok只做那个,那就太好了。它将具有明确的抽象,它不会依赖隐藏的全局状态,也不会修改其输入。
要了解strtok的局限性,请设想尝试将我们希望用空格分隔标记的语言标记化,除非该标记包含在"
"
中,在这种情况下我们希望应用不同的标记化规则到引用区域的内容,然后用空格分隔规则拾取。 strtok与自身组合很差,因此仅对最琐碎的标记化任务有用。
它是否必须对时间和空间的复杂性做任何事情?
没有
如果可能,建议任何替代方案。
Lexers并不难写;只写一个!
如果您编写不可变词法,则会获得积分。不可变词法分析器是一个小结构,它包含对词法的引用,词法分析器的当前位置以及词法分析器所需的任何状态。要提取令牌,您调用“下一个令牌”方法,传入词法分析器,然后返回令牌和新词法分析器。然后可以使用新的词法分析器来识别 next 标记,如果愿意,可以丢弃之前的词法分析器。
不可变词法分析器技术比修改状态的词法分析器更容易推理。您可以通过将丢弃的词法分析器保存在列表中来调试它们,现在您可以立即打开标记化操作的完整历史记录。
答案 1 :(得分:13)
strtok(char *str, const char *delim)
的限制是它不能同时处理多个字符串,因为它维护一个静态指针来存储索引,直到它被解析(因此,如果一次只播放一个字符串就足够了)。更好更安全的方法是使用strtok_r(char *str, const char *delim, char **saveptr)
显式获取第三个指针来保存已解析的索引。