首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NMEA 0183校验和验证

NMEA 0183校验和验证
EN

Code Review用户
提问于 2016-01-30 19:22:03
回答 1查看 1.9K关注 0票数 6

我希望能得到一些关于清理代码的几个方面的建议。特别是,十六进制到二进制部分,校验和在十六进制,其余在ASCII中。我试着用桌子等来度过美好的一天,但在挫折中,我最终还是这么做了。

是否有更好的方法来处理“在向量中存储单个字符”部分?我这样做是因为消息可以是可变大小的(加上1或2个字符)。

下面是消息类型的一个示例:

AIVDM,1,1,A,13 1,1:0P0000VOHLCnHQKwvL05Ip,0*23

代码语言:javascript
复制
using namespace std;

int main()

{
//Checksum Function

//Get Characters for Checksum
ifstream AisMsg("nmea.txt", ios::in);

    string MsgLine;
    getline(AisMsg, MsgLine, '*');
    MsgLine.erase(0,1);

        string HexVal;
        getline(AisMsg, HexVal);

AisMsg.close();

//Store individual characters in an element of an vector
int i = 0;
int j = ( MsgLine.length() );
vector <int> AsciiValues;
{
    bool done = false;
    while (!done)
    {
        int h ( MsgLine.at (i) );
        i++;
        AsciiValues.push_back(h);

    if ( i == j )
        done = true;
    }
}
//XOR validation
bitset<8> a = (AsciiValues[0]);
bitset<8> b = (AsciiValues[1]);
bitset<8> c = a ^ b;
    int d = 2;
    int e = (AsciiValues.size());

{
    bool done = false;
    while (!done)
    {
        a = (AsciiValues[d]);
        b = c;
        c = a ^ b;
        d++;

    if ( d == e )
        done = true;
    }
}
//Hex Checksum to Binary Conversion (messy, but does the job)
int PosOne = HexVal.at(0);
int PosTwo = HexVal.at(1);

    bitset<4> z = PosOne;
    bitset<4> x = PosTwo;

        ofstream Cheat("Amateur Hour.txt", ios::out | ios::app);
        Cheat << z << x << endl;
        ifstream Cheat1("Amateur Hour.txt", ios::in | ios::binary);

            string Chksm;
            getline(Cheat1,Chksm);

        Cheat.close();
        Cheat1.close();
        remove ("Amateur Hour.txt");


return 0;
}
EN

回答 1

Code Review用户

发布于 2016-01-30 21:29:24

我相信这是可以简化的。我的直接反应是编写类似这样的代码:

代码语言:javascript
复制
#include <sstream>
#include <iostream>
#include <numeric>

int main() { 
    std::istringstream in("$AIVDM,1,1,,A,13HOI:0P0000VOHLCnHQKwvL05Ip,0*23");

    std::string sentence;

    std::getline(in, sentence, '*');

    std::string received_checksum;

    // Save the checksum that was at the end of what we received.
    std::getline(in, received_checksum);

    // Re-compute the check-sum:
    char check = std::accumulate(sentence.begin()+1, sentence.end(), 0,
        [](char sum, char ch) { return sum ^ ch; });

    // Print out both the received and computed checksums:
    std::cout << "received checksum: " << received_checksum;
    std::cout << "\ncomputed checksum: " << std::hex << (int)check << "\n";
}

看一看代码的具体细节,我看到了一些事情,即使您要大致保留当前的实现,仍然可以简化和澄清。第一点是修复您的缩进。现在,它看起来几乎完全是任意的,并且与代码的结构无关。

然后你就可以清理你的一些循环了。例如:

代码语言:javascript
复制
bool done = false;
while (!done)
{
    int h ( MsgLine.at (i) );
    i++;
    AsciiValues.push_back(h);

if ( i == j )
    done = true;
}

...can变成了这样的东西:

代码语言:javascript
复制
for (int i=0; i<j; i++)
    AsciiValues.push_back((int)MsgLine.at(i));

或者,你可以直接使用std::copy。同样,计算校验和的代码:

代码语言:javascript
复制
bool done = false;
while (!done)
{
    a = (AsciiValues[d]);
    b = c;
    c = a ^ b;
    d++;

if ( d == e )
    done = true;
}

将...could简化为如下所示:

代码语言:javascript
复制
do {
    a = AsciiValues[d];
    b = c;
    c = a ^ b;
    ++d;
} while (d != e);

...or --您可以做一些与accumulate更接近的事情(在我看来,使用std::accumulate仍然要干净得多),正如我开始演示的那样。

票数 8
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/118379

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档