### xsc's blog

By xsc, history, 7 years ago,

I decided to rewrite this post, previously has been deleted.

I know there a many of posts low-level i/o.

scanf/printf solves slowly i/o, partially, but not always.

Most generic usage i/o — is read and write integers, so I'll write about it without a hundred lines of source code.

For simplicity, all input file content loaded to a big buffer, and it will be parsed.

char in[1<<23] ; // a big buffer
char const* o ; // pointer to buffer.


And for detecting end of buffer, put '\0' — terminating symbol to end of buffer ( as plain c-string).

void load(){  o = in;   in [   fread(in,  1,  sizeof(in ) - 4 ,  stdin ) ] = 0; }


fread - returns number of reading symbols, we just use this for put '\0' terminating symbol to end of buffer.

unsigned readUInt(){
unsigned u = 0;

while( *o && *o <= 32) ++o ; //  skip spaces

while ( *o >='0' && *o <='9') u = (u << 3) + (u << 1) + (*o++ -'0');
return u;
}


By default most implementations used u = u * 10 + (*o++ - '0'),
but u * 10 = u * 8 + u * 2 = (u << 3) + (u <<1) I don't know it gives speed, but with shifting the code become happy :)

Some theory of signed integer representation, in most situation see here

-u == ~u + 1

There ~ — bitwise inverting.

And ~u == u ^ 0xFFFFFFFF or ~u == u ^ ~0

Let start writing method

    int readInt()
{
unsigned u = 0, s = 0; // s = 0, if integer positive, s = ~0 - if integer negative
while(*o && *o <= 32)++o; // skip spaces

if (*o == '-')s = ~0, ++o; else if (*o == '+') ++o; // determine sign
while( *o >='0' && *o <= '9') u = (u << 3) + (u << 1) + (*o ++ - '0');

return (u^s) + !!s; // ??????? : s = 0 :  (u^s) + !!s = (u^0) + !!0 = u + 0 = u, and
//           s = ~0:  (u^s) + !!s = (u ^ ~0) + !! ~0 = (u^0xFFFFFFFF) + 1 = ~u + 1 = -u

}


How to use this complete?

#include <cstdio>

char const * o;
char in[1<<23];

void load(){ o = in ;  in [ fread(in,1,sizeof(in)-4,stdin)] = 0; }
unsigned u = 0;
while(*o && *o <= 32)++o;
while(*o >='0' && *o <='9') u = (u << 3) + (u << 1) + (*o++ -'0');
return u;
}
unsigned u = 0, s = 0;
while(*o && *o <= 32)++o;
if (*o == '-') s = ~0, ++o; else if(*o == '+') ++o;
while(*o >='0' && *o <='9') u = (u << 3) + (u << 1) + (*o++ - '0');

return (u ^ s) + !!s;
}

int main()
{
int s = 0;
for(int i= 0; i < n; ++i)s += readInt();

printf("summa = %d\n", s);

return 0;
}


Compare low-level i/o: 24139587 with std::cin , std::cout 24133798

## for competetive programming this single method is enough for reading integers:

   typedef long long ll;
typedef unsigned long long ull;

ull u = 0 , s = 0;
while(*o && *o <= 32)++o;
if (*o == '-') s = ~s, ++o; else if (*o == '+') ++o;
while(*o >='0' && *o<='9') u = (u << 3) + (u << 1) + (*o++ -'0');

return (u ^ s) +!!s;
}


# 2. Writing integers.

There are need a big buffer and pointer, again.

typedef long long ll;
char out[1<<23];
char * w = out; // initialize with &out[0] - beginning of the buffer.


There a single writeInt method, arguments: integer u and serarator c .

// need to implement this method.
void writeInt( ll u, char separator); // u - integer, separator - will printed after the integer, most situations is space, or '\n'.


AND flush method, which we must call at the end of all operations.

// flush - must be called before end of program.
void flush(){  fwrite(out, 1, w - out, stdout); }


For implementing writeInt need temporary buffer :

