Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.89
NewEXE
4 / 4 / 1
Регистрация: 03.05.2014
Сообщений: 24
#1

TinyXML. Преобразовать TiXmlElement в TiXmlString, char[] или string - C++

17.05.2014, 10:10. Просмотров 1385. Ответов 25
Метки нет (Все метки)

Вообщем-то, задача проста (для тех, кто работал с библиотекой TinyXML). Но я первый раз с ней работаю, и вообще первый раз со сторонними библиотеками.
Имеется: объект, содержащий данные XML-тега (получено с помощью метода FirstChildElement, сохранено в объект типа TiXmlElement).
Нужно: преобразовать или в string (лучше всего), или в массив char или в TiXmlString (последний вариант, тогда нужно TiXmlString в string перевести).

Заранее спасибо за помощь.

Добавлено через 9 минут

Выложил ниже main() - точку входа. Коротенько опишу класс Sum. Имеет поля "сумма", "буквенный код", "курс доллара". Без полиморфизма и наследования.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
int main()
{
    setlocale(0, "");
 
    float any2rur, to_usd_into_rur;
    Sum s1(500, 8.5, "UAH");
 
    TiXmlDocument *xml_MAIN = new TiXmlDocument("XML_daily.asp.xml");
    if(!xml_MAIN->LoadFile())
        return 1;
    TiXmlElement *xml_ValCurs = 0;
    TiXmlElement *xml_Valute = 0;
    TiXmlElement *xml_CharCode = 0;
    TiXmlElement *xml_Name = 0;
    TiXmlElement *xml_Value = 0;
 
    xml_ValCurs = xml_MAIN->FirstChildElement("ValCurs");
    xml_Valute = xml_ValCurs->FirstChildElement("Valute");
    xml_CharCode = xml_Valute->FirstChildElement("CharCode");
    //delete xml_CharCode;
    xml_Name = xml_Valute->FirstChildElement("Name");
    //delete xml_Name;
    xml_Value = xml_Valute->FirstChildElement("Value");
 
    string str1 = (string)xml_CharCode; //вот это организовать
    string str2 = s1.GetCode();
 
    while(xml_Valute != NULL)
    {
         if(str1 != str2) //для этого условия сравнения string
        {
            xml_Valute = xml_Valute->NextSiblingElement("Valute");
        }
        xml_Value->QueryFloatAttribute("Value", &any2rur);
    }
    //cout << &any2rur;
}


Добавлено через 10 часов 35 минут
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.05.2014, 10:10
Здравствуйте! Я подобрал для вас темы с ответами на вопрос TinyXML. Преобразовать TiXmlElement в TiXmlString, char[] или string (C++):

Преобразовать const unsigned char* в std::string (или _bstr_t ) - C++
Здравствуйте старшие товарищи! Есть функция, которая возвращает результат типа const unsigned char*. а мне нужно получить ...

