Хранение данных в программе, а не во внешнем файле - PullRequest
0 голосов
/ 27 мая 2011

У меня есть часть следующего C кода, который использует данные из файла с именами WMM.COF и использует данные, хранящиеся в файле, для вычисления магнитного поля Земли. Программа работает отлично, за исключением того, что я не могу получить доступ к внешнему файлу; Я хочу, чтобы все данные уже сохранялись в программе. Я попытался использовать структурный массив для репликации данных, а затем поместить массив в строку, но это вызывает ошибку в программе и не дает правильных результатов. Вот код программы, которую я пытаюсь изменить.

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 > 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;

Код, который я предложил для включения данных в программу, выглядит следующим образом:

    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);  

Проблема в том, что snprintf заставляет программу зависать и завершать работу каждый раз, когда она помещается в программу. Когда код, который я написал, запускается сам по себе, создается впечатление, что он создает c_str правильно, за исключением случаев, когда я пытаюсь просмотреть переменные n, m, gnm, hnm, dgnm и dhnm, отображается только одно значение для каждого из них.

1 Ответ

1 голос
/ 27 мая 2011

Мне нужно продолжить ответ из-за недостатка места / форматирования в комментарии.

Прежде всего, у вас есть 90 записей, но вы можете позволить компилятору выяснить, сколько записей нужно массиву book:

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}
};

И, что более важно, вам не нужно помещать их в строку и вытаскивать их обратно, когда они у вас уже есть:

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. */
}

Это будет аккуратным шагом в сторону любого переполнения буфера, которое вы вызывали с помощью snprintf.

Ваш c_str является всего лишь char[81], и вы проходите цикл 90 раз и каждый раз увеличиваете свое смещение до c_str; итак, вы скоро добежите до конца c_str, а затем скажете snprintf, что нужно набросать всю нераспределенную память. Отсюда и твоя ошибка.

...