【问题标题】:File pointers behave differently when passed to functions. Why?文件指针在传递给函数时表现不同。为什么?
【发布时间】:2015-05-13 11:19:48
【问题描述】:

所以我有这个代码

void getdata(int *q)
{
   for(int i=0;i<3;++i)
      scanf("%d",q++);
   *q=10;
}

int main()
{
   int *p,a[4];
   p=a;
   getdata(p);
   printf("%d",*p);
   return 0;
}

而且输出很明显。

7
8
9
7

但文件指针的工作方式不同。我正在尝试编写用于将数据附加到文件中的基本代码。

void getdata(FILE *fp)
{
    char ch;
    while((ch=getchar())!=EOF)
        fputc(ch,fp);
    rewind(fp);
}

void printdata(FILE *fp)
{
    char ch;
    while((ch=fgetc(fp))!=EOF)
        putc(ch,stdout);
}
int main()
{
    FILE *fp1;
    fp1=fopen("music.txt","w+");
    getdata(fp1);
    printf("Text is::\n");
    printdata(fp1);
    fp1=fopen("music.txt","a+");
    printf("\nEnter some more text::\n");
    getdata(fp1);
    printf("\nAfter appending text is::\n");
    printdata(fp1);
    return 0;
}

此代码运行良好。但是如果rewind(fp); 被删除,它的行为就会很奇怪。为什么我需要倒带指针?虽然指向同一个文件的 fp1fp 不是函数本地的,所以不应该像第一个程序那样相互影响?

【问题讨论】:

  • fputcputcrewind 更改指针指向的 io 对象。因此,指针是本地的并不重要。
  • fputc(ch,fp); in getdata 应该是 fgetc(ch,fp),对吧?顺便说一句,ch 的类型应该是 int,而不是 char
  • @CoolGuy 问题是,我没有看到 prints all 元素的声明。
  • @SouravGhosh,对。没注意。
  • 它们的工作原理完全相同——第一个函数修改q指向的东西,第二个函数修改fp指向的东西。

标签: c file pointers


【解决方案1】:

让我们看一下 FILE 结构的一个可能的非常简化的实现。出于示例的目的,假设content 指向映射到磁盘上文件的内存。

typedef struct FILE {
    size_t size;
    size_t cursor;
    uint8_t *content;
} FILE;

int fputc(FILE *f, char c) { size++; return f->content[f->cursor++] = c; }
int fgetc(FILE *f) { return (f->cursor == f->size) ? EOF : f->content[f->cursor++]; }
void rewind(FILE *f) { f->cursor = 0; }

现在,当您调用这些函数时,很明显它们会修改底层对象。当你写完文件后,光标指向最后一个元素,所以如果你不rewindfgetc 将立即返回 EOF。


澄清一下,当您调用fopen 时,您会创建一个存储在某处的FILE 对象。你无法控制这个对象,你只是得到一个指向它的指针。如果更容易理解,您可以将此指针(在您的示例中为 fp1)视为文件 ID。任何更改都在 FILE 对象上完成,而不是指针/ID 本身。

【讨论】:

    【解决方案2】:

    任何打开文件的进程都有一个数据结构,它存储与文件相关的查找位置等。无论您打开同一个文件多少次,它都是指向同一个 DS 的指针。打印两个 File 指针的值,它应该是相同的......所以无论您访问哪个 File * 都没有关系。他们会互相影响工作......

    最好的做法是 1 个 FP 到 1 个文件...如果您需要另一个关闭前一个文件

    因为打开的文件算作进程的资源。所以这更多地与进程资源有关,而不是位置

    【讨论】:

    • 你确定吗?我只是尝试打开同一个文件两次,从第一个 FILE 指针读取,然后从第二个指针读取。它从一开始就开始了。您对您的主张有任何参考吗?
    • 那个是关于open,而不是fopen。这几乎不相关。
    【解决方案3】:

    其他答案更技术性地解释它,所以我会保持简单。

    先了解以下内容

    • fp 就像一个头指针。它在每次读取写入操作时向前移动,因此下一次对文件的读取或写入将从上一次操作的末尾开始。
    • 由于它是一个指针,因此无论何时更改(在函数中或在 main 中),更改都会反映在任何地方。
    • Rewind 将 fp 设置为文件的开头

    所以在本例中,当您使用 getdata 写入文件时,fp(或头部)在写入每个字符后向前移动,即始终保持在文件末尾。然后倒带将其带回文件的头部。因此,当您再次打印时,读取从文件开头开始,而不是从文件结尾开始。

    现在,如果您不倒带,那么 fp 将保留在文件末尾,而 printdata 将不会打印任何内容。

    【讨论】:

      猜你喜欢
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 2020-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多