I'm trying to use fscanf
to read in data, and part of the input is a float followed by the letter 'e'
, for example, 41.72elapsed
. When writing the strng for fscanf
, I attempted to use "%felapsed"
, but this doesn't work, as %fe
is its own format specifier. How would I read this in using fscanf
?
edit: Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define CHAR_MAX 1024
int main(int argc, char **argv)
{
FILE *file_in = fopen(argv[1], "r+");
char out_name[CHAR_MAX];
strcpy(out_name, argv[1]);
strcat(out_name, ".csv");
FILE *csv_out = fopen(out_name, "w");
int minutes;
float seconds;
fprintf(csv_out, "Trial #, Execution Time\n");
for (int i = 0; fscanf(file_in, "%*fuser %*fsystem %d:%felapsed %*d%%CPU (%*davgtest+%*davgdata %*dmaxresident)k\n%*dinputs+%*doutputs (%*dmajor+%*dminor)pagefaults %*dswaps\n", &minutes, &seconds) == 2; i++) {
fprintf(csv_out, "%d, %d:%.2f\n", i, minutes, seconds);
};
return 0;
}
Here is some sample input:
283.97user 0.69system 1:13.77elapsed 385%CPU (0avgtext+0avgdata 107472maxresident)k
0inputs+4616outputs (0major+9550minor)pagefaults 0swaps
287.87user 0.35system 1:14.41elapsed 387%CPU (0avgtext+0avgdata 107328maxresident)k
0inputs+4616outputs (0major+9524minor)pagefaults 0swaps
To scan a float value, %f is used as a format specifier. In C programming, scanf() is one of the commonly used functions to take input from the user. The scanf() function reads formatted input from the standard input such as keyboards. The simplest application of scanf looks like this: scanf ("%d", &b);
%n in scanf() in C with Example In C, %n is a special format specifier. In the case of printf() function the %n assign the number of characters printed by printf(). When we use the %n specifier in scanf() it will assign the number of characters read by the scanf() function until it occurs.
The sscanf() function reads data from buffer into the locations that are given by argument-list . Each argument must be a pointer to a variable with a type that corresponds to a type specifier in the format-string . The sscanf() function returns the number of fields that were successfully converted and assigned.
The “%d” in scanf allows the function to recognise user input as being of an integer data type, which matches the data type of our variable number. The ampersand (&) allows us to pass the address of variable number which is the place in memory where we store the information that scanf read.
This is a problem with scanf()
FP formats like "%f"
see the e
as introducing exponentiation. Since the e
is not followed by a number, scanning for the float
stops. But scanf()
has all ready scanned one past the e
and C does not require for scanf()
to be able to back up more than 1 character. So code is out-of-luck using a simple "%f"
.
Some systems will back up more than 1 character, but C does not require that capability.
Code needs a new approach - scan in seconds as a string
char sec[20];
int cnt = fscanf(file_in, "%d:%19[0-9. ]elapsed", &minutes, sec);
if (cnt == 2) {
seconds = atof(sec);
...
}
There's simply no need for the "elapsed"
in your format. The scanf
family of function will read as long as they can from the input, and for floating-point number it will stop reading when it hits a non-digit character, i.e. the e
in elapsed
.
So the format only needs to be "%f"
, and that's it. I.e.
float value;
fscanf(file, "%f", &value);
If you want to read and discard the elapsed
part, use "%*s"
, the asterisk tells scanf
(and family) to read and ignore the rest, so the full call would look like
float value;
fscanf(file, "%f%*s", &value);
After seeing your code, it can be much simpler and easier with something like
char input[512];
for (int i = 0; fgets(input, sizeof input, file_in) != NULL; ++i) {
if (sscanf(input, "%*f%*s %*f%*s %d:%f%*s", &minutes, &seconds) == 2) {
fprintf(csv_out, "%d, %d:%.2f\n", i, minutes, seconds);
}
}
Since this loop uses fgets
instead of direct fscanf
you will read all lines in the input file, not only just the first one. Also since fgets
is used we don't need the sscanf
function to actually parse the parts of the string we don't need (which is most of it), instead we only have sscanf
parse the input string until we have the data we need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With