putback()和unget()的区别

28

我正在使用标准I/O流从文件中获取一些输入,但我对于 unget()putback(character) 之间的区别感到困惑。从文档上看,这些函数似乎是相同的,在这里 unget() 只是记住了放入的字符,所以我很紧张。我一直在使用 putback(character),但是character 总是最后读取的字符,我一直在考虑改用 unget()。如果 character 始终是最后读取的字符,那么putback(character) 是否总是等同于unget()

2个回答

19

unget()不会欺骗,它可以“撤回”最后读取的字符。而putback(c)可以欺骗,你可以“放回”一个与最后读取的字符不同的字符。有时,放回一个非最后读取的字符是有用的。

另外,如果底层读取缓冲区确实具有缓冲功能,你可以“放回”多个字符。我认为ungetc()仅限于一个字符。

编辑
不对。看起来unget()可以回退至与putback()相同的程度。


жҲ‘并дёҚжҳҜеңЁжҠұжҖЁдҪ зҡ„е®Ңе…ЁеҗҲзҗҶзҡ„еӣһзӯ”пјҢдҪҶжҲ‘и®Өдёәе®ғе®һйҷ…дёҠ并没жңүеӣһзӯ”иҝҷдёӘй—®йўҳгҖӮеҰӮжһңжҲ‘з”Ёunget()жӣҝжҚўжүҖжңүзҡ„putback(character)и°ғз”ЁпјҲе…¶дёӯcharacterдҝқиҜҒжҳҜжңҖеҗҺиҜ»еҸ–зҡ„еӯ—з¬ҰпјүпјҢйӮЈд№Ҳе®ҡд№үзҡ„иЎҢдёәжҳҜеҗҰзӣёеҗҢпјҹ - Puppy
2
在我看来确实是这样。putback()函数使您能够放回除最后读取的字符以外的其他内容。如果您只使用putback(last_read_character),则效果与调用unget()相同,但没有明确保证您真正“取消获取”了最后读取的字符。 - David Hammen
我最终还是使用了一个自定义流,可以将任意数量的字符放回。 - Puppy

4
这可能不是您预期的答案,但我想介绍一下我的原因。文档指出,方法putbackunget分别调用streambuf::sputbackcstreambuf::sungetc。定义如下:

streambuf::sungetc

将获取指针向后移动一个字符,使输入操作获取到的最后一个字符再次可用于下一次输入操作。

在其操作期间,如果获取指针gptr指向与开始指针eback相同的位置,则该函数将调用受保护的虚拟成员函数pbackfail。

另外一个:

streambuf::sputbackc

将获取指针后移,指向其当前位置之前的字符,因此上一次获取的字符c再次可用作下一次输入操作时要读取的字符。

在其操作期间,如果字符c不匹配gptr()[-1]或者获取指针gptr指向与开始指针eback相同的位置,则该函数会调用受保护的虚拟成员函数pbackfail。

当c与该位置的字符不匹配时,streambuf中pbackfail的默认定义将c前置为该位置提取的字符(如果可能),但派生类可以覆盖此行为。

成员函数sungetc的行为类似,但不带任何参数。

由于sputbackc在字符不匹配时调用pbackfail,这意味着该方法必须检查值是否相等。看起来额外的检查是唯一的开销,但我不知道实际上如何解决这个问题。我可以想象,如果最后一个字符没有存储在对象中,则必须重新读取它,因此即使保证字符相同,您可能也会期望这种情况发生。
当我们调用unget时,我有点担心的情况是最后一个字符不可用。putback是否能正确放置该值?我认为不行,但在操作文件时不应该出现这种情况。

1
看起来有不止一个差异。Putback 看起来像是前置?你确定它不是替换吗?考虑输入 "ABC",如果你读取 A,然后 B,然后 putback B,前置会插入并使输入流变为 "ABBC"。这是真的吗? - Lee Louviere
1
@Xaade,这取决于实现,streambuf默认情况下不执行任何操作。如果具有写入权限,则stringbuf将替换原始字符串中的字符,但是filebuf仅替换内部缓冲区中的字符,因此底层文件不受影响(但也会减少获取指针,因此在流中插入新字符没有影响)。更多细节请参见规范:http://www.cplusplus.com/reference/iostream/streambuf/pbackfail/。 - tomasz

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