1

So i have been using this function for codechef problems for quite some while now as a fast input method for integers.

My question is how this actually works,what is fgetc_unlocked(stdin) (even though its commented) and most importantly how can I optimise it to run for long and long long.

Here is the code:

inline void Scan_f(int a)
{
char c = 0;
while(c<33)//shouldn't value of c to compare be less than 9 as digit vary between 0 to 9?? 
//c = fgetc_unlocked(stdin);
c = getc(stdin);
a = 0;
while(c>33)
{
a = a*10 + c - '0';
//c = fgetc_unlocked(stdin);
c = getc(stdin);
}
Community
  • 1
  • 1
dannysood
  • 1,129
  • 3
  • 18
  • 36
  • 1
    Why `c>33` vs. maybe `while(c>' ')`? Why `char c = 0` vs. `int c = 0` – chux - Reinstate Monica Apr 07 '14 at 04:11
  • @chux thanks .. that explains one of the questions. I edited the comment in code so that it makes more sense to general reader. What about other questions? – dannysood Apr 07 '14 at 04:37
  • `fgetc_unlocked` is thread unsafe version of `getc`. If your program is guaranteedly single threaded this may offer some performance advantage. – oakad Apr 07 '14 at 05:16
  • 1
    @AndrewMedico '1' is 0x31, actually. 33 (decimal) is '!' and that `while()` basically skips leading ASCII control and `' '` chars. And the whole thing doesn't even try to validate that input chars are in the range `0..9` and just blindly assumes this. – Andrey Apr 07 '14 at 05:38
  • Oops, fail. That's what I get for not taking a few seconds to double-check the ASCII table. – nobody Apr 07 '14 at 17:55

1 Answers1

2

It looks to me as if the code should be:

inline unsigned long long Scan_f()
{
    int c;
    do
        c = fgetc(stdin);
    while ( (c < '0' || c > '9') && c != EOF );

    unsigned long long a = 0;
    while ( c >= '0' && c <= '9' )
    {
        a = a*10 + (c - '0');
        c = fgetc(stdin);
    }
    return a;
}

In the code you posted, a is a parameter passed by value, so it's unclear how the calling function will find out about your changes to a.

The fgetc_unlocked function is supposed to be a faster version of fgetc. It's a GNU extension.

It doesn't make sense for a to be a signed type, as your parsing can never retrieve a negative value.

This version does not check for overflow; if you want to handle that possibility then you'll need to add in a check before doing a = a*10.

Don't worry about efficiency in the c < '0' etc. sections, the compiler will generate the optimal code for you already. They can handle simple situations like this pretty well. Certainly it can check that faster than it can read characters from whatever your input stream is; the input stream speed will be the bottleneck.

M.M
  • 138,810
  • 21
  • 208
  • 365