You are not logged in.
In c is there a library to make standard integers (and vice versa) for storing in a file that may be used on different machines
It would also be nice to do this with floats as well, and to support variable widths
If anyone knows something that can point me in the right direction that would be very helpful
Last edited by BennyBolton (2013-03-09 09:58:12)
HP DV6 + Arch + Openbox
Offline
What do you mean by standard integers? int is a basic data type, so is float. stdio.h includes functions to read and write files.
What are you trying to do - I must be really misunderstanding this question as it seems to trivial.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
I'm a little confused by your needs... How about write the integers as plain text, then read them back in like this:
scanf("%d", &num);
Offline
I may have phrased it badly. I want some standard of interger and float that is independent of the current implementation, so that if I read/write it on another computer, it doesn't end up as some other number
HP DV6 + Arch + Openbox
Offline
I'm a little confused by your needs... How about write the integers as plain text, then read them back in like this:
scanf("%d", &num);
I would prefer them be in binary format
HP DV6 + Arch + Openbox
Offline
What do you mean independent of implementation? Especially if you want it in binary (use read, instead of scanf), then it has to be coded in some way. Is there some way you want the number coded into binary other than a straight writting of the bits to the file? Binary is not dependent on implementation.
Last edited by Trilby (2013-03-09 03:02:49)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
What do you mean independent of implementation? Especially if you want it in binary (use read, instead of scanf), then it has to be coded in some way. Is there some way you want the number coded into binary other than a straight writting of the bits to the file?
I want them written in binary, but a standard way, doesn't matter which way, so long as it can be read the same way on a different implementation (different endianness, architecture, etc)
HP DV6 + Arch + Openbox
Offline
What is wrong with read and write from stdio.h?
Last edited by Trilby (2013-03-09 03:21:36)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
What is wrong with read and write from stdio.h?
Depending on the system, the bytes in the numbers may be ordered differently. This is not standard in c
HP DV6 + Arch + Openbox
Offline
I found http://techforb.blogspot.co.nz/2007/10/ … ndian.html which will help with integers, but still looking for floats
HP DV6 + Arch + Openbox
Offline
Ok i've written my own library now
It doesn't give the number back, it writes it to a stream (why i wanted it)
Unsigned and signed ints work perfectly. Both big endian with signed being twos complement (haven't tested writting/loading as other but should work)
Floats are my own standard, i just load two signed ints (exponent and significand). Unfortunaly there is a loss a precision with this (test results below)
0.12345678901234567890 # this is the number i tested with
Double 0.12345678901234567737 8 bytes # this is the number as double
Float 0.12345679104328155518 4 bytes # this is the number as float
# I wrote then read the number for the sizes below (2-8 bytes)
Found 0.12304687500000000000 2 bytes at 0 # Expectedly crap precision
Found 0.12345504760742187500 3 bytes at 2 # Same
Found 0.12345677614212036133 4 bytes at 5 # Float size precision. The numbers are very similar
Found 0.12345677614212036133 5 bytes at 9 # same precision as 4 bytes (exponent increased to 2 bytes)
Found 0.12345678900601342320 6 bytes at 14
Found 0.12345678901215251244 7 bytes at 20
Found 0.12345678901234524716 8 bytes at 27 # same precision as double. The number is still pretty accurate but a couple significant figures of precision lost
Heres the code:
int bstream_getint(bstream *stream,bstream_int *num,int size){
bstream_byte buf[BSTREAM_SIZE_MAX];
int i,n;
if(!stream || !num){
return 0;
}
if(size<1){
size=1;
}
if(size>BSTREAM_SIZE_MAX){
size=BSTREAM_SIZE_MAX;
}
if(bstream_read(stream,buf,size,1)!=1){
return 0;
}
n=0;
if(buf[0]&128){
n=1;
}
buf[0]&=127;
num[0]=0;
for(i=0;i<size;i++){
num[0]<<=8;
num[0]+=buf[i];
}
if(n){
num[0]-=(((bstream_uint)1)<<((size<<3)-1));
}
return 1;
}
int bstream_putint(bstream *stream,bstream_int num,int size){
bstream_byte buf[BSTREAM_SIZE_MAX];
int i,n;
if(!stream){
return 0;
}
if(size<1){
size=1;
}
if(size>BSTREAM_SIZE_MAX){
size=BSTREAM_SIZE_MAX;
}
n=0;
if(num<0){
n=1;
num+=(((bstream_uint)1)<<((size<<3)-1));
}
for(i=size-1;i>=0;i--){
buf[i]=(num%256);
num>>=8;
}
if(n){
buf[0]|=128;
} else {
buf[0]&=127;
}
return bstream_write(stream,buf,size,1);
}
int bstream_getuint(bstream *stream,bstream_uint *num,int size){
bstream_byte buf[BSTREAM_SIZE_MAX];
int i;
if(!stream || !num){
return 0;
}
if(size<1){
size=1;
}
if(size>BSTREAM_SIZE_MAX){
size=BSTREAM_SIZE_MAX;
}
if(bstream_read(stream,buf,size,1)!=1){
return 0;
}
num[0]=0;
for(i=0;i<size;i++){
num[0]<<=8;
num[0]+=buf[i];
}
return 1;
}
int bstream_putuint(bstream *stream,bstream_uint num,int size){
bstream_byte buf[BSTREAM_SIZE_MAX];
int i;
if(!stream){
return 0;
}
if(size<1){
size=1;
}
if(size>BSTREAM_SIZE_MAX){
size=BSTREAM_SIZE_MAX;
}
for(i=size-1;i>=0;i--){
buf[i]=(num%256);
num>>=8;
}
return bstream_write(stream,buf,size,1);
}
int bstream_getfloat(bstream *stream,bstream_float *num,int size){
int i,xb,expb;
bstream_int x,exp;
if(!stream || !num){
return 0;
}
if(size<2){
size=2;
}
if(size>BSTREAM_SIZE_MAX){
size=BSTREAM_SIZE_MAX;
}
expb=size/5+1;
xb=size-expb;
if(!bstream_getint(stream,&exp,expb) || !bstream_getint(stream,&x,xb)){
return 0;
}
xb<<=3;
xb--;
num[0]=ldexp(x/(double)(((bstream_uint)1)<<xb),exp);
return 1;
}
static bstream_int _limitnum(bstream_int n,bstream_int size){
size<<=3;
size--;
size=((bstream_int)1)<<size;
if(n>=size-1){
return size-1;
}
if(n<-size){
return -size;
}
return n;
}
int bstream_putfloat(bstream *stream,bstream_float num,int size){
int i,xb,expb;
bstream_int x;
int exp;
if(!stream){
return 0;
}
if(size<2){
size=2;
}
if(size>BSTREAM_SIZE_MAX){
size=BSTREAM_SIZE_MAX;
}
expb=size/5+1;
xb=(size-expb)<<3;
xb--;
x=((double)(((bstream_uint)1)<<xb))*frexp(num,&exp);
exp=_limitnum(exp,expb);
x=_limitnum(x,size-expb);
if(!bstream_putint(stream,exp,expb) || !bstream_putint(stream,x,size-expb)){
return 0;
}
return 1;
}
FYI: bstream_int and bstream_uint are typedefs for long int signed and unsigned respectively, and bstream_float is a double
Edit: Also, BSTREAM_SIZE_MAX is 8, size in the function definition is size to read/write in bytes 1-8, floats can write 2-8
Edit2: Apparently my system is little endian, so i guess this works fine
Last edited by BennyBolton (2013-03-09 10:18:43)
HP DV6 + Arch + Openbox
Offline
FYI I think Glib has such standardized numerical types. It also has a million other things, though, so it might be more than what you need.
That said, this seems like one of those things that is reinvented in every large-scale C project.
Offline
I looks like the glib numeric types just typedef c numeric types. there int8, int16, etc types don't mention endianess but i assume there typedefs of types in stdint.h, Might you be mentioning extra functions in glib?
Last edited by BennyBolton (2013-03-09 10:27:46)
HP DV6 + Arch + Openbox
Offline
If you are only worried about endianess, you could just use ntohl/htonl, ntohs/htons.
You still need float unpacking for machines that don't support the network type (which you decide).
The stuff gets trickier, if the datatypes differ in size.
In these cases it's usually easiest to just serialize as string and read back.
Though, I think there was library that does all this already. I just don't remember the name right now.
EDIT:
It was this: http://hookatooka.com/poshlib/
EDIT2:
You also might want to look at: http://koti.kapsi.fi/jpa/nanopb/
Last edited by Cloudef (2013-03-09 12:37:21)
Offline
It doesn't give the number back, it writes it to a stream (why i wanted it)
Awww, you waited until the end to tell us what you actually wanted?
Offline
If you are only worried about endianess, you could just use ntohl/htonl, ntohs/htons.
You still need float unpacking for machines that don't support the network type (which you decide).The stuff gets trickier, if the datatypes differ in size.
In these cases it's usually easiest to just serialize as string and read back.Though, I think there was library that does all this already. I just don't remember the name right now.
EDIT:
It was this: http://hookatooka.com/poshlib/EDIT2:
You also might want to look at: http://koti.kapsi.fi/jpa/nanopb/
endianess is first thing i worry about but my code should also work with one's complement and sign/magnitude, but i haven't tested these. Also float storing splits the float into significand and exponent, multiplies/divides the significand to make an int (this is where precision is lost) and stores them as two signed integers. Its not the nicest way to do it but im happy for now. I cant see how this wouldn't work on systems with other float representations, but i'll still test it.
HP DV6 + Arch + Openbox
Offline