我对fscanf和printf做错了什么?

时间:2014-05-12 01:32:33

标签: c printf scanf

我在使用fscanf函数或printf函数时遇到了一些困难。我使用printf函数进行测试,以查看我的值是否正确存储,并且它们无法正常工作。 Printf在输出屏幕上打印一些非常奇怪的值。

来自payfile.txt的文字:

ADA     A AGUSTA    33 BABBAGE ROAD  LOVELACE    GB 19569 28 F 2 350.50
ISSAC   A ASIMOV    99 FICTION WAY   AMHERST     MA 63948 58 M 6 423.88
HUMPHRY R BOGART    71 SAM STREET    HOLLYWOOD   CA 48482 56 M 5 366.00
ALBERT  G EINSTEIN  94 ENERGY WAY    PRINCETON   NJ 47474 67 M 8 780.00
EMMYLOU L HARRIS    66 COUNTRY ROAD  NASHVILLE   TN 72647 38 F 2 767.42
JAMES   T KIRK      11 SPACE STREET  VULCAN      CA 82828 46 M 1 235.70
TED     L KOPPEL    55 ABC PLACE     WASHINGTON  DC 37376 48 M 9 909.44
DAVID   T LETTERMAN 14 WNBC AVENUE   NEW YORK    NY 19338 47 M 5 445.65
STEVIE  R NICKS     31 MUSIC ROAD    CHICAGO     IL 23459 38 F 8 460.88
MONTY   P PYTHON    76 SILLY STREET  LONDON      GB 80939 44 M 2 320.50
ROGER   R RABBIT    15 LOONEY TOONS  HOLLYWOOD   CA 91343 24 M 4 259.53
SALLY   W RIDE      21 COLUMBIA WAY  HOUSTON     TX 91123 30 F 9 707.80
ROD     Q SERLING   11 TWLIGHT ZONE  SAN DIEGO   CA 93939 56 M 1 440.00
LUKE    R SKYWALKER 43 MILKY WAY     NEW YORK    NY 12343 35 M 5 660.00

源文件:

#include <stdio.h>

typedef struct {
    char first[8];
    char initial;
    char last[10];
    char street[17];
    char city[12];
    char state[3];
    char zip[6];
    int age;
    char sex;
    int tenure;
    double salary;
} Employee;

void readData(Employee *number);

int main(void){
    Employee number[14];

    readData(number);
    getchar();
    return 0;
}

void readData(Employee *number){
    int i;
    FILE *f = fopen("payfile.txt", "r");
    for (i = 0; i < 14; i++) {
        fscanf(f, "%7s %c %9s %16s %11s %2s %5s %d %c %d %lf\n", number[i].first, &number[i].initial, number[i].last, number[i].street, number[i].city, number[i].state, number[i].zip, &number[i].age, &number[i].sex, &number[i].tenure, &number[i].salary);
        printf("%s %c %s %s %s %s %s %d %c %d %f\n", number[i].first, number[i].initial, number[i].last, number[i].street, number[i].city, number[i].state, number[i].zip, number[i].age, number[i].sex, number[i].tenure, number[i].salary);
    }
}

3 个答案:

答案 0 :(得分:3)

使用%sscanf表示阅读。当它撞到一个空间时停止。但是,您的源文件在您尝试阅读的内容中包含一些空格。例如,WASHINGTONNEW YORK都需要读入city

您必须从文件中读取确切数量的字符,而不是使用%s

这样做的一种方法是,仅在fscanf中更改%11s以使用此说明符:%11[^\n]。这意味着要读取接下来的11个字符(除非我们点到该行的末尾),即使其中有空格。

这实际上会将尾随空格放入你的字符串中,所以如果你不想要尾随空格,那么你需要创建另一个从字符串中删除它们的函数。

您还应该检查fscanf的返回值。由于您尝试阅读11个项目,因此应返回11。如果它返回其他内容,那么您的程序应该报告数据错误并停止阅读。

NB。出于测试目的,在printf中,在项目之间使用逗号或其他内容,而不是空格;这样可以更容易地识别数据是否以您期望的方式读取。

答案 1 :(得分:2)

基于空格的fscsanf标记。因此,您的地址将被标记为其各个部分,因此无法按预期进行匹配。

您应该有一个字段分隔符,例如,(通常有问题),|(通常更好,但不完美),或\t(数据时可能有点棘手)得到传播)。

然后使用strtok_r之类的函数来获取每个字段。

PS。 scanf系列函数对于解析(特别是捕获错误)并不是特别健壮;你可以迅速达到限制。

答案 2 :(得分:1)

为什么不直接将它们读入带有fgets的结构?或者更好的是,如果它是Posix系统,并且因为大小是固定的read()。

typedef struct {
  char first[8];
  char initial[2];
  char last[10];
  char street[17];
  char city[12];
  char state[3];
  char zip[6];
  char age[3]
  char sex[2];
  char tenure[2];
  char salary[6];
  char pad[128-71]; // pad to a factor of 2
} Employee;

然后根据需要明确地处理任何必要的转换,或者根据需要直接处理单独的结构,甚至可以使用联合来完成它。

这是一个示例结构(*因为我使用了嵌套的匿名联合和结构,因此如果你抓到了什么就编辑我)

typedef struct {
  char first[8];
  char initial[2];
  char last[10];
  char street[17];
  char city[12];
  char state[3];
  union{
    char zip_in[6];
    struct{
    int zip;
    char pad_zip[2];
    }
  }
  union{
    char age_in[3]
    struct{
      short age;
      char pad_age;
    }
  }
  char sex[2];
  char tenure[2];
  union{
    char salary_in[6];
    struct{
      float salary;
      char pad_salary[2];
    }
  }
  char pad[128-71]; // pad to a factor of 2
} Employee;

在阅读每位员工后,您需要为每个字段运行适当的转化。这包括将'\ 0'放在字符串的末尾,将非字符串字段转换为short,int或float。请记住,它们占据了相同的记忆。