0

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

任何建议都将被视为非常有帮助。

4

1 回答 1

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 Fromscanf()

于 2017-11-20T01:51:37.903 回答