嘿,我有一个关于从文本文件中读取信息的快速问题。 我有一个格式化的.txt文件中包含客户信息。该文件包含多个客户,每个客户都有不同的订单类型,购买的产品,地址,城市,州,总成本等。当我使用fscanf()时,它没有返回任何值,而在调试器中,所有的值都分配给了我变量不正确。
以下是文本文件中的数据:
0
Programming With C
Larry Page
1600 Amphitheatre Parkway
Mountain View
California
94043
81.07
1
Data Structures and Algorithms in Java
Elon Musk
3500 Deer Creek Road
Palo Alto
California
94304
32.50
2
Computer Science Distilled
James Gosling
1234 Main Dr.
San Francisco
California
94122
35.70
这是我使用的代码。
int orderType, zipCode;
double totalCost;
char product[MAXSIZE], customer[MAXSIZE], address[MAXSIZE], city[MAXSIZE], state[MAXSIZE];
// Scan in the order type, product name, customer, address, city, state, zip code, order cost
fscanf(customerDataPtr, "%d", "%s", "%s", "%s", "%s", "%s", "%f", "%f");
printf("%d", "%s", "%s", "%s", "%s", "%s", "%f", "%f",
orderType, product, customer, address, city, state, zipCode, totalCost);
任何建议都会被认为非常有帮助。
答案 0 :(得分:4)
检查来自fscanf()
的返回值,并获得一个抱怨fscanf()
滥用的编译器 - 例如GCC。您需要一个格式字符串参数,其中包含单个字符串中的所有转换,然后是存储数据的指针参数。与printf()
类似。
你有:
fscanf(customerDataPtr, "%d", "%s", "%s", "%s", "%s", "%s", "%f", "%f");
printf("%d", "%s", "%s", "%s", "%s", "%s", "%f", "%f",
orderType, product, customer, address, city, state, zipCode, totalCost);
您需要的或多或少的最低版本是:
if (fscanf(customerDataPtr, "%d%s%s%s%s%s%d%f", &orderType, product,
customer, address, city, state, &zipCode, &totalCost) == 8)
{
printf("%d %s %s %s %s %s %.5d %f",
orderType, product, customer, address, city, state, zipCode, totalCost);
}
else
{
…handle error somehow…
}
请注意使用%d
来阅读和打印邮政编码。
另请注意,产品必须是单个单词,客户名称必须是单个单词,地址必须是单个单词,城市必须是单个单词,并且状态必须是单个单词。这套限制是不现实的,但你应该可以从这里到达某个地方。
您需要使用fgets()
或POSIX读取行
getline()
,然后适当地存储结果。这主要意味着删除换行符,检查溢出等等。
处理过程比较繁琐;目前还不完全清楚什么是最好的方法。一个简单的方法,应该工作,模拟代码中的任何拼写错误:
static int read_line(FILE *fp, size_t buflen, char *buffer)
{
char line[4096];
if (fgets(line, sizeof(line), fp) == 0)
return -1;
line[strcspn(line, "\n")] = '\0';
if (strlen(line) >= buflen)
return -1;
strcpy(buffer, line);
return 0;
}
在其他一些功能中:
char line[4096];
FILE *fp = customerDataPtr; // That name is too damn long!
if (fgets(line, sizeof(line), fp) == 0)
return -1;
if (sscanf(line, "%d", &orderType) != 1)
return -1;
if (read_line(fp, product, sizeof(product) != 0)
return -1;
if (read_line(fp, customer, sizeof(customer) != 0)
return -1;
if (read_line(fp, address, sizeof(address) != 0)
return -1;
if (read_line(fp, city, sizeof(city) != 0)
return -1;
if (read_line(fp, state, sizeof(state) != 0)
return -1;
if (fgets(line, sizeof(line), fp) == 0)
return -1;
if (sscanf(line, "%d", &zipCode) != 1)
return -1;
if (fgets(line, sizeof(line), fp) == 0)
return -1;
if (sscanf(line, "%f", &totalCost) != 1)
return -1;
printf("%d: %s\n%s\n%s\n%s %s %.5d\n%f",
orderType, product, customer, address, city, state, zipCode, totalCost);
return 0;
请注意,没有错误报告;代码在出错时返回-1,在成功时返回0。你可能想要做得更好。您可以将“整数读取和分配”代码封装到类似于所示的read_line()
函数的函数中;你要适当地重命名这些功能。您可能还会添加一个函数来处理“浮点读取和分配”。请注意打印格式的变化,以更好地处理基于行的输入。您可以使用格式字符串来获取内容。
我注意到理论上你可以使用复杂的fscanf()
格式字符串,例如这个,假设MAXSIZE是128:
if (fscanf(fp, "%d %127[^\n]%*c %127[^\n]%*c %127[^\n]%*c %127[^\n]%*c %127[^\n]%*c %d %f",
&orderType, product, customer, address, city, state, &zipCode, &totalCost) == 8)
但是错误恢复并没有考虑到。如果你甚至是最偏僻的人想要使用这样的怪物,你应该阅读Beginnner's Guide Away From scanf()
。