Storing data in a program instead of in an external file
I have the part of the following C code that uses data from a file names WMM.COF and uses the data stored in the file to compute the magnetic field of the earth. The program works perfectly except I can't have the program access the external file; I want to have all of the data already stored in the program. I tried using a structure array to replicate the data and then put the array into a string but this causes an error in the program and doesn't produce the correct results. Here is the code of the program that I'm trying to modify.
static void E0000(int IENTRY, int *maxdeg, double alt, double glat, double glon, double time, double *dec, double *dip, double *ti, double *gv)
{
static int maxord,i,icomp,n,m,j,D1,D2,D3,D4;
static double c[13][13],cd[13][13],tc[13][13],dp[13][13],snorm[169],
sp[13],cp[13],fn[13],fm[13],pp[13],k[13][13],pi,dtr,a,b,re,
a2,b2,c2,a4,b4,c4,epoch,gnm,hnm,dgnm,dhnm,flnmj,otime,oalt,
olat,olon,dt,rlon,rlat,srlon,srlat,crlon,crlat,srlat2,
crlat2,q,q1,q2,ct,st,r2,r,d,ca,sa,aor,ar,br,bt,bp,bpp,
par,temp1,temp2,parp,bx,by,bz,bh;
static char model[20], c_str[81], c_new[5];
static double *p = snorm;
char answer;
FILE *wmmdat;
wmmdat = fopen("WMM.COF","r");
/* INITIALIZE CONSTANTS */
maxord = *maxdeg;
sp[0] = 0.0;
cp[0] = *p = pp[0] = 1.0;
dp[0][0] = 0.0;
a = 6378.137;
b = 6356.7523142;
re = 6371.2;
a2 = a*a;
b2 = b*b;
c2 = a2-b2;
a4 = a2*a2;
b4 = b2*b2;
c4 = a4 - b4;
/* READ WORLD MAGNETIC MODEL SPHERICAL HARMONIC COEFFICIENTS */
c[0][0] = 0.0;
cd[0][0] = 0.0;
fgets(c_str, 80, wmmdat);
S3:
if (fgets(c_str, 80, wmmdat) == NULL) goto S4;
/* CHECK FOR LAST LINE IN FILE */
for (i=0; i<4 && (c_str[i] != '\0'); i++)
{
c_new[i] = c_str[i];
c_new[i+1] = '\0';
}
icomp = strcmp("9999", c_new);
if (icomp == 0) goto S4;
/* END OF FILE NOT ENCOUNTERED, GET VALUES */
sscanf(c_str,"%d%d%lf%lf%lf%lf",&n,&m,&gnm,&hnm,&dgnm,&dhnm);
if (n &开发者_如何学Cgt; maxord) goto S4;
if (m > n || m < 0.0)
{
fprintf(stderr, "Corrupt record in model file WMM.COF\n");
exit(1);
}
if (m <= n)
{
c[m][n] = gnm;
cd[m][n] = dgnm;
if (m != 0)
{
c[n][m-1] = hnm;
cd[n][m-1] = dhnm;
}
}
goto S3;
/* CONVERT SCHMIDT NORMALIZED GAUSS COEFFICIENTS TO UNNORMALIZED */
S4:
*snorm = 1.0;
fm[0] = 0.0;
for (n=1; n<=maxord; n++)
{
*(snorm+n) = *(snorm+n-1)*(double)(2*n-1)/(double)n;
j = 2;
for (m=0,D1=1,D2=(n-m+D1)/D1; D2>0; D2--,m+=D1)
{
k[m][n] = (double)(((n-1)*(n-1))-(m*m))/(double)((2*n-1)*(2*n-3));
if (m > 0)
{
flnmj = (double)((n-m+1)*j)/(double)(n+m);
*(snorm+n+m*13) = *(snorm+n+(m-1)*13)*sqrt(flnmj);
j = 1;
c[n][m-1] = *(snorm+n+m*13)*c[n][m-1];
cd[n][m-1] = *(snorm+n+m*13)*cd[n][m-1];
}
c[m][n] = *(snorm+n+m*13)*c[m][n];
cd[m][n] = *(snorm+n+m*13)*cd[m][n];
}
fn[n] = (double)(n+1);
fm[n] = (double)n;
}
k[1][1] = 0.0;
otime = oalt = olat = olon = -1000.0;
fclose(wmmdat);
return;
The code that I came up with to include the data in the program is as follows:
struct wmm
{
int alpha;
int beta;
float gamma;
float delta;
float epsilon;
float zeta;
}book[90]= {{1, 0, -29496.6, 0.0, 11.6, 0.0},
{1, 1, -1586.3, 4944.4, 16.5, -25.9},
{2, 0, -2396.6, 0.0, -12.1, 0.0},
{2, 1, 3026.1, -2707.7, -4.4, -22.5},
{2, 2, 1668.6, -576.1, 1.9, -11.8},
{3, 0, 1340.1, 0.0, 0.4, 0.0},
/* 50+ similar lines of code */
{12, 8, -0.4, 0.1, 0.0, 0.0},
{12, 9, -0.4, 0.3, 0.0, 0.0},
{12, 10, 0.2, -0.9, 0.0, 0.0},
{12, 11, -0.8, -0.2, -0.1, 0.0},
{12, 12, 0.0, 0.9, 0.1, 0.0}};
for (i = 0; i < 90 && offset < buf_size; i++)
{
offset += snprintf(c_str + offset,buf_size - offset, "%d %d %7.1lf %7.1lf %7.1lf %7.1lf \n", book[i].alpha, book[i].beta , book[i].gamma , book[i].delta, book[i].epsilon, book[i].zeta);
}
sscanf(c_str,"%d%d%lf%lf%lf%lf",&n,&m,&gnm,&hnm,&dgnm,&dhnm);
The problem is the snprintf causes the program to freeze and terminate every time it is placed in the program. When the code that I wrote is run on it's own it seems to create c_str properly except when I try to view the variables n,m,gnm,hnm,dgnm, and dhnm only a single value for each is displayed.
I need to continue in an answer due to a lack of space/formatting in a comment.
First of all, you do have 90 entries but you can let the compiler figure out how many entries the book
array needs:
struct wmm {
int alpha;
int beta;
float gamma;
float delta;
float epsilon;
float zeta;
} book[] = {
{1, 0, -29496.6, 0.0, 11.6, 0.0},
{1, 1, -1586.3, 4944.4, 16.5, -25.9},
/* ... */
{12, 12, 0.0, 0.9, 0.1, 0.0}
};
And, more importantly, you don't need to put them in a string and pull them back out when you already have them on hand:
for(i = 0; i < sizeof(book)/sizeof(book[0]); ++i) {
n = book[i].alpha;
m = book[i].beta;
gnm = book[i].gamma;
hnm = book[i].delta;
dgnm = book[i].epsilon;
dhnm = book[i].zeta;
/* Do whatever you need to do with the above variables. */
}
This will neatly side step whatever buffer overflow you were causing with your snprintf
.
Your c_str
is only a char[81]
and you're going through your loop 90 times and incrementing your offset into c_str
each time; so, you'll run off the end of c_str
before long and then you'll tell snprintf
to scribble all over unallocated memory. Hence your segfault.
精彩评论