我在使用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);
}
}
答案 0 :(得分:3)
使用%s
和scanf
表示阅读字。当它撞到一个空间时停止。但是,您的源文件在您尝试阅读的内容中包含一些空格。例如,WASHINGTON
和NEW 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。请记住,它们占据了相同的记忆。