TinyXML и проблема с тегами и форматированием

У меня проблема с TinyXML, которую я не могу исправить. Я расширил приложение MFC, используя C++ для работы. Приложение выполняет автоматизированное тестирование. После завершения он сохраняет все данные в файле XML. Ниже начала моего дерева DOM.

<?xml version="1.0" encoding="utf-8" ?>
<TestData>
<Operator>Alex</Operator>
<ParentBarCode>12345
</ParentBarCode>
<Measurements>

Проблема в том, что библиотека, кажется, добавляет случайную новую строку после 12345. Это должно быть:

<ParentBarCode>12345</ParentBarCode>

Не могли бы вы мне помочь, пожалуйста? Я пробовал все... Фрагмент кода ниже. Кроме того, есть ли способ удалить новую строку перед закрытием тега нового элемента, т.е. перед

</ParentBarCode>?? 
//Code starts here
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration("1.0","utf-8", "");
//doc.FirstChildElement();
doc.LinkEndChild(decl);
TiXmlElement *rootelement = new TiXmlElement("TestData");
doc.LinkEndChild(rootelement);
TiXmlText *textTestData = new TiXmlText("");
rootelement->LinkEndChild(textTestData);
//Operator node
TiXmlElement *Operator = new TiXmlElement("Operator"); 
//Tree root
rootelement->LinkEndChild(Operator);
TiXmlText *textOperator = new TiXmlText("Alex");
Operator->LinkEndChild(textOperator);
//ParentBarcode Node
TiXmlElement *barcode = new TiXmlElement("ParentBarCode"); 
//Tree root
rootelement->LinkEndChild(barcode);

//saving serial to a stringstream

stringstream serial;
serial << (DlgPtr->m_lSerialNumber);
std::string myserial = serial.str();
//Removing spaces
myserial.erase(std::remove_if(myserial.begin(),     myserial.end(),::isspace), myserial.end());

char buffer[sizeof(myserial) + 1];
//int ret = snprintf(buffer, sizeof(myserial), "%05ld", DlgPtr>m_lSerialNumber);
int ret = sprintf_s(buffer, sizeof(myserial), "%05ld", myserial);
const char * charSerial = buffer;
TiXmlText *textbarcode = new TiXmlText(charSerial);
barcode->LinkEndChild(textbarcode);

Никаких сообщений об ошибках, просто тег элемента не закрывается на той же строке. Я сделал небольшой проект песочницы с точно таким же деревом DOM, но там все работало нормально. Я подумал, может быть, есть еще одна проблема, которую я не вижу в sprintf_s?? Заранее спасибо.


person Stav    schedule 10.09.2019    source источник
comment
изменить sizeof(myserial) на myserial.size()   -  person Alan Birtles    schedule 10.09.2019
comment
или просто используйте TiXmlText *textbarcode = new TiXmlText(myserial.cstr());   -  person Alan Birtles    schedule 10.09.2019
comment
sprintf_s(buffer, sizeof(myserial), "%05ld", myserial); совершенно неправильно   -  person Alan Birtles    schedule 10.09.2019
comment
Хорошо. Как бы вы поступили вместо этого? int ret = snprintf_s (буфер, sizeof(myserial), %05ld, DlgPtr›m_lSerialNumber); кажется, работает нормально в коде. Кстати, все еще новичок в программировании на С++.   -  person Stav    schedule 10.09.2019
comment
Если эта строка работает, почему она закомментирована? Покажите минимально воспроизводимый пример с фактическим кодом, вызывающим вашу проблему.   -  person Alan Birtles    schedule 10.09.2019


Ответы (1)


Как указал @AlanBirtles в комментариях, эта часть вашего кода не очень хороша:

stringstream serial;
serial << (DlgPtr->m_lSerialNumber);
std::string myserial = serial.str();
//Removing spaces
myserial.erase(std::remove_if(myserial.begin(),     myserial.end(),::isspace), myserial.end());

char buffer[sizeof(myserial) + 1];
int ret = sprintf_s(buffer, sizeof(myserial), "%05ld", myserial);
const char * charSerial = buffer;
TiXmlText *textbarcode = new TiXmlText(charSerial);
barcode->LinkEndChild(textbarcode);

Вы начинаете с сильного преобразования DlgPtr->m_lSerialNumber в std::string:

stringstream serial;
serial << (DlgPtr->m_lSerialNumber);
std::string myserial = serial.str();

Это нормально, хотя начиная с С++ 11 вы также можете просто сделать:

std::string myserial = std::to_string(DlgPtr->m_lSerialNumber);

Затем вы удаляете пробелы из myserial, что не повредит, но я почти уверен, что их не нужно будет удалять, так как вы только что построили строку из одного целого числа.

Вот тогда все начинает идти не так.

Вы создаете буфер массива символов для записи вашего числа, но вы определяете его размер с помощью sizeof(myserial), что дает вам количество байтов, которые объект занимает в памяти, включая бухгалтерские данные, указатели vtable и т. д. Таким образом, вы также выделяете здесь много места; myserial.size() подойдет лучше.

Затем вы пытаетесь использовать sprintf_s для записи числа в новый буфер, но используете "%05ld" в качестве строки формата и std::string в качестве аргумента - это просто не сработает. "%05ld" говорит sprintf_s ожидать целое число в качестве входных данных (и дополняет его до 5 цифр дополнительными нулями), поэтому он просто берет этот аргумент, приводит его к типу int и интерпретирует первые 4 байта как число - что не имеет смысла, и вероятно, вызывает неопределенное поведение.

Это не только не делает то, что вы хотите, у вас уже есть строка с вашим номером, и вы можете просто вызвать myserial.c_str(), чтобы получить const char* с содержимым myserial. Это означает, что весь второй раздел можно заменить на:

TiXmlText *textbarcode = new TiXmlText(std::to_string(DlgPtr->m_lSerialNumber).c_str());
barcode->LinkEndChild(textbarcode);
person Frodyne    schedule 10.09.2019
comment
Я сделал некоторые изменения, как советовали. Использование TiXmlText *textbarcode = new TiXmlText(std::to_string(DlgPtr-›m_lSerialNumber).c_str()); штрих-код-›LinkEndChild(textbarcode); вместо массива символов. Тем не менее, xml выглядит следующим образом: ‹?xml version=1.0 encoding=utf-8 ?› ‹TestData› ‹Operator›Demo test‹/Operator› ‹ParentBarcode›01489 ‹/ParentBarcode› ‹Measurements› Проблема, как и прежде, заключается в том, что тег не закрывается на той же строке. Ничего не изменилось .. Что-то я все еще делаю неправильно? Не вижу. Если нет, то как переместить закрывающий тег в ту же строку, добавив дополнительный код? - person Stav; 11.09.2019