头文件声明函数和定义类内变量,但源文件中引用时显示未定义未声明
#ifndef READER_H
#define READER_H
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <sstream>
#include <vector>
#include <cstddef> //定义常用的常量、宏、类型和函数
#include <cstring>
#include <array>
#include <map>
#include <utility> //定义STL类型、 函数和运算符
#include <iomanip> //设置精度
#include <Cmath>
#include <Eigen/Dense> //矩阵运算库
#include <Eigen/Core> //矩阵运算库
#define endd '\n'
#define MAX_STRLEN 100 //定义最大长度 100
#define MAX_BYTE 1024 //定义最大字节数1024
#define PI 3.14159265358979323846264 //定义PI值
using namespace std;
using namespace Eigen;
class reader {
public:
//构造函数
reader(const char* obsFilename, const char* navFilename);
FILE* obspfile; //观测文件指针
FILE* navpfile; //星历文件指针
bool obsHeader = true;
bool navHeader = true;
int SENTINEL = 0;
//观测文件 结构
//保存观测文件头文件信息
struct Header {
string version;
string markername;
int nobstype;
vector< string > obstype;
double interval;
vector< double > antpos;
};
Header head;
//保存观测文件记录内容
struct RECORDS {
vector< vector<double> > record;
double time;
double YEAR;
double MONTH;
double DAY;
double HOUR;
double MIN;
double Indivi_Sec;
double SEC;
vector<int> prn;
int NumOfSat;
};
RECORDS obs;
////星历文件 结构
//保存星历文件信息
struct NAVRECORDS {
double IODE, Crs, DeltaN, Mo, Cuc, Eccentricity, Cus, Sqrta, Toe, Cic,
OMEGA, Cis, Io, Crc, omega, OMEGADOT, IDOT, L2CodesChannel, GPSWeek, L2PDataFlag, SVAccuracy, SVHealth, TGD, IODC,
TransmissionTime, FitInterval, SVClockBias, SVClockDrift, SVClockDriftRate, PRN, SEC, gpstime;
};
vector<NAVRECORDS> SV_data;
};
#endif
//****************函数声明****************//
double GPSTime(vector<double> time); //把时间转换为gps时
double scientificTodouble(string str); //将科学字符串表示法转换为双精度
void rinexOBSReader(reader::Header& head, reader::RECORDS& obs_RECORDS, int& SENTINEL);
void rinexNAVReader(vector<reader::NAVRECORDS>& nav_RECORDS);
c++
#include "reader.h"
//构造函数
reader::reader(const char* obsFilename, const char* navFilename)
{
obspfile = fopen(obsFilename, "rt");
if (obspfile == NULL) perror("Error opening file");
navpfile = fopen(navFilename, "rt");
if (navpfile == NULL) perror("Error opening file");
}
//计算gps周内秒
double GPSTime(vector<double> time)
{
double julian_date, JDholder1, JDholder2, gpsweekholder, y, m, gpsweek, gpstime;
double UT = time[3] + (time[4] / 60) + (time[5] / 3600);
if (time[1] > 2) {
y = time[0] + 2000;
m = time[1];
}
else {
y = time[0] + 2000 - 1;
m = time[1] + 12;
}
JDholder1 = 365.25 * y;
JDholder2 = 30.6001 * (m + 1);
if (JDholder1 > 0 && JDholder2 > 0) {
julian_date = floor(JDholder1) + floor(JDholder2) + time[2] + (UT / 24) + 1720981.5;
}
else {
julian_date = ceil(JDholder1) + ceil(JDholder2) + time[2] + (UT / 24) + 1720981.5; //儒略日
}
gpsweekholder = (julian_date - 2444244.5) / 7; //gps周
if (gpsweekholder > 0) {
gpsweek = floor(gpsweekholder);
}
else {
gpsweek = ceil(gpsweekholder);
}
gpstime = round((((julian_date - 2444244.5) / 7) - gpsweek) * 7 * 24 * 3600); //gps周内秒
return gpstime;
}
//将科学字符串表示法转换为双精度类型
double scientificTodouble(string str)
{
istringstream os(str.replace(15, 1, "e")); //将星历文件中的D换成e
double str1;
os >> str1;
return str1;
}
//RINEX类型观测文件读取
void rinexOBSReader(reader::Header& head, reader::RECORDS& obs_RECORDS, int& SENTINEL)
{
//存储逐行字符的变量line
char line[MAX_STRLEN];
//读取头文件
if (obsHeader == true) {
fgets(line, MAX_STRLEN, obspfile);
while (!feof(obspfile) && strstr(line, "END OF HEADER") == NULL) {
if (sizeof(line) >= 61) {
if (strstr(line, "RINEX VERSION")) {
string sline(line); // 将line (char型)转换为字符串类型sLine
string token = sline.substr(5, 3); //从第5个字符和5个空格
head.version = token;
}
if (strstr(line, "MARKER NAME")) {
string sline(line); // 将line (char型)转换为字符串类型sLine
string token = sline.substr(0, 10); // 从第5个字符和5个空格
head.markername = token;
}
if (strstr(line, "INTERVAL")) {
string sline(line); // 将line (char型)转换为字符串类型sLine
string token = sline.substr(5, 5); // 从第5个字符和5个空格
head.version = token;
}
if (strstr(line, "APPROX POSITION XYZ")) {
string sline(line); // 将line (char型)转换为字符串类型sLine
string token = sline.substr(3, 56); // 从第3个字符到第56个字符
char cline[MAX_BYTE]; // cline是个字符行
strncpy(cline, token.c_str(), sizeof(cline));
cline[sizeof(cline) - 1] = 0;
for (char* r = strtok(cline, " "); r; r = strtok(NULL, " "))
{
double rr = atof(r);
head.antpos.push_back(rr);
}
}
if (strstr(line, "# / TYPES OF OBSERV")) {
string sline_new(line); // 将line (char型)转换为字符串类型sLine
string token_new = sline_new.substr(5, 2); //从第5个字符和2个空格
head.nobstype = stoi(token_new);
if (head.nobstype <= 9)
{
string sline(line); // 将line (char型)转换为字符串类型sLine
string token = sline.substr(10, 50); // 从第10个字符到 #
char cline[MAX_BYTE]; // cline是个字符行
strncpy(cline, token.c_str(), sizeof(cline));
cline[sizeof(cline) - 1] = 0;
for (char* p = strtok(cline, " "); p; p = strtok(NULL, " "))
{
head.obstype.push_back(p);
}
}
else {
string sline(line); // 将line (char型)转换为字符串类型sLine
string token = sline.substr(10, 50); // 从第10个字符到 #
char cline[MAX_BYTE]; // cline是个字符行
strncpy(cline, token.c_str(), sizeof(cline));
cline[sizeof(cline) - 1] = 0;
for (char* p = strtok(cline, " "); p; p = strtok(NULL, " "))
{
head.obstype.push_back(p);
}
//......... 获取下一行.......................
fgets(line, MAX_STRLEN, obspfile);
string sline2(line); // 将line (char型)转换为字符串类型sLine
string token2 = sline.substr(10, 50); // 从第10个字符到 #
char cline2[MAX_BYTE]; // cline是个字符行
strncpy(cline2, token2.c_str(), sizeof(cline2));
cline2[sizeof(cline2) - 1] = 0;
for (char* pp = strtok(cline2, " "); pp; pp = strtok(NULL, " "))
{
head.obstype.push_back(pp);
}
}
}
}
//......... 获取下一行.......................
fgets(line, MAX_STRLEN, obspfile);
}
}
obsHeader = false;
//Read the observation file......
int Nobs = head.nobstype;
int Num_Sat;
//---------------------------------------------------------------------------------//
while (!feof(obspfile) && SENTINEL != -1)
{
fgets(line, MAX_STRLEN, obspfile); // Get a newline
if (strstr(line, "G") && !strstr(line, "COMMENT"))
{
double Y, M, D, H, Min, Sec, timeStamp, timeSEC;
reader::RECORDS obs_temp;
std::vector< int > SV;
std::vector< string > tempEpoch;
string sline(line); // convert the line (char) to string class type sLine
string token = sline.substr(0, 32); // first line of each epoch from start upto G
char epoch[MAX_BYTE]; // cline is a char line rep the starting line of each epoch
strncpy(epoch, token.c_str(), sizeof(epoch));
epoch[sizeof(epoch) - 1] = 0;
for (char* p = strtok(epoch, " "); p; p = strtok(NULL, " "))
{
tempEpoch.push_back(p);
}
//Get the time from the file.....
Y = stod(tempEpoch[0]);
M = stod(tempEpoch[1]);
D = stod(tempEpoch[2]);
H = stod(tempEpoch[3]);
Min = stod(tempEpoch[4]);
Sec = stod(tempEpoch[5]);
vector<double> timeHolder;
timeHolder.push_back(Y);
timeHolder.push_back(M);
timeHolder.push_back(D);
timeHolder.push_back(H);
timeHolder.push_back(Min);
timeHolder.push_back(Sec);
timeStamp = GPSTime(timeHolder);
timeSEC = (H * 3600) + (Min * 60) + (Sec);
int Num_Sat_i, L_To_SN, S_Of_Str;
Num_Sat = 0; //Initialize a variable to hold the number of sat at each epoch
Num_Sat_i = stoi(tempEpoch[7]); //initial num of satellite
L_To_SN = 33; //Length to satellite number
S_Of_Str = 0; //Start of string
//..................................................................................//
// Loop for getting the satellite vehicles in each epoch and num of sat
//.................................................................................//
string sline1(line); // convert the line (char) to string class type sLine
string token1 = sline1.substr(L_To_SN, sline1.length());
//Prn storage
for (int r = 0; r < Num_Sat_i; r++) {
string token2 = token1.substr(S_Of_Str, 2);
int p = stoi(token2);
SV.push_back(p);
Num_Sat = Num_Sat + 1;
S_Of_Str = S_Of_Str + 3;
}
obs_RECORDS.NumOfSat = Num_Sat;
obs_RECORDS.prn = SV;
obs_RECORDS.time = timeStamp;
obs_RECORDS.YEAR = Y;
obs_RECORDS.MONTH = M;
obs_RECORDS.DAY = D;
obs_RECORDS.HOUR = H;
obs_RECORDS.MIN = Min;
obs_RECORDS.Indivi_Sec = Sec; // individual second
obs_RECORDS.SEC = timeSEC; // Total time in seconds
//------------------------------------------------------------------------------------------------------------------------------------------------------
double con = floor(Nobs / 5); // Condition for looping according to continuation lines if past 5 obs in a line
vector< vector<double> > array;
for (int i = 0; i < Num_Sat; i++)
{
int curObsType = 1; // current observation type
size_t obsSpace = 14; // space of an observation in a line
std::vector< double > recVec; // Get a newline
fgets(line, MAX_STRLEN, obspfile);
// Each observation line contains a max of 5 records.... //So if less or equal(we have less or equal to 5 obs types)
if (Nobs <= 5)
{
for (int j = 0; j < Nobs + 1; j++) {
string sline2(line); // convert the line (char) to string class type sLine
size_t S_Of_Rec = 0;
if (strlen(line) > 1) {
string token3 = sline2.substr(S_Of_Rec, 14);//从下标s_of_rec开始截取向后14个字节(下一个数据)
double p = stod(token3);//把上一行数据类型由字符串强制转换为双浮点并且赋予给p
recVec.push_back(p);//把p插入recvec数组
S_Of_Rec = S_Of_Rec + 16;//下个数据下标起点
}
else {
//(An empty line)
double p = NAN;
recVec.push_back(p);
S_Of_Rec = S_Of_Rec + 16;
}
}
}
else
{
for (int k = 0; k < con; k++)
{
string sline2(line); // convert the line (char) to string class type sLine
size_t S_Of_Rec = 0;
double count = 0;
double strlen_sline2 = sline2.length();
for (int l = 0; l < 5; l++) { //MAX NUMBER OF OBS PER LINE = 5
count = count + 1;
//****************************ADDED 8/26/2018***************************************//
if (strlen(line) > 1) {
if (count * 14 > strlen_sline2) {
double p = 0.0;
recVec.push_back(p);
S_Of_Rec = S_Of_Rec + 16;
}
else {
string token3 = sline2.substr(S_Of_Rec, 14);
//****************************ADDED 8/26/2018***************************************//
double p;
bool whiteSpacesOnly = std::all_of(token3.begin(), token3.end(), isspace);
if (whiteSpacesOnly) {
p = 0.0;
}
else {
p = stod(token3);
}
//****************************CHANGED**************************************//
recVec.push_back(p);
S_Of_Rec = S_Of_Rec + 16;
}
}
else {
//(An empty line)
double p = 0.0;
recVec.push_back(p);
S_Of_Rec = S_Of_Rec + 16;
}
}
//..........Continuation line...........//
fgets(line, MAX_STRLEN, obspfile);
}
string sline3(line); // convert the line (char) to string class type sLine
size_t S_Of_Rec = 0;
double count = 0;
double strlen_sline3 = sline3.length();
for (int o = 0; o < (Nobs - 5 * con); o++) //MAX NUMBER OF OBS PER LINE = 5
{
count = count + 1;
if (strlen(line) > 1)
{
if (count * 14 > strlen_sline3) {
double p = 0.0;
recVec.push_back(p);
S_Of_Rec = S_Of_Rec + 16;
}
else {
string token4 = sline3.substr(S_Of_Rec, 14);
double p;
bool whiteSpacesOnly = std::all_of(token4.begin(), token4.end(), isspace);
if (whiteSpacesOnly) {
p = 0.0;
}
else {
p = stod(token4);
}
recVec.push_back(p);
S_Of_Rec = S_Of_Rec + 16;
}
}
else
{ //An empty line
double p = 0.0;
recVec.push_back(p);
S_Of_Rec = S_Of_Rec + 16;
}
}
// Put recVec in array double vector
array.push_back(recVec);
obs_RECORDS.record = array;
}
}
array.clear();
SENTINEL = -1;
}
else {
//Do nothing
}
}
}
//RINEX NAVIGATION FILE READER
void rinexNAVReader(vector<reader::NAVRECORDS>& nav_RECORDS)
{
char aline[MAX_STRLEN];
// SKIP THE HEADER......
if (navHeader == true) {
fgets(aline, MAX_STRLEN, navpfile);
while (!feof(navpfile) && strstr(aline, "END OF HEADER") == NULL) {
if (strstr(aline, "END OF HEADER")) {
break;
}
fgets(aline, MAX_STRLEN, navpfile);
}
}
navHeader = false;
// Read the navigation file...
//Get a new line......
fgets(aline, MAX_STRLEN, navpfile);
while (!feof(navpfile))
{
double prn, Y, M, D, H, Min, Sec, timeStamp, timeSEC;
reader::NAVRECORDS navrecord_temp;
// First line of the nav records at each epoch
string sline(aline); // convert the line (char) to string class type sLine
//Store the time in the file
string prn_s = sline.substr(0, 2); prn = stod(prn_s);
string Y_s = sline.substr(3, 2); Y = stod(Y_s);
string M_s = sline.substr(6, 2); M = stod(M_s);
string D_s = sline.substr(9, 2); D = stod(D_s);
string H_s = sline.substr(12, 2); H = stod(H_s);
string Min_s = sline.substr(15, 2); Min = stod(Min_s);
string Sec_s = sline.substr(18, 4); Sec = stod(Sec_s);
vector<double> timeHolder;
timeHolder.push_back(Y);
timeHolder.push_back(M);
timeHolder.push_back(D);
timeHolder.push_back(H);
timeHolder.push_back(Min);
timeHolder.push_back(Sec);
//Get gps time in seconds....
timeStamp = GPSTime(timeHolder);
timeSEC = (H * 3600) + (Min * 60) + (Sec);
string SVCB_s = sline.substr(22, 19);
double SVCB = scientificTodouble(SVCB_s); // Convert scientific string in Nav to double (and replace D with e)
string SVCD_s = sline.substr(41, 19);
double SVCD = scientificTodouble(SVCD_s);
string SVCDR_s = sline.substr(60, 19);
double SVCDR = scientificTodouble(SVCDR_s);
//Get a new line.......
fgets(aline, MAX_STRLEN, navpfile);
vector<double> navRecHolder;
for (int i = 0; i < 6; i++) {
string sline(aline);
size_t S_Of_Rec = 3;
for (int j = 0; j < 4; j++) {
string p_s = sline.substr(S_Of_Rec, 19);
double p = scientificTodouble(p_s);
navRecHolder.push_back(p);
S_Of_Rec = S_Of_Rec + 19;
}
fgets(aline, MAX_STRLEN, navpfile);
}
string sline6(aline);
if (sline6.length() <= 23) {
string TransmissionTime_s = sline6.substr(3, 19);
double TransmissionTime = scientificTodouble(TransmissionTime_s);
navrecord_temp.TransmissionTime = TransmissionTime;
navrecord_temp.FitInterval = NAN;
}
else {
string TransmissionTime_s = sline6.substr(3, 19);
double TransmissionTime = scientificTodouble(TransmissionTime_s);
string FitInterval_s = sline6.substr(3, 19);//拟合区间
double FitInterval = scientificTodouble(FitInterval_s);
navrecord_temp.TransmissionTime = TransmissionTime;
navrecord_temp.FitInterval = FitInterval;
}
// Store all the nav obs in the local struct
navrecord_temp.PRN = prn;
navrecord_temp.SVClockBias = SVCB;
navrecord_temp.SVClockDrift = SVCD;
navrecord_temp.SVClockDriftRate = SVCDR;
navrecord_temp.SEC = timeSEC;
navrecord_temp.gpstime = timeStamp;
navrecord_temp.IODE = navRecHolder[0];
navrecord_temp.Crs = navRecHolder[1];
navrecord_temp.DeltaN = navRecHolder[2];
navrecord_temp.Mo = navRecHolder[3];
navrecord_temp.Cuc = navRecHolder[4];
navrecord_temp.Eccentricity = navRecHolder[5];
navrecord_temp.Cus = navRecHolder[6];
navrecord_temp.Sqrta = navRecHolder[7];
navrecord_temp.Toe = navRecHolder[8];
navrecord_temp.Cic = navRecHolder[9];
navrecord_temp.OMEGA = navRecHolder[10];
navrecord_temp.Cis = navRecHolder[11];
navrecord_temp.Io = navRecHolder[12];
navrecord_temp.Crc = navRecHolder[13];
navrecord_temp.omega = navRecHolder[14];
navrecord_temp.OMEGADOT = navRecHolder[15];
navrecord_temp.IDOT = navRecHolder[16];
navrecord_temp.L2CodesChannel = navRecHolder[17];
navrecord_temp.GPSWeek = navRecHolder[18];
navrecord_temp.L2PDataFlag = navRecHolder[19];
navrecord_temp.SVAccuracy = navRecHolder[20];
navrecord_temp.SVHealth = navRecHolder[21];
navrecord_temp.TGD = navRecHolder[22];
navrecord_temp.IODC = navRecHolder[23];
// Store everything in the vector of global struct
nav_RECORDS.push_back(navrecord_temp);
//Get a new line
fgets(aline, MAX_STRLEN, navpfile);
}
}
所有的navHeader和navpfile、obsHeader和obspfile都显示未声明和未定义,但是可以在源文件中转到头文件中的定义,头文件没有报错
能正常引用不报错
void rinexOBSReader(reader::Header& head, reader::RECORDS& obs_RECORDS, int& SENTINEL)
{
//存储逐行字符的变量line
char line[MAX_STRLEN];
//读取头文件
if (obsHeader == true) {
===============
注意,以上代码不是类的成员函数代码,所以obsHeader是不认识的。应该改为head.obsHeader==true
如果引入c库就需要添加相关的编译器宏判断