关于C中的文件输入和输出

时间:2014-09-15 23:57:58

标签: c file input output

我通常不会在这里问问题,除非我真的卡住了!我想知道是否有人可以解释为什么我的代码打印出'5 47'。我理解为什么有一个5,但不是为什么有47?我查找了空白空间(32)的ASCII值,我尝试将第二个字母更改为e,f,g,例如输出保持'5 47'不变。

一般情况下,当我使用fscanf(fp, "%d", &variablename)时,fscanf是否会跳过其他字符?例如:在我的文件test.txt中,我有“5 hello 6 ben jerry\n”。我如何扫描5和6? fscanf(fp, "%d %d", &test1, &test2)会在5和6中扫描,跳过“你好”这个词吗?

这是我用来测试输出的简单代码:

int main(int argc, char *argv[]) {
  int blah, test;
  FILE * fp;
  fp = fopen(argv[1], "r");
  fscanf(fp, "%d %d", &blah, &test);
  printf("%d %d\n", blah, test);
  return 0;
}

我使用的文件是argv [1]内容:

5g

P.S。是FILE *fp一个指向每个字符/数字的实际指针,它是否在扫描文件时作为占位符工作?这就是为什么我们需要rewind(fp)一旦它到达文件的末尾?

2 个答案:

答案 0 :(得分:1)

运算符%d查找整数,而不是字符。因为g是一个字符,而不是一个整数,%d变得混乱,输出不会总是5 47. 47可以是任何东西。这可能是5,7,5 23等。这是因为fscanf没有读取第二个数字,因此没有分配值来测试。因此,测试保持在程序启动时位于该存储器中的值。

要解决此问题,请将%d替换为%c,并将blah和test的类型更改为int。另外,正如WhozCraig所说,检查fscanf的返回值以检查是否找到了两个值是一种好习惯。这样,您就可以确定找到了您正在寻找的所有内容。

答案 1 :(得分:1)

请注意,scanf()函数系列在遇到格式字符串不期望的字符时会停止读取。意外字符留在输入中以供下一个要处理的输入操作。

如果你想要读取两个明确用非整数的“单词”分隔的整数,那么你需要跳过这个单词。如果您事先不知道该单词是什么,则需要使用赋值抑制(有关大量信息,请参阅POSIX scanf()页面。)

因此,您的代码从包含

的输入中读取两个整数
5 hello 6 ben jerry

应该是:

if (fscanf(fp, "%d %*s %d", &blah, &test) != 2)
    …Oops; format error?…

请注意,代码测试它得到了预期的结果。但是,如果您不知道这两个数字之间是否有单词,那么使用fgets()sscanf()会更好,因为您可以尝试同一行的不同解析:

char buffer[4096];

while (fgets(buffer, sizeof(buffer), fp) != 0)
{
    if (sscanf(buffer, "%d %*s %d", &blah, &test) == 2)
        …got two numbers with a word — let's go!
    else if (sscanf(buffer, "%d %d", &blah, &test) == 2)
        …got two numbers but no word — let's go!
    else
        …didn't recognize the format…
}

这样做的一个主要优点是,您可以根据完整的输入行报告错误,而不仅仅是fscanf()无法处理的部分。

关于FILE *的最后一个问题,不是指向文件中每个字符的指针。它是一个句柄,允许您调用带有文件指针参数的函数来读取或写入相关文件。但是,您不能使用基于文件指针的索引(因此fp[1024] 标识文件中偏移1024处的字符或类似的任何有用的字符)。如果您需要这种行为,则需要一个内存映射文件(POSIX系统mmap())。