【问题标题】:fscanf while-loop never runsfscanf while-loop 从不运行
【发布时间】:2016-08-27 12:33:54
【问题描述】:

我正在做一个项目,但我似乎无法弄清楚为什么我的一个查找素数的函数无法运行。本质上,我想编写代码以首先检查文本文件日志中是否存在任何先前遇到的素数,但无论我为包含 fscanf() 的 while 循环输入什么,我的代码似乎永远不会进入它。

int filePrime(int a) {
int hold = 0;
FILE *fp = fopen("primes.txt", "a+");

if (fp == NULL) {
    printf("Error while opening file.");
    exit(2);
}

/*
the while loop below this block is the one with the issue.
on first run, it should skip this loop entirely, and proceed
to finding prime numbers the old-fashioned way, while populating the file.
instead, it is skipping this loop and proceeding right into generating a
new set of prime numbers and writing them to the file, even if the previous
numbers are already in the file
*/

while (fscanf(fp, "%d", &hold) == 1){ 
    printf("Inside scan loop.");
    if (hold >= a) {
        fclose(fp);
        return 1;
    }
    if (a % hold == 0) {
        fclose(fp);
        return 0;
    }
}

printf("Between scan and print.\n");

for (; hold <= a; hold++) {
    if (isPrime(hold) == 1) {
        printf("Printing %d to file\n", hold);
        fprintf(fp, "%d\n", hold);
        if (hold == a)
            return 1;
    }
}

fclose(fp);
return 0;
}

我已经尝试了对 while-loop 测试的各种更改。
前任。 != 0, != EOF,完全切断 == 1。

我似乎无法让我的代码使用 fscanf 进入循环。

非常感谢您的帮助,非常感谢您的宝贵时间。

【问题讨论】:

  • primes.txt有数据吗?第一个“字段”是数字吗?你确定吗?考虑使用 fgets() 读取一行 - 这样您就可以打印它,然后使用 sscanf() 而不是 fscanf() 扫描它。
  • prime.txt 要么是一个全新的文件,由 fopen() 创建,要么是由 fprintf() 进一步填充代码中的整数。我还尝试使用初始素数“2”运行它,但没有任何改变。
  • if (hold == a) return 1; 不会先关闭fp。
  • 为什么不看看 fscanf 返回了什么。
  • "a+" 模式将当前文件指针留在哪里?在文件的开头还是结尾?如果您在fscanf() 循环之前执行fseek(fp, 0L, SEEK_SET),那会改变什么吗?

标签: c while-loop scanf


【解决方案1】:

在comment中,我问"a+"模式离开当前位置在哪里?

在 Mac OS X 10.11.4 上,使用 "a+" 模式打开文件并将读/写位置定位在文件末尾。

演示代码(aplus.c):

#include <stdio.h>

int main(void)
{
    const char source[] = "aplus.c";
    FILE *fp = fopen(source, "a+");
    if (fp == NULL)
    {
        fprintf(stderr, "Failed to open file %s\n", source);
    }
    else
    {
        int n;
        char buffer[128];
        fseek(fp, 0L, SEEK_SET);
        while ((n = fscanf(fp, "%127s", buffer)) == 1)
            printf("[%s]\n", buffer);
        printf("n = %d\n", n);
        fclose(fp);
    }
    return(0);
}

如果没有fseek(),n 的返回值立即为 -1 (EOF)。 使用fseek(),可以读取数据(源代码)。

有一件事让我有点困惑:我在 POSIX fopen() 规范(或 C 标准)中找不到提到在使用 "a+" 模式打开文件后的读/写位置的信息。很明显,无论fseek() 的介入使用如何,写操作都将始终结束。

POSIX 规定对open() 的调用应使用O_RDWR|O_CREAT|O_APPEND 表示"a+",而open() 指定:

用于标记文件中当前位置的文件偏移量应设置为文件的开头。

但是,正如chux notes(谢谢!),C 标准明确表示:

附录 J 可移植性问题

J.3 实现定义的行为

J.3.12 库函数

…
附加模式流的文件位置指示符最初是否位于 文件的开头或结尾 (7.21.3)。
…

所以看到的行为在 C 标准中是允许的。

fopen() 在 Mac OS X 上的手册页说:

  • "a+" — 可读写。如果文件不存在,则创建该文件。流位于文件的末尾。对文件的后续写入将始终在文件的当前末尾结束,而与任何干预 fseek(3) 或类似内容无关。

这是标准 C 允许的;目前尚不清楚它是否完全符合 POSIX。

【讨论】:

  • 注意:C11 §J.3.12 可移植性问题“附加模式流的文件位置指示符最初是位于文件的开头还是结尾 (7.21.3)。”
  • 这正是我需要看到的。我在 OS X 10.11.4 上。它是这个版本的 OS X 独有的,还是我应该注意前进的东西?在我检查的所有文档中,它告诉我“a+”应该在开头打开读取位置,在末尾打开写入位置。
  • @ConCat:查看答案的更新,以及来自 chux 的评论。它是实现定义的;它可能因平台而异。使用显式 fseek() 是明智的,因为行为可能会有所不同。注意在读和写操作之间,或者在写和读之间,无论如何都需要使用定位函数(比如fseek())。
猜你喜欢
  • 2021-05-29
  • 1970-01-01
  • 2018-09-27
  • 2011-08-27
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
相关资源
最近更新 更多