C++ 解析文本和输出“;“出现时间”;某些行的
所以我得到的文件看起来像:C++ 解析文本和输出“;“出现时间”;某些行的,c++,string,parsing,C++,String,Parsing,所以我得到的文件看起来像: $GPGGA,124613.90,5543.3221231,N,03739.1368442,E,1,15,0.69,147.0851,M,14.4298,M,,*54 $GPGSV,3,1,10,27,12,078,41,05,31,308,49,16,25,043,44,02,11,268,44*7E $GPGSV,3,2,10,26,03,031,39,07,74,216,52,09,58,121,52,30,39,234,48*71 $GPGSV,3,3,10,
$GPGGA,124613.90,5543.3221231,N,03739.1368442,E,1,15,0.69,147.0851,M,14.4298,M,,*54
$GPGSV,3,1,10,27,12,078,41,05,31,308,49,16,25,043,44,02,11,268,44*7E
$GPGSV,3,2,10,26,03,031,39,07,74,216,52,09,58,121,52,30,39,234,48*71
$GPGSV,3,3,10,23,30,116,46,04,37,114,47*79
$GLGSV,2,1,07,84,17,338,43,78,15,212,48,85,12,032,46,67,84,223,53*67
$GLGSV,2,2,07,77,67,195,47,76,50,047,54,66,32,144,52*5C
$GPGGA,124614.00,5543.3221239,N,03739.1368445,E,1,15,0.69,147.0864,M,14.4298,M,,*53
$GPGSV,3,1,10,27,12,078,41,05,31,308,49,16,25,043,43,02,11,268,44*79
$GPGSV,3,2,10,26,03,031,39,07,74,216,52,09,58,121,52,30,39,234,48*71
$GPGSV,3,3,10,23,30,116,46,04,37,114,47*79
$GLGSV,2,1,07,84,17,338,43,78,15,212,48,85,12,032,46,67,84,223,53*67
$GLGSV,2,2,07,77,67,195,47,76,50,047,54,66,32,144,52*5C
我的cod正在检查字符串的校验和,并在字符串中输出一些值。
在$GPGGA中,“124614.00”是时间。12小时46分14秒。我需要输出时间的“外观”$GPGSV线。我试着用指针减去第一个值和后面的值,但我一定是把什么地方搞砸了
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <numeric>
#include <cstdlib>
#include <cstring>
#include <stdio.h>
int checksum(const char* s) {
int c = 0;
while (*s)
c ^= *s++;
return c;
}
int main() {
char linec_h[200];
int k, key;
int* hour = NULL;
int* minute = NULL;
float* sec = NULL;
std::string line, key_s;
std::ifstream logs_("C:/Users/Olya/Desktop/broken.txt");
std::ofstream pout("C:/Users/Olya/Desktop/outLOG.txt");
if (logs_.is_open()) {
while (getline(logs_, line)) {
key_s = line.substr(line.length() - 2, 2);
key = strtol(key_s.c_str(), NULL, 16);
line = line.substr(1, line.length() - 4);
strcpy_s(linec_h, line.c_str());
if (key != checksum(linec_h))
pout << "Line is corrupted!" << std::endl;
else {
k = 0;
if (line.substr(0, 5) == "GPGGA") {
if (hour, minute, sec) {
*hour = stoi(line.substr(5, 2)) - *hour;
*minute = stoi(line.substr(7, 2)) - *minute;
*sec = stof(line.substr(9, 4)) - *sec;
}
else {
hour = new int;
minute = new int;
sec = new float;
*hour = stoi(line.substr(5, 2));
*minute = stoi(line.substr(7, 2));
*sec = stof(line.substr(9, 4));
}
} else if (line.substr(0, 5) == "GPGSV") {
for (size_t i = 0, SNR = 7, N = 4; i < line.size(); i++) {
if (line[i] == ',')
k++;
if (k == N) {
pout << "Satellite number -- " << line.substr(i + 1, 2) << " ";
if ((N += 4) > 16)
;
} else if (k == SNR) {
pout << "SNR -- " << line.substr(i + 1, 2) << " time -- " << hour
<< "." << minute << "." << sec << std::endl;
if ((SNR += 4) > 19)
break;
}
}
}
}
delete hour;
delete minute;
delete sec;
}
logs_.close();
std::cout << "Success" << std::endl;
} else
std::cout << "File is not open" << '\n';
pout.close();
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
整数校验和(常量字符*s){
int c=0;
而(*s)
c^=*s++;
返回c;
}
int main(){
char linec_h[200];
int k,键;
int*hour=NULL;
int*minute=NULL;
浮点*秒=空;
标准::字符串行,键;
std::ifstream日志(“C:/Users/Olya/Desktop/break.txt”);
std::of stream pout(“C:/Users/Olya/Desktop/outLOG.txt”);
如果(日志是打开的()){
while(getline(logs,line)){
key_s=line.substr(line.length()-2,2);
key=strtol(key_s.c_str(),NULL,16);
line=line.substr(1,line.length()-4);
strcpy_s(linec_h,line.c_str());
if(key!=校验和(linec_h))
pout我可以看到像if(小时、分钟、秒){
这样的错误,还有许多C风格的代码,用指针操作。我不想调试你的代码
作为对您的samll提示,我创建了一个解析器,它读取所有源代码行,将tem拆分为标记并检查校验和
只需要几行代码就可以了。从那以后,您可以进一步开发
#include <iostream>
#include <regex>
#include <vector>
#include <iterator>
#include <string>
#include <utility>
#include <algorithm>
#include <functional>
#include <numeric>
#include <fstream>
const std::regex re{ R"(\$(.*)\*[abcdefABCDEF\d]{2})" };
const std::regex delimiter{ "," };
using Tokens = std::vector<std::string>;
std::tuple<bool, Tokens> checkString(const std::string& str) {
// Return value of the function. Assume that string is not ok
std::tuple<bool, std::vector<std::string>> result(false, {});
// We want to find a string in the given format
std::smatch sm{};
if (std::regex_match(str, sm, re)) {
// OK, found. Validate checksum
if (std::string s = sm[1]; std::stoul(str.substr(str.size() - 2), nullptr, 16) == std::accumulate(s.begin(), s.end(), 0U, std::bit_xor<unsigned char>())) {
// Tokenize string
Tokens tokens(std::sregex_token_iterator(str.begin(), str.end(), delimiter, -1), {});
// Build return value
result = std::make_tuple(true, std::move(tokens));
}
}
return result;
}
int main() {
std::vector<Tokens> csvData{};
// Open file and check if it is open
if (std::ifstream logs("r:\\log.txt"); logs) {
// Read all lines of files
for (std::string line{}; std::getline(logs, line);) {
if (const auto& [ok, data] = checkString(line); ok) {
csvData.push_back(std::move(data));
}
else {
std::cerr << "**** Coruppted: " << line << "\n";
}
}
}
// So, now we have read all csv data
// Show eight column of GPGSV data
for (const Tokens& t : csvData) {
if (t[0] == "$GPGGA") {
std::cout << "$GPGGA -->" << t[1] << "\n";
}
else if (t[0] == "$GPGSV") {
std::cout << "$GPGSV -->" << t[4] << " " << t[7] << "\n";
}
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
const std::regex re{R“(\$(.*)\*[abcdefABCDEF\d]{2})”;
常量std::regex分隔符{“,”};
使用Tokens=std::vector;
std::tuple checkString(const std::string和str){
//函数的返回值。假设字符串不正常
std::tuple result(false,{});
//我们希望找到给定格式的字符串
std::smatch sm{};
if(std::regex_匹配(str、sm、re)){
//好的,找到了。验证校验和
if(std::string s=sm[1];std::stoul(str.substr(str.size()-2),nullptr,16)=std::accumulate(s.begin(),s.end(),0U,std::bit_xor()){
//标记化字符串
Tokens Tokens(std::sregx_token_迭代器(str.begin(),str.end(),delimiter,-1),{});
//构建返回值
结果=std::make_tuple(true,std::move(tokens));
}
}
返回结果;
}
int main(){
std::vector csvData{};
//打开文件并检查它是否已打开
if(std::ifstream日志(“r:\\log.txt”);日志){
//读取所有文件行
for(std::string line{};std::getline(logs,line);){
如果(常量自动&[ok,数据]=检查字符串(行);ok){
csvData.push_back(标准::移动(数据));
}
否则{
std::cerr只是为了好玩。我创建了一个完整的解决方案,可以完全解析GPS NMEA格式,并将所有结果放入结构中。因此,您可以获得所有卫星数据
但是,我只显示您在示例中使用的值
我把我的编码风格改成了你的。在C++中,我会把事情做得完全不同。无论如何。< /P>
请参阅附件中的完整示例:
#include <string>
#include <ctime>
#include <cstring>
#include <iostream>
#include <fstream>
#include <iomanip>
constexpr size_t NumberOfFixQualityStrings = 9;
constexpr size_t NumberOfSatellitesPerGSVSentencePart = 4;
constexpr size_t MaxNumberOfPartsInSentence = 10;
constexpr size_t MaxTokensInSentence = 64;
constexpr size_t NumberOfFieldsInGGA = 12;
std::string fixQualityString[NumberOfFixQualityStrings]{
"invalid", "GPS fix (SPS)", "DGPS fix", "PPS fix", "Real Time Kinematic", "Float RTK",
"estimated (dead reckoning", "Manual input mode", "Simulation mode" };
// essential fix data which provide 3D location and accuracy data
struct GGA {
// Time of last satellite fix
unsigned int fixTimeInUtcHours{};
unsigned int fixTimeInUtcMinutes{};
unsigned int fixTimeInUtcSeconds{};
unsigned int fixTimeInUtcMilliSeconds{};
// Position: Lattitude
unsigned int lattitudeInDegree{};
double lattitudeInMinutes{};
std::string lattitideDirection{};
// Position: Longitude
unsigned int longitudeInDegree{};
double longitudeInMinutes{};
std::string longitudeDirection{};
// FixQuality // see dteails as string above
unsigned int fixQuality{};
std::string fixQualityString{};
// Number of satellites being tracked (can be more than shown in GSV, not all are beeing used for calculation)
unsigned int numberOfTrackedSatellites{};
// Horizontal dilution of position
double horizontalDilution{};
// Altitude, Meters, above mean sea level
double altitude{};
std::string altitudeDimension{};
// Height of geoid (mean sea level) above WGS84 ellipsoid
double goidHight{};
std::string goidHightDimension{};
};
// Detail information for satellites in satellit view (GSV)
struct SatelliteData {
std::string satellitePRNnumber{};
double elevationInDegress{};
double azimuthInDegrees{};
double snr{}; // signal noise ratio
};
// Part of a GSV sentence
struct GSVSentencePart {
size_t numberOfSentencesForFullData{};
size_t sentencePartNumber{};
size_t numberOfSatellitesInView{};
size_t numberOfSatellitesInThisPart{};
SatelliteData satelliteData[NumberOfSatellitesPerGSVSentencePart];
};
struct GSV
{
GSVSentencePart gsvSentencePart[MaxNumberOfPartsInSentence];
size_t numberOfParts{};
};
bool checksumTest(std::string& line) {
bool result{ false };
// Check, if there is a 2 digt checksum at the end and convert it to decimal
if (size_t pos{}, checkSumGiven{ std::stoul(line.substr(line.size() - 2), &pos, 16) }; pos == 2)
{
// Strip off checksum part
line = line.substr(1,line.size() - 4);
// Calculate checksum
unsigned char calculatedChecksum{ 0U }; for (const unsigned char c : line) calculatedChecksum ^= c;
// Get result
result = (calculatedChecksum == checkSumGiven);
}
return result;
}
// Split all strings into a tokens
size_t splitIntoTokens(std::string& s, std::string (&tokens)[MaxTokensInSentence]) {
// Number of converted tokens
size_t numberOfTokens{ 0 };
// First check checksum
if (checksumTest(s)) {
// Now split along each comma
for (size_t i{ 0U }, startpos{ 0U }; i < s.size(); ++i) {
// So, if there is a comma or the end of the string
if ((s[i] == ',') || (i == (s.size() - 1))) {
// Copy substring
tokens[numberOfTokens++] = s.substr(startpos, i - startpos);
startpos = i + 1;
}
}
}
return numberOfTokens;
}
GGA convertStringToGGA(std::string& s) {
GGA gga;
// Split string into tokens and check, if it worked
if (std::string tokens[MaxTokensInSentence]; splitIntoTokens(s, tokens) > NumberOfFieldsInGGA && tokens[0] == "GPGGA") {
gga.fixTimeInUtcHours = std::stoul(tokens[1].substr(0, 2));
gga.fixTimeInUtcMinutes = std::stoul(tokens[1].substr(2, 2));
gga.fixTimeInUtcSeconds = std::stoul(tokens[1].substr(4, 2));
gga.fixTimeInUtcMilliSeconds = std::stod(tokens[1].substr(6, 2))*1000.0;
gga.lattitudeInDegree = std::stoul(tokens[2].substr(0, 2));
gga.lattitudeInMinutes = std::stod(tokens[2].substr(2));
gga.lattitideDirection = tokens[3];
gga.longitudeInDegree = std::stoul(tokens[4].substr(0, 2));
gga.longitudeInMinutes = std::stod(tokens[4].substr(2));
gga.longitudeDirection = tokens[5];
gga.fixQuality = std::stoul(tokens[6]);
gga.fixQualityString = (gga.fixQuality < NumberOfFixQualityStrings) ? fixQualityString[gga.fixQuality] : fixQualityString[0];
gga.numberOfTrackedSatellites = std::stoul(tokens[7]);
gga.horizontalDilution = std::stod(tokens[8]);
gga.altitude = std::stod(tokens[9]);
gga.altitudeDimension = tokens[10];
gga.goidHight = std::stod(tokens[11]);
gga.goidHightDimension = tokens[12];
}
return gga;
}
GSVSentencePart convertToGSVSentencePart(std::string& s) {
GSVSentencePart gsvsp;
// Split string into tokens and check, if it worked
std::string tokens[MaxTokensInSentence];
if (size_t numberOfCOnvertedTokens = splitIntoTokens(s, tokens); numberOfCOnvertedTokens > 0 && tokens[0] == "GPGSV") {
gsvsp.numberOfSentencesForFullData = std::stoul(tokens[1]);
gsvsp.sentencePartNumber = std::stoul(tokens[2]);
gsvsp.numberOfSatellitesInView = std::stoul(tokens[3]);
gsvsp.numberOfSatellitesInThisPart = 0;
for (size_t currentToken = 4; currentToken < numberOfCOnvertedTokens; currentToken += 4) {
gsvsp.satelliteData[gsvsp.numberOfSatellitesInThisPart].satellitePRNnumber = tokens[currentToken];
gsvsp.satelliteData[gsvsp.numberOfSatellitesInThisPart].elevationInDegress = stod(tokens[currentToken + 1]);
gsvsp.satelliteData[gsvsp.numberOfSatellitesInThisPart].azimuthInDegrees= stod(tokens[currentToken + 2]);
gsvsp.satelliteData[gsvsp.numberOfSatellitesInThisPart].snr = stod(tokens[currentToken + 3]);
++gsvsp.numberOfSatellitesInThisPart;
}
}
return gsvsp;
}
std::string calculateElapsedTime(const GGA& previousGGA, const GGA& nextGGA) {
std::tm tmPrevious{}, tmNext{};
tmPrevious.tm_year = 100; tmPrevious.tm_mon = 1; tmPrevious.tm_mday = 1;
tmNext.tm_year = 100; tmNext.tm_mon = 1; tmNext.tm_mday = 1;
tmPrevious.tm_hour = previousGGA.fixTimeInUtcHours;
tmPrevious.tm_min = previousGGA.fixTimeInUtcMinutes;
tmPrevious.tm_sec = previousGGA.fixTimeInUtcSeconds;
std::time_t previousTime = std::mktime(&tmPrevious);
tmNext.tm_hour = nextGGA.fixTimeInUtcHours;
tmNext.tm_min = nextGGA.fixTimeInUtcMinutes;
tmNext.tm_sec = nextGGA.fixTimeInUtcSeconds;
std::time_t nextTime = std::mktime(&tmNext);
double diff = std::difftime(nextTime, previousTime);
diff = diff + 1.0*nextGGA.fixTimeInUtcMilliSeconds/1000.0- 1.0*previousGGA.fixTimeInUtcMilliSeconds/1000.0;
return std::to_string(diff);
}
int main() {
// Open file and check, if it is open
if (std::ifstream nmeaFile("r:\\log.txt"); nmeaFile) {
GGA previousGGA;
GGA nextGGA;
GSV gsv;
size_t state{ 0 };
for (std::string line{}; std::getline(nmeaFile, line); ) {
switch ( state) {
case 0: // wait for first GGA data
if (line.substr(0, 6) == "$GPGGA") {
previousGGA = nextGGA;
nextGGA = convertStringToGGA(line);
state = 1;
gsv = {};
}
break;
case 1: // wait for GSV
if (line.substr(0, 6) == "$GPGSV") {
gsv.gsvSentencePart[gsv.numberOfParts] = convertToGSVSentencePart(line);
if (gsv.gsvSentencePart[gsv.numberOfParts].numberOfSentencesForFullData ==
gsv.gsvSentencePart[gsv.numberOfParts].sentencePartNumber) {
state = 0;
++gsv.numberOfParts;
// Now all data are available in reable and structed format.
// You can do, what you want with them
// For example, we can print all Satellite Data:
size_t counter{ 0 };
for (size_t i = 0; i < gsv.numberOfParts; ++i) {
for (size_t j = 0; j < gsv.gsvSentencePart[i].numberOfSatellitesInThisPart; j++) {
std::cout << "Satellite: " << std::setw(2) << ++counter << " Satellite name: " <<
std::setw(3) << gsv.gsvSentencePart[i].satelliteData[j].satellitePRNnumber <<
" SNR: " << std::setw(8) << gsv.gsvSentencePart[i].satelliteData[j].snr <<
" Elapsed time: "<< calculateElapsedTime(previousGGA, nextGGA)<< " s\n";
}
}
--gsv.numberOfParts;
}
++gsv.numberOfParts;
}
break;
}
}
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
constexpr size\u t NumberOfFixQualityStrings=9;
constexpr size_t NumberOfSatellitesPerGSVSentencePart=4;
constexpr size\u t MaxNumberOfPartsInSession=10;
constexpr size\u t maxTokensinSession=64;
constexpr size_t numberofieldsingga=12;
std::string fixQualityString[NumberOfFixQualityStrings]{
“无效”、“GPS定位(SPS)”、“DGPS定位”、“PPS定位”、“实时运动学”、“浮动RTK”,
“估计(航位推算”、“手动输入模式”、“模拟模式”};
//提供3D位置和精度数据的基本固定数据
结构GGA{
//最后一次卫星定位时间
无符号int-fixTimeInUtcHours{};
无符号int-fixtimeinutcmins{};
无符号int-fixtimeinutseconds{};
无符号int-fixtimeinutcmissions{};
//职位:Lattude
无符号int-latticudeindegree{};
双格点{};
std::string latitidedirection{};
//位置:经度
无符号int-longitudeInDegree{};
双纵联{}分钟;
std::string longitudeDirection{};
//FixQuality//请参见上面的dteails字符串
无符号整型质量{};
std::string fixQualityString{};
//正在跟踪的卫星数量(可能超过GSV中显示的数量,并非所有卫星都用于计算)
无符号整数跟踪卫星{};
//位置的水平稀释
双水平稀释{};
//海拔高度,米,高于平均海平面
双高度{};
std::字符串altitudeDimension{};
//WGS84椭球体上方大地水准面高度(平均海平面)
双甲状腺右{};
std::字符串goidHightDimension{};
};
//卫星视图(GSV)中卫星的详细信息
结构卫星数据{
std::字符串卫星号{};
双提升指数{};
双方位角角度{};
双信噪比{};//信噪比
};
//GSV语句的一部分
结构GSVSentencePart{
完整数据{}的大小和数量;
尺寸句子零件号{};
卫星在视图{}中的大小和数量;
该部分{}中卫星的大小和数量;
卫星数据卫星数据[卫星数/卫星数/分件];
};
结构GSV
{
GSVSentencePart GSVSentencePart[句子中的最大零件数];
零件的尺寸和数量{};
};
布尔校验集测试(标准::字符串和行){
bool结果{false};
//检查末尾是否有2位校验和,并将其转换为十进制
if(size_t pos{},checksum{std::stoul(line.substr(line.size()-2),&pos,16)};pos==2)
{
//去掉校验和部分
line=line.substr(1,line.size()-4);
//计算校验和
无符号字符calculatedChecksum{0U};for(const unsigned char c:line)calculatedChecksum^=