【问题标题】:Reading in data with fscanf用 fscanf 读入数据
【发布时间】:2018-05-03 04:42:02
【问题描述】:

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

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

【问题讨论】:

  • 检查来自fscanf() 的返回值,并获得一个会抱怨滥用fscanf() 的编译器——比如GCC。您需要一个格式字符串参数,其中包含一个字符串中的所有转换,然后是存储数据的指针参数。与printf()类似。
  • 输入示例会很方便
  • 数据中是否有空白行,或者这些行是连续的?这不是一个大问题(但它是一个问题)。我在编辑时查看数据时不清楚。
  • 我在示例数据中看不到一个逗号。 fscanf的格式与数据不匹配

标签: c text-files scanf c-libraries


【解决方案1】:

数据说明之前

检查来自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()

【讨论】:

  • 次要:size_t buflen 可以是 size_t buf_size 以更好地匹配代码使用的语义
猜你喜欢
  • 1970-01-01
  • 2015-01-24
  • 1970-01-01
  • 1970-01-01
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多