Как преобразовать char* в string и вывести переменную string на экран? - C++
for (int k = 0; k &lt; 10; k++) { int x = (int)rand() / RAND_MAX + rand() % 6 + 2; char *chars = new char; ...

Не удаётся преобразовать string в char - C++
Здравствуйте. Пользуюсь C++Builder. Создана форма с тремя TEdit + кнопка. Задача, при вводе в TEdit1 и TEdit2 числовых значений, ...

Преобразовать string в массив char - C++
Всем доброго времени суток!Как преобразовать string в массив char.

преобразовать программу из string в char - C++
Помогите преобразовать программу из string в char #include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;string&gt; #include &lt;fstream&gt; ...

Как преобразовать char в string - C++
Есть массив char buffer; есть переменная string X; как присвоить значение X допустим такое X=buffer+buffer;

25
outoftime
║XLR8║
511 / 433 / 33
Регистрация: 25.07.2009
Сообщений: 2,295
19.05.2014, 01:14 #16
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
NewEXE, настоятельно рекомендую соблюдать форматирование как у меня. Я много чего переделал, много чего оставил как есть, ибо очень много чего сделано "не как у людей", к примеру:

- название методов в камелкейсе начинаются с буквы нижнего регистра, т.е не GetSum а getSum
- если параметр не будет изменятся внутри функции\метода помечайте его как константный указатель на объект, тогда у вас не будет проблем если пользователь передаст константное значение, ибо преобразование T > const T - валидно, а const T > T возможно только через const_cast<T> и без него вызовет ошибку компиляции

И много много чего еще..

Как сделать нормальное преобразование char* в double для любой локали сделаешь сам, либо на форуме найдешь (кажется даже маны писали).

Собственно сам код:

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <string>
#include <tinyxml.h>
 
using namespace std;
 
class Sum
{
private:
    float sum;
    string code;
    float kurs;
 
public:
    // Собрал 4 конструктора в 1
    Sum(float IntSum = 1, float IntKurs = 1, string IntCode = "USD") {
        if (!(IntSum > 0 && IntKurs > 0)) {
            IntSum = 1;
            IntKurs = 1;
        }
        SetSum(IntSum);
        SetCode(IntCode);
        SetKurs(IntKurs);
    }
 
    // Так как передаваемый класс уже верифицировал валидность параметров
    // достаточно вызвать copy constructor-ы для полей класса
    Sum(const Sum& c) : sum(c.sum), code(c.code), kurs(c.kurs) { }
 
    void Init(float IntSum, float IntKurs, string IntCode) {
        if (IntSum > 0 && IntKurs > 0) {
            SetSum(IntSum);
            SetCode(IntCode);
            SetKurs(IntKurs);
        } else {
            SetSum(1);
            SetCode("UAH");
            SetKurs(1);
        }
    }
 
    void Print() const {
        cout << "Код валюты: \n" << code << endl << "Кол-во: " << sum << endl 
            << "Курс доллара: " << kurs << endl << endl;
    }
 
    void Print4float(const float &N) const {
        cout << N << endl;
    }
 
    void Sravn(const Sum &s2) const {
        if (sum > s2.sum)
            cout << "Первая сумма > Второй суммы";
        else if (sum < s2.sum)
            cout << "Первая сумма < Второй суммы";
        else 
            cout << "Суммы равны";
    }
 
    float Add(const Sum &s2) const {
        float Rezult;
        Rezult = sum + s2.sum;
        return Rezult;
    }
 
    float Convert() const {
        float Rezult;
        Rezult = sum / kurs;
        return Rezult;
    }
 
    float GetSum() const { return sum; }
 
    string GetCode() const { return code; }
 
    float GetKurs() const { return kurs; }
 
    void SetSum(float f) {
        sum = f < 0 ? 1 : f;
    }
 
    void SetCode(string s) {
        code = s.empty() ? "USD" : s;
    }
 
    void SetKurs(float f) {
        kurs = f <= 0 ? 1 : f;
    }
};
 
int main () {
    TiXmlDocument *xml_MAIN = new TiXmlDocument("XML_daily.asp.xml");
    // Если так делаешь выдеяй его пожирнее, что-бы в глаза кидалось
    // а то пропустишь это место и будешь думать почему код далее не исполняется
    if (!xml_MAIN->LoadFile()) 
    {
        return 1;
    }
 
    TiXmlElement *xml_ValCurs, *xml_Valute, *xml_CharCode, *xml_Value;
 
    xml_ValCurs = xml_MAIN->FirstChildElement("ValCurs");
    xml_Valute = xml_ValCurs->FirstChildElement("Valute");
    
    Sum s1(500, 8.5, "UAH");
    double value; // сюда схраним значение тега
 
    // проходим по всем полям "Valute"
    for (; xml_Valute != 0; xml_Valute = xml_Valute->NextSiblingElement("Valute")) {
        xml_CharCode = xml_Valute->FirstChildElement("CharCode");
        
        if (!strcmp(s1.GetCode().c_str(), xml_CharCode->GetText())) {
            xml_Value = xml_Valute->FirstChildElement("Value");
            // Старая сишная конвертация учитывает локаль неудобным образом
            // советую использовать stringstream для этих целей, либо другой
            // способ преобразования char* в double
            value = atof(xml_Value->GetText());
            break;
        }
    }
    cout << value << endl;
}

Bash
1
2
3
ruslan@TFTM-K53TA:~/Programming/c++/cyberforum$ make tinyxml && ./main 
clang++ main.cpp -o main -std=c++11 -ltinyxml -W
29
Добавлено через 7 минут
NewEXE, P.S. мне удалось уменьшить размер кода на 60 строк, что почти треть, не уменьшая при этом читабельности. Поработайте и выработайте свой стиль форматирование либо используйте чей-то, к примеру: c++ google coding style (хотя я использую немного другой)
1
0x10
2479 / 1654 / 248
Регистрация: 24.11.2012
Сообщений: 4,097
19.05.2014, 05:01 #17
Цитата Сообщение от outoftime Посмотреть сообщение
"не как у людей"
Цитата Сообщение от outoftime Посмотреть сообщение
- название методов в камелкейсе начинаются с буквы нижнего регистра, т.е не GetSum а getSum
Вот уж что непринципиально.

Хоть я сам и двинут на стиле, но в данном случае дело даже не в нем. Если говорить о качестве кода, то тут в большей части случаев я бы не давил ошибки невалидных параметров, подставляя какие-то значения по умолчанию, а кидал бы исключения.
1
NewEXE
4 / 4 / 1
Регистрация: 03.05.2014
Сообщений: 24
19.05.2014, 12:47  [ТС] #18
outoftime, большое спасибо за аудит кода и поправки! Я изучаю программирование первый год, важно выработать правильный стиль.
Сделал, как Вы советовали, через stringstream (сейчас кода при мне нет). Все работает (ура!), если бы не одно "но" - в xml в числах вместо точек стоит запятая...
Что можно тут придумать?
0
0x10
2479 / 1654 / 248
Регистрация: 24.11.2012
Сообщений: 4,097
19.05.2014, 13:04 #19
Цитата Сообщение от NewEXE Посмотреть сообщение
Что можно тут придумать?
Вариантов несколько.
1. Тупо в строке заменяем запятую на точку. Неправильно, зато быстро.
2. Устанавливаем локаль для потока. Пример кода, думаю, достаточно ясен:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <locale>
#include <sstream>
 
int main() {
    std::locale l("ru_RU");
 
    std::stringstream ss("3,14");
    ss.imbue(l);
 
    double pi;
    ss >> pi;
 
    std::cout << pi << std::endl;
    return 0;
}
1
outoftime
║XLR8║
511 / 433 / 33
Регистрация: 25.07.2009
Сообщений: 2,295
19.05.2014, 14:19 #20
Цитата Сообщение от NewEXE Посмотреть сообщение
Что можно тут придумать?
Все уже придумано до нас. На форуме эта тема поднималась не раз. (подпевай :)
0
NewEXE
4 / 4 / 1
Регистрация: 03.05.2014
Сообщений: 24
19.05.2014, 17:48  [ТС] #21
0x10, внушил локаль l("RU_ru"), реализовал функцию
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
double ToDouble(const char *p)
    {
        locale l("RU_ru");
        stringstream ss(p);
        ss.imbue(l);
        double d = 0;
        ss >> d;
        return d;
    }
/////////
int main()
    { // ........ //
        value = ToDouble(xml_Value->GetText());
    }
что-то не пойму, пишет
Кликните здесь для просмотра всего текста
terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

я так понял, что нельзя создавать такие вещи, как std::locale l("ru_RU");
outoftime,

Не по теме:

но все же мы еще раз спросим и сказать мы вас попросим

0
0x10
2479 / 1654 / 248
Регистрация: 24.11.2012
Сообщений: 4,097
19.05.2014, 17:52 #22
NewEXE, ru_RU - название локали в моей системе, в винде может отличаться. Видел, что пишут "Russian" - мб получится.
0
outoftime
║XLR8║
511 / 433 / 33
Регистрация: 25.07.2009
Сообщений: 2,295
19.05.2014, 18:19 #23
NewEXE, я бы сделал костыль. Определил сколько в строке символов не цифровых, и, если их количество равно одному, заменил его на http://www.cplusplus.com/reference/locale/numpunct/decimal_point/ после чего пользовался бы любым библиотечным способом без опаски.

Добавлено через 58 секунд
Идею взял отсюда http://habrahabr.ru/post/138957/
1
NewEXE
4 / 4 / 1
Регистрация: 03.05.2014
Сообщений: 24
19.05.2014, 19:47  [ТС] #24
0x10, у меня работает, если сделать так:
C++
1
locale l("");
но тогда выводится 31. Пробовал через
C++
1
setlocale(LC_NUMERIC, "");
тоже самое (31)
под катом несколько ссылок
Кликните здесь для просмотра всего текста
вот эту информацию я осилил (еще давно, но повторил) и попробовал все, что там было;
Вот тут предстоит задача обратная и немного полегче (чтобы в консоли выдавалась запятая). Решили с помощью класса. Не разобрался с ним;
не используют stringstream и не создают объектов типа locale.


Добавлено через 15 минут
outoftime, а что, если просто заменить запятую на точку после считывания? Костыль конечно, не такой изящный, как у Вас (), но проще. Типа так: s = s->Replace(',' , '.'); (но так сработает с System::String^ ! Поищу подобную для std::string)
Нашел http://www.cplusplus.com/reference/string/string/replace/

Добавлено через 17 минут
ДА!!! Я сделал это!
C++
1
2
3
4
string str;
str = xml_Value->GetText();
str.replace(str.find(","), 1, ".");
value = ToDouble(str);
Добавлено через 3 минуты
Теперь осталось выяснить, как получить xml сразу из asp
0
outoftime
║XLR8║
511 / 433 / 33
Регистрация: 25.07.2009
Сообщений: 2,295
19.05.2014, 21:02 #25
Цитата Сообщение от NewEXE Посмотреть сообщение
Теперь осталось выяснить, как получить xml сразу из asp
Имя файла не обязательно должно иметь расширение .asp, главное чтобы язык разметки был валидным. В крайнем случае можно обрезать до нужной части.
0
NewEXE
4 / 4 / 1
Регистрация: 03.05.2014
Сообщений: 24
19.05.2014, 21:45  [ТС] #26
outoftime, с данным парсером не прокатило. Мне посоветовал 0x10 использовать URLDownloadToFile или cURL
0
19.05.2014, 21:45
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.05.2014, 21:45
Привет! Вот еще темы с ответами:

Как преобразовать string в char*? - C++
Как преобразовать string в char* и отправить как аргумент наименьшими усилиями? #include &lt;iostream&gt; #include &lt;string&gt; using...

Где и почему используют ту или иную строку std::string, char[], System::String^ ? - C++
Где и почему используют ту или иную строку std::string, char, System::String^ ? Объясните пожалуйста где нужно использовать...

Как преобразовать переменную string в массив char[]? - C++
Есть переменная string и массив char как записать переменную типа string в такой массив ? String X=&quot;test&quot;; char Mass; ...

Как преобразовать объект string в строку char*? - C++
Доброго времени суток! Недавно я писал код, и обнаружил, что в качестве имя файла при объявлении объектов ifstream/ofstream нельзя...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
26
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru