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. 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()
.
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.
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. 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. 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; 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:
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()
.