Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to scanf a float followed immediately by the letter 'e' in c?

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
like image 534
user2093696 Avatar asked Mar 18 '16 14:03

user2093696


People also ask

What is the scanf for float in C?

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

What does %n do in C?

%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.

What is the use of sscanf in C?

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.

What does scanf %D mean?

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.


2 Answers

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); 
  ...
}
like image 85
chux - Reinstate Monica Avatar answered Oct 01 '22 03:10

chux - Reinstate Monica


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.

like image 29
Some programmer dude Avatar answered Oct 01 '22 04:10

Some programmer dude