使用fscanf读取数据

时间:2017-11-20 01:37:45

标签: c text-files scanf c-libraries

嘿,我有一个关于从文本文件中读取信息的快速问题。 我有一个格式化的.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);

任何建议都会被认为非常有帮助。

1 个答案:

答案 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()