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!
Related
Sorry, but I know how to do it in other languages, but C is rather new to me.
I need to import an ascii grid file in a C code. The structure of the file is as follows:
ncols 12
nrows 101
xllcorner 2.0830078125
yllcorner 39.35908297583665
cellsize 0.00439453125
nodata_value -2147483648
401.99 407.38 394.17 362.35 342.36 335.13 319.91 284.99 262.88 259.58 245.62 233.58
397.63 396.36 380.70 358.96 339.35 327.96 314.06 296.73 279.11 264.80 257.20 249.97
389.71 381.29 356.41 338.75 326.04 323.36 317.67 301.30 281.79 269.46 261.94 250.72
.....
I can read the bulk of values but I am struggling to properly import the first 6 lines in two arrays, a character one (namevar) and a double one (valvar).
My only partially working code is:
#define ny 101
#define nx 12
#define dime nx *ny
int main(void)
{
FILE *dem;
double Z[dime], varval[6];
char namevar[12];
int l = 1;
dem = fopen("buttami.txt", "r");
int i;
int j;
while (l < 7)
{
//
fscanf(dem, "%s %f\n", &namevar, &varval[l]);
printf("%s %.8f\n", namevar, varval[l]);
l++;
}
for (i = 1; i < dime; i++)
{
fscanf(dem, "%lf", &Z[i]);
printf("%.5f ", Z[i]);
printf("\n");
}
fclose(dem);
}
Comments address many issue, this focuses on your specific mention...
"I am struggling to properly import the first 6 lines in two arrays, a character one (namevar) and a double one (valvar)"
First, the variable char namevar[12]; is too small to contain the longest name string it will need to contain: "nodata_value" as stored in the file contains 12 characters requiring the variable namevar to be created with size of at least 13 to provide room for the null terminator. ( see definition of C string )
The top part of the input file could be thought of as a header section, and its content as tag/values. An array of struct is useful to store content of varying types into a single array, each containing a set of members to accommodate the various types, in this case one C string, and one double. For example:
#define NUM_HDR_FLDS 6 // to eliminate magic number '6' in code below
typedef struct {
char namevar[20];
double varval;
} header_s;
header_s header[NUM_HDR_FLDS] = {0};//array of NUM_HDR_FLDS elements, each contains two members,
//1 a char array with room for null terminator for field name
//2 a double to contain value
Then your fscanf() loop will look like this:
//note changes to format specifier and the
//string member needs no &
int l=0;//C uses zero base indexing
dem=fopen("buttami.txt", "r");
if(dem)//test for success before using
{
while(l<NUM_HDR_FLDS){//zero base indexing again (0-5)
if(fscanf(dem,"%s %lf", header[l].namevar,&header[l].varval) == 2)
{
printf("%s %.8f\n",header[l].namevar,header[l].varval);
} //else handle error
l++;
}
fclose(dem);
}
By your example data description, I guess it is Arc/Info Ascii Grid foramt by wikipedia https://en.wikipedia.org/wiki/Esri_grid.
For raster data files I/O, please try library Gdal.
Gdal doc about this format https://gdal.org/drivers/raster/aaigrid.html
Here is code samples for open and read a raster file https://gdal.org/tutorials/raster_api_tut.html
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 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.
I've been pouring over my code (which does not work) now for quite some time. It is for a Project Euler problem in which one is given a very large sum to find, and then required to print the first ten digits of said sum. (The problem can be found here: https://projecteuler.net/problem=13)
I have run several 'tests' where I add print commands to see various values at various points in the code. When I run the code, I have gotten anything from symbols to ten digit numbers that should be single digits.
Anyways. My question is this: is this a type conversion issue or is there some other glaring issue with my method that I'm missing? I've been studying type conversions trying to find a fix, but to no avail.
Thank you for any help!
The code is as follows:
// this is a program to find a very large sum of many very large numbers
#include <stdio.h>
#include <math.h>
int main()
{
//declare all ints needed
int i;
int j;
int d; // digit, need to add 48
int placesum; // sum of addition in _'s place (1's, 10's, 10000's)
int place; // final place value
int c = 0, tens = 1, otherc; // counters for start finder
int a = 0; // another counter
//declare all arrays
char numarray[101][51]; //array of strings containing all 100 numbers
char sum[100];
printf("please save data to largesumdata.txt\n\n press enter when ready");
getchar();
// THE PROBLEM- I don't know how to get my data into my program // FIXED
// using fscanf()
FILE *pf; // declare a pointer to the file
pf = fopen("largesumdata.txt", "r"); // trys to open file // "r" means read only
if(pf == NULL)
printf("Unable to open file, sorry Jar\n");
else
{
for(j = 0; j < 100; j++)
fscanf(pf, "%s\n", &numarray[j]); // fscanf(pointer, data type, location)
}
//TESTING
//printf("You have reached point A\n");//POINT A WAS REACHED
//TESTING
//TESTING
//printf("Check1, %c\n", numarray[45][23]);
//TESTING
//TESTING
//printf("%c\n", numarray[90][22]);//Can successfully call characters from array
//TESTING
// (Brute force attempt) //I NEVER MESS WITH numarray WHY IS IT CHANGING
for(i = 49; i >= 0; i--)
{
//printf("%d\n", d);
for(j = 0; j < 100; j++)
{
d = (int)numarray[j][i] - 'o';
//printf("%d\n", d);
//holdup// d -= 48; // ASCII conversion // could also write "d = d-48"
//printf("%d\n", d);
placesum += d; // could also write "placesum = placesum + d"
//printf("%d\n", placesum);
}
place = placesum % 10;
placesum = placesum / 10; // takes "10's place" digit for next column
// now need to put 'int place' into 'char sum'
sum[i+5] = (char)place+'0'; // ASCII conversion // "+5" for extra space //HERE not properly stored in sum
}
//TESTING
//printf("Check2, %c\n", numarray[45][23]);
//TESTING
//TESTING
//printf("You have reached point B\n");//POINT B WAS REACHED
//TESTING
// find out where sum starts
for(c=0; c<10; c++)
if(sum[c] != '0')
break;
//TESTING
//printf("You have reached point C\n"); //POINT C WAS REACHED
//TESTING
otherc = 4-c;
printf("The first 10 digits of the sum of all those f***ing numbers is....\n");
printf("%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", sum[otherc, otherc+1, otherc+2, otherc+3, otherc+4, otherc+5, otherc+6, otherc+7, otherc+8, otherc+9]);
//%c-%c-%c-%c-%c-%c-%c-%c-%c-%c //copy and paste purposes
//%d-%d-%d-%d-%d-%d-%d-%d-%d-%d // ^^^^^
getchar();
return 0;
}
P.S. I apologize if my plethora of notes is confusing
You are using wrong form to print an array in C.
sum[otherc, otherc+1, otherc+2, otherc+3, otherc+4, otherc+5, otherc+6, otherc+7, otherc+8, otherc+9] -> This actually decays to sum[otherc+9] because C treats , as an operator.
To print value at each array index, you should use it like this: sum[otherc], sum[otherc+1], sum[otherc+2],..
To read more about C's , (comma) operator, you can begin here
In your printf as I explained above, the first format specifier %d gets sum[otherc + 9], since sum[otherc,...,otherc+9] is actually a single number and that is otherc + 9th index of array sum. You do not provide anything to print for other format specifiers, hence you get garbage.
After a while I revisited my code, and realized that I was working with numbers upwards of 10 million. I had a mix of int, long int, and long long int variables declared.
I re-analyzed which was which, and made sure that all variables could handle the data it needed to (after looking at this handy link, showing what max integer sizes are for different data types.
Before I had been using the wrong ones, and going over the max values returned incorrect values, causing my program to crash during run time.
Lesson here: Check your data types!