简体   繁体   English

用fscanf读取数据

[英]Reading in data with fscanf

Hey all I had a quick question regarding reading in information from a text file. 嘿,关于从文本文件中读取信息,我有一个快速的问题。 I have a formatted .txt with customer information in the file. 我在文件中有一个格式化的.txt文件,其中包含客户信息。 The file contains multiple customers, each with a different order type, product purchased, address, city, state, total cost, etc. When I used fscanf() it returned no values, and in the debugger all the values that were assigned to my variables were incorrect. 该文件包含多个客户,每个客户具有不同的订单类型,购买的产品,地址,城市,州,总成本等。当我使用fscanf()时,它不返回任何值,并且在调试器中分配给我的所有值变量不正确。

Here is the data from the text file: 这是来自文本文件的数据:

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

Here is the code that I used. 这是我使用的代码。

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);

Any advice would be considered very helpful. 任何建议都将被认为是非常有帮助的。

Before the data was illustrated 在说明数据之前

Check the return value from fscanf() , and get a compiler that will complain about abuses of fscanf() — such as GCC. 检查fscanf()的返回值,并获得一个编译器,该编译器将抱怨fscanf()滥用—例如GCC。 You need one format string argument with all the conversions in a single string, and then the pointer arguments where the data will be stored. 您需要一个格式字符串参数,所有转换都在一个字符串中,然后是指针参数将存储数据。 Similarly with printf() . printf()类似。

You have: 你有:

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);

A more or less minimal version of what you need is: 您所需的基本版本是:

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…
}

Note the use of %d to read and print the zip code. 请注意使用%d来读取和打印邮政编码。

Also note that the product must be a single word, the customer name must be a single word, the address must be a single word, the city must be a single word, and the state must be a single word. 还要注意,产品必须是单个单词,客户名称必须是单个单词,地址必须是单个单词,城市必须是单个单词,州必须是单个单词。 That set of restrictions is not realistic, but you should be able to get somewhere from here. 那套限制是不现实的,但是您应该可以从这里得到一些帮助。

After the data is illustrated 数据说明之后

You need to read the lines using fgets() or perhaps POSIX getline() , and then store the results appropriately. 您需要使用fgets()或POSIX getline()读取行,然后适当地存储结果。 That mainly means removing the newlines, and checking for overflows, etc. 这主要意味着删除换行符,并检查溢出等。

The processing is fiddlier; 处理比较麻烦; it isn't entirely clear what's the best approach. 最好的方法尚不完全清楚。 A simple minded approach that should work, modulo any typos in the code, is: 可以对代码中的任何错字取模的简单思路是:

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;
}

In some other function: 在其他功能中:

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;

Note that there is no error reporting; 请注意,没有错误报告。 the code returns -1 on error and 0 on success. 代码返回-1表示错误,返回0表示成功。 You would probably want to do a lot better than that. 您可能想做得更好。 You could encapsulate the 'integer read and assign' code into a function analogous to the read_line() function shown; 您可以将“整数读取和分配”代码封装到一个类似于所示read_line()函数的函数中; you'd rename the functions appropriately. 您将适当地重命名功能。 You would probably add a function to handle 'floating point read and assign' too. 您可能还会添加一个函数来处理“浮点读取和分配”。 Note the variation in the print format to handle line based input better. 注意打印格式的变化,以便更好地处理基于行的输入。 You can futz with the format string to your heart's content. 您可以将格式字符串添加到您的心脏内容中。

I note that in theory you could play around with a complex fscanf() format string such as this, which assumes that MAXSIZE is 128: 我注意到,从理论上讲,您可以使用复杂的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)

but the error recovery doesn't bear thinking about. 但是错误恢复是不用考虑的。 If you're even the remotest bit tempted to use such a monstrosity, you should read the Beginnner's Guide Away From scanf() . 如果您甚至不愿意使用这种怪物,都应该阅读scanf()的《初学者指南》

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM