Консоль C ++ Eclipse, кодирующая простой текст как другие символы

У меня есть программа C ++, работающая на Intel Edison, которая считывает некоторые данные GPS с последовательного порта и передает их обратно на консоль.

Эта часть работает нормально, но когда строки читаются в консоли, у них есть символы, которых там быть не должно, наприме𠫬é». Я предполагаю, что что-то напутано с кодировкой в ​​консоли Eclipse / G ++, и он считает, что некоторые чтения являются символьными кодами.

Вот некоторый вывод из консоли Eclipse:

$GPVTG,,T,,M,0.041,N,0.075,K,A*24
$GPGGA,225153.00,5206.75433,N,12206.88881,W,1,10,1.03,582.1,M,-15.6,M,,*6F
$GPGSA,A,3,32,02,12,14,24,06,03,19,17,25,,,1.84,1.03,1.53*05
$GPGSV,3,1,11,¬é­N
-> 02,51,176,30,03,10,027,17,06,60,088,33,12,68,295,36*79
$GPGSV,3,2,11,14,10,316,30,17,20,072,27,19,45,069,40,24,36,215,35*7E
$GPGSV,3,3,11,25,29,301,28,29,05,254,,32,07,305,33*40
$GPGLL,5206.75433,N,12206.88881,W,225153.00,A,A*78
.53*05
$GPGSV,3,1,11,¬é­N

А вот некоторые из выводимых данных, считанные непосредственно с последовательного порта на Edison (cat /dev/ttyMFD1):

$GPVTG,,T,,M,0.048,N,0.090,K,A*26
$GPGGA,225407.00,5206.75339,N,12206.88816,W,1,10,1.02,584.2,M,-15.6,M,,*6C
$GPGSA,A,3,32,02,12,14,24,06,03,19,17,25,,,1.80,1.02,1.49*0B
$GPGSV,3,1,11,02,52,176,15,03,10,026,20,06,59,086,29,12,69,295,41*76
$GPGSV,3,2,11,14,09,316,29,17,19,072,29,19,44,070,34,24,35,215,32*74
$GPGSV,3,3,11,25,30,301,29,29,06,254,,32,06,304,17*4C
$GPGLL,5206.75339,N,12206.88816,W,225407.00,A,A*7F
$GPRMC,225408.00,A,5206.75337,N,12206.88814,W,0.058,,170616,,,A*6F

Я перепробовал все параметры кодирования, доступные на общей вкладке конфигурации запуска, но все они дали странные результаты, даже китайские символы!

Соответствующий код char array[255]; инициализировать буфер, а затем прочитать последовательные данные в буфер и вывести их в консоль:

while(true){
dev->read(array,255);
std::cout<<"-> "<<array<<std::endl;
}

0

Решение

Учитывая этот блок:

-> 02,51,176,30,03,10,027,17,06,60,088,33,12,68,295,36*79
$GPGSV,3,2,11,14,10,316,30,17,20,072,27,19,45,069,40,24,36,215,35*7E
$GPGSV,3,3,11,25,29,301,28,29,05,254,,32,07,305,33*40
$GPGLL,5206.75433,N,12206.88881,W,225153.00,A,A*78
.53*05
$GPGSV,3,1,11,¬é­N

добавив rn для представления двух символов CRLF, которые заканчивают строку данных NMEA, а затем просто посчитав количество символов между мусором, который я получаю

  0123456789ABCDEF
0 02,51,176,30,03,
1 10,027,17,06,60,
2 088,33,12,68,295
3 ,36*79rn$GPGSV,3
4 ,2,11,14,10,316,
5 30,17,20,072,27,
6 19,45,069,40,24,
7 36,215,35*7Ern$G
8 PGSV,3,3,11,25,2
9 9,301,28,29,05,2
A 54,,32,07,305,33
B *40rn$GPGLL,5206
C .75433,N,12206.8
D 8881,W,225153.00
E ,A,A*78rn.53*05r
F n$GPGSV,3,1,11,

255 символов

Точно один из них:

dev->read(array,255);

Дешевый взлом это

char array[256];

а потом

dev->read(array,sizeof(array)-1);
array[sizeof(array)-1] = '\0';

Но я думаю, что вам лучше с чем-то вроде этого:

int len = receiveUntil(array,sizeof(array), "\r\n")
if (len >= 0)
{
// checksum and parse
}
discardUntil ("$");

где

receiveUntil читает входящий поток в array пока он не найдет конец предложения NMEA, тогда null завершится array и возвращает количество прочитанных байтов или array собирается переполниться, и в этом случае он возвращает -1.

discardUntil выбрасывает все, пока не найдет начальный символ NMEA ‘$’

Бонусные баллы за замену receiveUntil с функцией сброса array когда он находит $ так что вы не пропустите ни одного сообщения, которое еще не было повреждено.

1

Другие решения

Оказывается, это не было проблемой с кодировкой. Я начал понимать, что это было что-то еще, когда я попытался сделать то же самое с NodeJS, и получил тот же результат.

Я забыл, что правильный способ считывания выходных данных с этого модуля GPS состоит в том, чтобы читать символы по одному, пока вы не нажмете терминатор перевода строки в конце строки, и затем работать с ним / войти в консоль.

Итак, мой код стал:

char array[255];
char c[1];
int i = 0;

while(true){
dev->read(c,1);

if(c[0] == '\n'){
i = 0;

std::cout<<"-> "<<array<<std::endl;

char *begin = array;
char *end = begin + sizeof(array);
std::fill(begin, end, 0);
}else{
array[i] = c[0];
++i;
}
}

Который сейчас работает отлично 🙂

0

По вопросам рекламы [email protected]