【问题标题】:Is there an equivalent to the rewind function, but for one token only?是否有与倒带功能等效的功能,但仅适用于一个令牌?
【发布时间】:2015-02-22 23:16:39
【问题描述】:

在 C 语言中,rewind 函数用于将流的位置设置为最开始。我想问一下是否有一个等效的函数可以将流位置向左移动一个标记。

例如,我有一个名为 FooFile.txt 的文件,其中包含几行整数序列,由 " " 空格字符分隔。

int main()
{
    // open file stream.
    FILE *FooFile = fopen("FooFile.txt" , "r");
    int Bar = 0;

    // loop through every integer token in the file stream.
    while ( fscanf( FooFile, "%d", &Bar ) == 0 )
    {
        // I don't want to reset the stream to the very beginning.
        // rewind( FooFile );
        // I only need to move the stream back one token.

        Bar = fscanf ( FooFile, "%d", &Bar )
        Bar = fscanf ( FooFile, "%d", &Bar )
    }
}

【问题讨论】:

  • fgetposfsetpos。祝你好运。
  • 对于 1 个字符的情况,ungetc() 应该可以工作。

标签: c loops token


【解决方案1】:

您需要"%n" 说明符来知道读取了多少个字符,然后您需要fseek() 知道读取的负数字符,这是一个示例

#include <stdio.h>

int main()
{
    FILE * file  = fopen("FooFile.txt" , "r");
    int    bar   = 0;
    int    count = 0;

    if (file == NULL)
        return -1;

    while (fscanf(file, "%d%n", &bar, &count) == 1)
    {
        fseek(file, -count, SEEK_CUR);
        /* if you don't re-scan the value, the loop will be infinite */
        fscanf(file, "%d", &bar);
    }

    return 0;
}

请注意,在您的代码中有错误,fscanf() 不返回读取值,而是返回说明符匹配的参数数量。

【讨论】:

  • 此方法可能会失败,尤其是如果换行符位于数字之前。对文本文件执行fseek() 是UB,除非该目标是先前ftell() 的结果,或者是有效的倒带,或转到结束。 C11dr §7.21.9.2 “对于文本流,偏移量应为零,或偏移量应为先前成功调用与同一文件关联的流上的 ftell 函数返回的值,并且应为 SEEK_SET。”建议重新考虑这个答案。
【解决方案2】:

如果long 足够大,您可以使用ftell 获取当前位置,使用fseek 设置当前位置。

最好使用fgetposfsetpos 来处理所有可能的文件偏移。

#include <stdio.h>

fpos_t pos;
if(fgetpos(file, &pos)) abort(); // Get position

/* do naughty things */

fsetpos(file, pos); // Reset position

http://man7.org/linux/man-pages/man3/fseek.3.html
http://en.cppreference.com/w/c/io/fsetpos

【讨论】:

  • 很好:执行ftell()fgetpos() 是在文本文件中重新定位文件指针的最佳方式。
猜你喜欢
  • 2011-11-18
  • 2023-03-14
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 2011-03-31
相关资源
最近更新 更多