呵呵!!我怎么才能把整件事都问清楚呢!!让我试试:
我知道使用fopen()
打开的文件被缓冲到内存中。我们使用缓冲区是为了提高效率和方便。从文件中读取时,首先将文件内容读取到缓冲区,然后再从缓冲区中读取。同样,在对文件的写入中,先将内容写入缓冲区,然后再写入文件。
但是,如果fseek()
、fsetpos()
和rewind()
删除以前对ungetc()
的调用的效果,又会怎样呢?你能告诉我是怎么做的吗?我是说,鉴于我们已经打开了一个文件进行读取,并将其复制到缓冲区中。现在使用ungetc()
我们已经更改了缓冲区中的一些字符。以下是我在付出很大努力后仍然无法理解的:
以下是关于ungetc()
--“调用流上fseek、fsetpos或倒带将丢弃先前用此函数放回其中的任何字符。”--如何丢弃已放回缓冲区中的字符?一种方法是删除的原始字符被“记住”,每一个输入的新字符都被识别并替换为原始字符。但是它看起来效率很低。另一个选择是将原始文件的副本加载到缓冲区并将文件指针放在指定的位置。fseek、fsetpos或rewind采用哪种方法来丢弃使用ungetc()
输入的字符?
对于文本流,流中存在未读字符(使用ungetc()
输入的字符)如何影响ftell()
的返回值?我的困惑来自下面关于ftell()
的一行,而ungetc()
来自这个关于ftell
的链接(SOURCE)
对于文本流,该数值可能没有意义,但以后仍可以使用fseek将位置还原到相同的位置(如果有使用ungetc放回的字符仍在等待读取,则行为未定义)
集中在上一段的最后一行,pending of being read
与丢弃“ungetc()-get”字符有什么关系?每次我们读取使用ungetc()
放入流中的字符时,是否在读取后将其丢弃?
最佳答案
一个好的放回字符的心理模型很简单,它是挂起FILE *
对象的一些额外的小属性。假设你有:
typedef struct {
/* ... */
int putback_char;
/* ... */
} FILE;
假设
putback_char
被初始化为表示“没有putback char”的值EOF
,并且ungetc
只是将字符存储到此成员。假设每个读取操作都经过
getc
,并且getc
会执行如下操作:int getc(FILE *stream)
{
int ret = stream->putback_char;
if (ret != EOF) {
stream->putback_char = EOF;
if (__is_binary(stream))
stream->current_position--;
return ret;
}
return __internal_getc(stream); /* __internal_getc doesn't know about putback_char */
}
清除回推的函数只需将
EOF
分配给putback_char
。换句话说,放回字符(只需要支持一个)实际上可以是一个小型缓冲区,它与常规缓冲区分离。(考虑到即使是无缓冲流也支持
ungetc
:这样的流必须将字节或字符放在某处。)关于位置指示器,C99标准规定如下:
对于文本流,在成功调用
ungetc
函数后,其文件位置指示符的值未指定,直到读取或丢弃所有被推回的字符。对于二进制流,每次成功调用ungetc
函数时,它的文件位置指示器都会递减;如果在调用之前它的值为零,则在调用之后它是不确定的。[7.19.7.11ungetc
功能]因此,您正在使用的www.cpluplus.com引用是不正确的;
ftell
的行为在有用ungetc
推后的挂起字符时不是未定义的。对于文本流,该值未指定。访问未指定的值不是未定义的行为,因为未指定的值不能是陷阱表示。
如果在位置零点发生逆推,则二进制流存在未定义的行为,因为该位置随后变得不确定。不确定意味着它是一个未指定的值,可能是一个陷阱表示。访问它可能会导致程序停止并显示错误消息,或者触发其他行为。
最好从马口中获取编程语言和库规范,而不是从随机的网站中获取。