I have a problem:
I am doing a cast by using memcpy (in C) and storing a double variable inside a char buffer. What I want to do is convert back the char inside the buffer into my initial variable (double). If I convert each location of the buffer, I obtain the conversion of the ASCII character, not the true value of the variable
I post my code in order to clear better my problem:
int counter = 1;
double pippo = 100.0;
const int cPacketSizeInBytes = 40;
char packet[cPacketSizeInBytes];
do
{
.....;
.....;
memcpy(&packet[32], (char*)&pippo, sizeof(double));
serverSocket.Send((char*)&packet, cPacketSizeInBytes);
pippo += 3.0;
if ( pippo > 180.0 ) pippo = 0.0;
counter++;
if(!(counter%100))
{
printf("Pippo value (double) is : %f\n", pippo);
for (int i = 32; i < 40; i ++) {
printf("%c\n", packet[i]);
double x = (double)packet[i];
printf("%f\n", x);
}
}
}
x is the double conversion of the ASCII character in packet[i]..
How can I merge all the character inside packet (i.e., packet[32....39]) to obtain back the value of pippo?
Be wary that when you send something on a socket, the endianess is something you have to take into account, otherwise you can end up with the wrong value.
I propose you to use function like "htonl", "ntohl", because such function are designed to do that.
Edit : And your memcpy suppose that your double is 4 octet, so mainly an x32 bit machine. If your code is run on x64 architecture, it will fail, I think. Sorry ! It was wrong.
Related
In c language,
for example:
if value double x = 3.4900
I want output be 3.4900, not 3.490000
The problem is the input value x is changeable, I don't how many decimal point will be.
any idea?
to make an answer:
double x = 3.4900;
printf("the value of x is %.4f",x);
.4 means, you print the value with for digits after the dot. If you want to print exact and changeable number of digits you read in, you had to work with a string.
double x = 3.4900; is exactly the same as double x = 3.49;
When you ask about "input", you might mean "reading a value as a string from a file or stdin"... You could count the digits to the right of the decimal point and store that count in another variable.
Once that string is converted to double, there is no record of how much 'precision' was supplied by the source.
And, because floats and doubles use base-2 numbers (not base-10), it is extremely rare that the internal representation matches the base-10 version (without some rounding involved.)
Note in the following the 'extra effort' to determine the precision from the pseudo-input string...
int main() {
char *s1 = "3.4900";
char *s2 = "3.49";
double d1 = strtod( s1, NULL );
double d2 = strtod( s2, NULL );
printf( "%s\n", d1 == d2 ? "Same" : "Diff!!" );
char *cp = strchr( s1, '.' ) + 1;
int prec = strlen( s1 ) - (cp - s1);
printf( "s1 restores as %.*lf\n", prec, d1 );
return 0;
}
any idea?
C programming language does not have reflection - it's not possible to inspect itself. If you want to have the ability to inspect the source code of a C program from that C program itself, you have to implement such functionality yourself.
how to print double exactly as input in C
You have to include verbatim the stringifed form of the input inside your source code and print that.
double x = 3.4900;
const char *xstr = "3.4900";
printf("source code %s was translated into %f\n", xstr, x);
With the help of # preprocessor operator, we could make it a bit nicer and don't repeat ourselves:
struct double_and_string {
double x;
const char *str;
};
#define VAL_AND_STR(x) { x, #x }
struct double_and_string a = VAL_AND_STR(3.4900);
printf("source code %s was translated into %f\n", a.str, a.x);
double x = 3.4900;
printf("the value of x is %lf",x);
I am trying to write a bunch of files by iterating, doing some calculations and adding the index to the file's name, heres part of my code (I emphasized where the code stops compiling):
float AltAzCalc(int d, float t, float Lon, float RA, float Dec, float Lat){
FILE *in;
-----> char filename[30] = ("hiparcos_horizontal_%lf_%lf.csv",Lon,Lat);
in = fopen(filename, "w");
float PI = 3.14159265;// pi
float G = 6.5949997;
float Alt , Az;
float GST = G + 0.0657098244*d + 1.00273791*t;
if (GST > 24){
GST = GST - 24;
}
float LST = GST*360/24 + Lon;
Alt = (180/PI)*(asin(sin(PI*Dec/180)*sin(PI*Lat/180) + cos(PI*Dec/180)*cos(PI*Lat/180)*cos(PI*(LST-RA*360/24)/180)));
if(sin(PI*(LST-RA*360/24)/180) <= 0){
Az = (180/PI)*(acos((sin(PI*Dec/180)-(sin(PI*Alt/180)*sin(PI*Lat/180)))/(cos(PI*Alt/180)*cos(PI*Lat/180))));
}else{
Az = 360 - (180/PI)*(acos((sin(PI*Dec/180)-(sin(PI*Alt/180)*sin(PI*Lat/180)))/(cos(PI*Alt/180)*cos(PI*Lat/180))));
}
fprintf(in," %lf %lf \n",Alt,Az);
}
int main{
for(int i = -180 ; i < 181 ; i++){
for(int j = -180 ; j < 181 ; j++){
for(int k = 0; k < 119616 ; k++){
AltAzCalc(97,9.2,i,AscensionRecta.array[k],Declinacion.array[k],j);
}
}
}
}
I have used such syntaxes before only not adding any extra numbers that I want to change, which is a string literal and that's what its asking for, any idea how to fix this?
Two major things:
char filename[30] is probably too small in dimension to hold the name.
You need to use sprintf()/snprintf() to generate the filename.
Worthy to mention, %f is enough and recommended to print a float value.
Do something like (pseudo-code)
char filename[128] = {0}; //allocate enough memory
sprintf(filename, "hiparcos_horizontal_%f_%f.csv",Lon,Lat)); //Added missing semi-colon // use %f, that's enough and recommended, too.
Note: Always check the return value of fopen() for success before using the returned file pointer.
If you want a formatted string, use snprintf:
char filename[30];
snprintf(filename, sizeof filename, "hiparcos_horizontal_%f_%f.csv", Lon, Lat);
And %f instead of %lf to print a float.
Also note (as pointed out by #SouravGhosh) that [30] is too small to hild the entire filename.
What you have here it a comma-expression enclosed in parentheses. It contains three subexpressions—a string and two float variables—which are 'calculated' in odrer from left to right, then the result of the last subexpression becomes the result of the whole paren. Thus a result (value in this case) of a string and Lon variable remain unused, as compiler said. Then the result of Lat is inappropriate to initialize a char array.
The compiler has no idea you want a formatted string, you need to write it explicitly, as others said: first you need to prepare a buffer long enough for your file name:
char filename[66];
then fill it with data:
sprintf(filename, "hiparcos_horizontal_%lf_%lf.csv", Lon, Lat);
The formatting string itself contains 25 plain characters. Assuming both Lon and Lat will convert to no more than 20 characters each (but verify that with the sprintf description!) the total file name should not exceed 65 characters. Add one for the NUL terminator and you have the size of 66 in a declaration.
Oh, and don't forget to fclose a file once you finished writing to it!
I am trying to code a function that converts a double into a string (a sort of dtoa function). I don't want to use any of the standard library that will do all the job for me (itoa is ok, strlen too, because I can code them on my own).
My main idea was to extract the integer part, doing something like this:
/* Let's suppose that str is ok, and d > 0 */
/* Let's also suppose that we don't need to round the result */
/* Let's finally suppose that precision is greater than 0 */
char *dtoa(double d, int precision, char *str)
{
int int_part;
size_t i, len;
char *temp;
int decimals;
if (str == NULL)
return (NULL);
int_part = (int)d;
temp = itoa(int_part);
i = 0;
len = strlen(temp);
while (i < len)
{
str[i] = temp[i];
i++;
}
d -= (double)int_part;
str[i] = '.';
i++;
decimals = 0;
while (decimals < precision)
{
d *= 10;
int_part = (int)d;
str[i] = int_part + '0';
i++;
decimals++;
d -= (double)int_part;
}
return (str);
}
That function doesn't work so bad. I think I am a little bit stupid, because I could extract several decimal numbers instead of extracing them one by one. But, even when I tried this other method, I had a problem.
Actually, when I do this, it works for a lot of double. But, for some of them, I am losing precision. For example, when I try with 1.42, I have 1.4199 as result.
My question is: is there an easy way to solve this problem, or do I need to change all the conversion method? A few years ago, I learned about how the floating point numbers where coded (using the IEE-754 representation) but I would like to avoid me to create a sort of IEE-754 converter.
Thanks for your help!
Edit: This is just an exercice, I'm not going to send a rocket to Mars with this function (the astronauts are grateful).
Edit2: It looks like 1.42 is not a "correct" double. But, in that case, why does this work fine?
printf("Number: %lf\n", 1.42);
Im sorry but im just learning c, probably its easy to fix but i dont know how
In the code i just have 1 printf but in the terminal shows the same question 2 times. But finally the result is correct.
#include <stdio.h>
#include <math.h>
double lfDemanaTaxa(){
double i;
double d;
printf("Quant es la taxa interes nominal?\n");
scanf("%lf",&i);
d = i/100;
return d;
}
double lfDemanaMensualitat(){
double n;
scanf("%lf",&n);
return n;
}
int main(){
double a,b,c,TAE;
a = (1+lfDemanaTaxa()/lfDemanaMensualitat());
b = pow(a,lfDemanaMensualitat());
c = b -1;
TAE = c * 100;
printf("El TAE total es %.2lf%% \n", TAE);
return 0;
}
You call the lfDemanaMensualitat() function twice, and it does one call to printf(), so of course you're going to have two print-outs.
If you wanted to only call it once and store the value, you can something like this:
const double t = lfDemanaMensualitat();
const double a = (1 + lfDemanaTaxa()) / t;
const double b = pow(a, t);
And then compute c and TAE like you already do. This just saves the result of lfDemanaMensualitat() in a temporary variable called t.
By the way you should know that scanf() can fail, if the user enters things that don't match the specified conversion. You must check the return value to make sure it succeeded before relying on the input.
I am trying to write a bunch of files by iterating, doing some calculations and adding the index to the file's name, heres part of my code (I emphasized where the code stops compiling):
float AltAzCalc(int d, float t, float Lon, float RA, float Dec, float Lat){
FILE *in;
-----> char filename[30] = ("hiparcos_horizontal_%lf_%lf.csv",Lon,Lat);
in = fopen(filename, "w");
float PI = 3.14159265;// pi
float G = 6.5949997;
float Alt , Az;
float GST = G + 0.0657098244*d + 1.00273791*t;
if (GST > 24){
GST = GST - 24;
}
float LST = GST*360/24 + Lon;
Alt = (180/PI)*(asin(sin(PI*Dec/180)*sin(PI*Lat/180) + cos(PI*Dec/180)*cos(PI*Lat/180)*cos(PI*(LST-RA*360/24)/180)));
if(sin(PI*(LST-RA*360/24)/180) <= 0){
Az = (180/PI)*(acos((sin(PI*Dec/180)-(sin(PI*Alt/180)*sin(PI*Lat/180)))/(cos(PI*Alt/180)*cos(PI*Lat/180))));
}else{
Az = 360 - (180/PI)*(acos((sin(PI*Dec/180)-(sin(PI*Alt/180)*sin(PI*Lat/180)))/(cos(PI*Alt/180)*cos(PI*Lat/180))));
}
fprintf(in," %lf %lf \n",Alt,Az);
}
int main{
for(int i = -180 ; i < 181 ; i++){
for(int j = -180 ; j < 181 ; j++){
for(int k = 0; k < 119616 ; k++){
AltAzCalc(97,9.2,i,AscensionRecta.array[k],Declinacion.array[k],j);
}
}
}
}
I have used such syntaxes before only not adding any extra numbers that I want to change, which is a string literal and that's what its asking for, any idea how to fix this?
Two major things:
char filename[30] is probably too small in dimension to hold the name.
You need to use sprintf()/snprintf() to generate the filename.
Worthy to mention, %f is enough and recommended to print a float value.
Do something like (pseudo-code)
char filename[128] = {0}; //allocate enough memory
sprintf(filename, "hiparcos_horizontal_%f_%f.csv",Lon,Lat)); //Added missing semi-colon // use %f, that's enough and recommended, too.
Note: Always check the return value of fopen() for success before using the returned file pointer.
If you want a formatted string, use snprintf:
char filename[30];
snprintf(filename, sizeof filename, "hiparcos_horizontal_%f_%f.csv", Lon, Lat);
And %f instead of %lf to print a float.
Also note (as pointed out by #SouravGhosh) that [30] is too small to hild the entire filename.
What you have here it a comma-expression enclosed in parentheses. It contains three subexpressions—a string and two float variables—which are 'calculated' in odrer from left to right, then the result of the last subexpression becomes the result of the whole paren. Thus a result (value in this case) of a string and Lon variable remain unused, as compiler said. Then the result of Lat is inappropriate to initialize a char array.
The compiler has no idea you want a formatted string, you need to write it explicitly, as others said: first you need to prepare a buffer long enough for your file name:
char filename[66];
then fill it with data:
sprintf(filename, "hiparcos_horizontal_%lf_%lf.csv", Lon, Lat);
The formatting string itself contains 25 plain characters. Assuming both Lon and Lat will convert to no more than 20 characters each (but verify that with the sprintf description!) the total file name should not exceed 65 characters. Add one for the NUL terminator and you have the size of 66 in a declaration.
Oh, and don't forget to fclose a file once you finished writing to it!