无法正确打印txt文件

时间:2014-03-09 19:50:21

标签: c file while-loop

这是我的C编程课程的家庭作业。

我得到一个文本文件,有两个数据列;第一列是age;第二列是avgprice。我能够很好地阅读和打印这些值。但是,出于某种原因,ageavgprice会在输出中翻转。我不知道为什么。

这是代码

#include "stdafx.h"
#include <stdio.h>

int main() {

double age, avgprice; //age = 1st column, avgprice = 2nd column
FILE *corolla; //ptr for file
char eof; //needed for end of file check

corolla = fopen("C:/Users/Nate/Downloads/DataFiles/corolla.txt", "r");
if (corolla == NULL) { //makes sure the file exists
    printf("File does not exist!\n");
    return 0; //prevents crashing
}
else {
    printf("Age \t\t Average Price\n"); //header for data when printed
    /*prints values until we're at the end of the file*/
    while (fscanf(corolla, "%c", &eof) != EOF) {
        fscanf(corolla, "%lf %lf", &age, &avgprice); //scans in data from file
        printf("%.1f \t\t $%.2f\n", age, avgprice); //prints data from file
    }
}
fclose(corolla); //closes file
return 0;
}

这是输出的样子

bad_output

这令我感到困惑,因为我使用这种确切的格式与其他数据文件做同样的事情 - 没有问题。由于某种原因,这个文件有困难。

这是我应该阅读的数据文件。我已将其上传到我的Dropbox,您可以根据需要检查格式。 Corolla.txt

2 个答案:

答案 0 :(得分:1)

您的输入文件使用基于行的格式。 fscanf按块读取输入块。块通常是由空白隔开的东西,可以是空格,制表符甚至是新行。因此fscanf不适合读取基于行的格式。

在我看来,最好分两步读取输入:首先,用fgets读取一行,然后用sscanf读取该行的数据。例如:

#include <stdlib.h>
#include <stdio.h>

int main()
{
    FILE *f;
    int line = 0;

    f = fopen("kk", "r");
    if (f == NULL) {
        printf("File does not exist!\n");
        return 0;
    }
    printf("%20s%20s\n", "age", "avg. price ($)");

    for (;;) {
        char buffer[80];
        int age, price;

        if (fgets(buffer, sizeof(buffer), f) == NULL) break;
        line++;

        if (sscanf(buffer, "%d %d", &age, &price) < 2) {
            printf("(Skipping bad input in line %d).\n", line);
        } else {
            printf("%20d%20d\n", age, price);
        }
    }
    fclose(f);

    return 0;
}

这也为您提供了一种低级错误报告。

此外,通常无需对EOF进行额外检查。当到达文件末尾时,文件输入函数返回特殊值。 fscanfgetc返回EOF; fgets返回NULL。根据这些返回值停止阅读通常总是更好。

在你的情况下,fscanf("%c", &oef)会占用文件中的第一个字符,即数字1.幸运的是,之后它只会以换行符为主,因此您的输入不会变得更糟。 (但要将扫描格式更改为"%lf %lf ",以便大幅降价。)

答案 1 :(得分:1)

这一行:

while (fscanf(corolla, "%c", &eof) != EOF)

从文件中读取一个字符。文件中的第一个字符为1,因此它将1读入eof

你的下一行是:

fscanf(corolla, "%lf %lf", &age, &avgprice); 

按顺序读取文件中的下两个条目,即139902。因此,第一个年龄为13990,第一个平均价格为2

之后,文件指针现在指向2之后的空白区域。你去的时候:

fscanf(corolla, "%c", &eof)

它将空格读入eof

然后当你到达:

fscanf(corolla, "%lf %lf", &age, &avgprice); 

它分别读取接下来的两个值13495和3。等等。

要解决此问题,您应该停止fscanf(corolla, "%c", &eof)。我不知道你期望这完全做什么,但它不测试你是否在文件的末尾。相反,它会读取一个字符,忽略该字符,并检查fscanf的返回值。

修复您的代码:

while (2 == fscanf(corolla, "%lf %lf", &age, &avgprice))
{
    printf("%.1f \t\t $%.2f\n", age, avgprice); //prints data from file
}

fscanf的返回值是成功读取的项目数(如果成功)。当它返回2以外的其他内容时,您知道必须已经到达文件的末尾。