redefining a text record in progmem

I'm working with some externally provided data records that i'm storing in progmem.
each record consists of 69*2 characters of ascii data and within that are stored a bunch of different numeric fields. For example, there's a two character year at offset 18 and a 12 digit fractional day at offset 20.
To get at them, I code a bunch of defines with offsets and lengths for each element and a separate routine for each that uses those offsets and lengths to pull the pieces into a char array, pop a \0 on the end then atof() the char array to get the value.

what i think i need is a thing like a struct so i can define the data record breakdown as fixed length strings and then some way to neatly copy and atof() them. Any suggestions?

prog_char PROGMEM tles[]={
"1 28646U 05016A   11236.19785818 0.00000020  00000-0  47771-5 0    04"
"2 28646  57.0180 143.8885 0007000 104.2909 255.7091 14.53336366    07"
                                          .....
"1 31702U 07027B   11232.05943584 0.00000000  00000-0  00000-0 0    09"
"2 31702  63.3746 292.4363 0047000 293.0061  66.9939 14.17710013    02"
};
int numtles=6;
#define tlelen 69 //length of a tle line
#define yebegin 18 //offset to 1st byte of YE element epoch year
#define tebegin 20 //offset to TE
#define telen 12
...
...
double tle2ye(int n){ //return epoch year of tle n
  int len=yelen, offst=yebegin;
  tle2buff(n,offst,len);
  return 2000.0+atof(buff);
}
double tle2te(int n){ //return epoch time of tle n
  int len=telen, offst=tebegin;
  tle2buff(n,offst,len);
  return atof(buff);
}
void tle2buff(int n, int byteoffset,int len){ //copy n bytes out of tle n at offset given
  for (int i=0;i<len;i++){
    int tleoffset=(n-1)*tlelen*2; //1st byte of the 1st line of the tle pointed to
    char x=pgm_read_byte_near(tles+tleoffset+byteoffset+i);
    buff[i]=x;
  }
  buff[len]='\0';
}

what i think i need is a thing like a struct so i can define the data record breakdown as fixed length strings and then some way to neatly copy and atof() them. Any suggestions?

Why do you think you need this? What's wrong with the way you are doing it now?

  for (int i=0;i<len;i++){
    int tleoffset=(n-1)*tlelen*2; //1st byte of the 1st line of the tle pointed to
    char x=pgm_read_byte_near(tles+tleoffset+byteoffset+i);
    buff[i]=x;
  }

The value of tleoffset is independent of the loop index. So, why is the declaration and definition inside the loop?

PaulS:

what i think i need is a thing like a struct so i can define the data record breakdown as fixed length strings and then some way to neatly copy and atof() them. Any suggestions?

Why do you think you need this? What's wrong with the way you are doing it now?

well, it would be nice to write something like

struct tlerecord
  filler char[17]
  YE     char[2]
  TE     char[12]
   ...and so on...

then later

year=atof(YE);
daydate=atof(TE)

understanding that if the structure was in progmem i would have to copy it out first but even then it would feel better to have the definition specify the length of a fixed string at compile time rather than have to hand code it or poke in a \0.

maybe it's just me...

PaulS:

  for (int i=0;i<len;i++){

int tleoffset=(n-1)tlelen2; //1st byte of the 1st line of the tle pointed to
    char x=pgm_read_byte_near(tles+tleoffset+byteoffset+i);
    buff[i]=x;
  }



The value of tleoffset is independent of the loop index. So, why is the declaration and definition inside the loop?

tleoffset is just an intermediate result to keep the next line from getting unbearably complex. It isn't used anywhere else so i defined and discarded it in the loop.
You're correct, it "belongs" outside the loop but really so does everything except the something+i. It may have had something to do with having multiple copies of the routine and keeping the differences to a minimum - not a conscious decision, just seemed clearer to me at the time.

well, it would be nice to write something like

Defining a structure, and defining an instance of the structure, and populating the members of the structure are three separate issues.

Defining the structure is relatively simple. Creating an instance of the structure is easy. Populating the structure is the most difficult part, and, having done so, doesn't really but you anything. You have to have done all the work already, so having the data in a structure doesn't seem to buy you much.

yah, I think I'll just hide some of the #defines in a .h, make a common routine for the move and atof() and call it a day.

I think I'll just make a common routine for the move and atof()

This makes sense.

and call it a day.

This does, too.

hide some of the #defines in a .h

The need for this, though, escapes me.