void writeInt(ll u, char separator)
{
char tmpbuf[20]; int i;
if ( u < 0 ){ *w ++ = '-'; u = - u ; }
i = 20;
do tmpbuf[--i] = u % 10 + '0'; while(u/=10); // write last digits of u to tmpbuf from end to begin.

// now write tmpbuf to out[] buffer from w pointer.
do *w++ = tmpbuf[i++]; while(i < 20);

// and separator
*w++ = separator;
}


It's all.

------------------------------------------------------------------------------------------------------

# UPD: Wrapper classes.

Let simplify all above codes.

typedef long long ll;
typedef unsigned long long ull;

char in[1<<23];
char out[1<<23];

struct scanner
{
char const* o;
void load(){ in[ fread(in , 1, sizeof(in)- 4, stdin)] = 0; }
ull u = 0, s = 0;
while(*o && *o <= 32)++o;
if (*o == '-')s = ~s, ++o; else if (*o == '+')++o;
while(*o >='0' && *o <='9') u = (u << 3) + (u << 1) + (*o++ - '0');
return (u^s) + !!s;
}
};

//wrapper to writer
struct writer
{
char * w;
writer(): w(out){}
~writer(){ flush();}
void flush(){ if (w!=out){ fwrite(out,1,w-out,stdout); w = out; } }
void writeInt(ll u, char c){
char t[20]; int i = 20;
if (u < 0){ *w++ = '-'; u = -u;}
do t[--i] = u % 10 + '0'; while(u/=10);
do *w++ = t[i++]; while(i < 20);
*w++ = c;
}
};

//A+B
int main()
{
scanner sc;
writer pw;
}


# UPD-2 Reverse-Writer

Sometimes, needed restore answer from end to begin, for example shortest path in graph from source to target. Most solution is save answer to array, vector, and reverse it and print. But there exists another solution with reverse-writer.

Reverse-writer -is simple writes numbers to array from end to begin in reverse order.

Let code it

typedef long long ll;
typedef unsigned long long ull;

char out[1<<23];

struct reverse_writer
{
char * w;
reverse_writer(): w( out + sizeof(out) ){} // w - indicated end of  out[] array
~reverse_writer(){ flush(); }
void flush(){
if (w != out + sizeof(out) )
fwrite(w, 1, out + sizeof(out) - w, stdout), w = out + sizeof(out);
}

void writeInt(ll u, char c){
*--w = c; // print separator at first
(u < 0) ? (u = -u, c ='-') : c = '\0' ; // determine sign
do *--w = u%10 + '0'; while(u/=10); // put digits
if(c)   *--w= c ;// write sign
}
};

// USAGE:

vi g[maxn];
int parent[maxn];
int n,m,source, target;
int main()
{
scanner sc;
reverse_writer pw;

for(int i= 0; i<m;++i){
g[a].push_back(b); g[b].push_back(a);
}

memset(parent, -1, sizeof(parent));
dejkstra(source, target);

int total = 0;  char c = '\n';
for(int i = target ; i != -1; i = parent[i], ++total)
pw.writeInt( i , c), c = ' ';
pw.writeInt(total, '\n');
}


GOoD lUck!

• +33

 » 7 years ago, # |   0 Auto comment: topic has been updated by xsc (previous revision, new revision, compare).
 » 7 years ago, # |   0 Auto comment: topic has been updated by xsc (previous revision, new revision, compare).
 » 7 years ago, # |   0 This looks pretty simple to code from scratch.Also, you have to take a look at this. It's based on the same idea, but has nicer interface. Unofortunately, not all the competiotions allow prewritter code.
•  » » 7 years ago, # ^ |   0 http://ideone.com/X1tP8Q nice interface with 500 lines code.
•  » » » 7 years ago, # ^ |   0 Yes, that's one of the disadvantages :)
 » 7 years ago, # |   0 Auto comment: topic has been updated by xsc (previous revision, new revision, compare).
 » 7 years ago, # |   0 Auto comment: topic has been updated by xsc (previous revision, new revision, compare).
 » 7 years ago, # |   0 The integer arithmetic "optimizations" are not necessary. The compiler will convert multiplication by 10 into a shift-add instruction for you, for instance.
•  » » 7 years ago, # ^ | ← Rev. 2 →   0 Thx. I have testes (u<<3) + (u<<1) it uses two registers, so I'll use u*10 anywhere.