Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Передача указателя в качестве аргумента.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Jenya7
Есть такая функция.
Код
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char* pchr)
{
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
  
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], "/>\0", 3);
    
    pchr = strstr(xml_str, buf);
    if(pchr == NULL) return 0;
    else return 1;
}

Внутри функции pchr принимает правильное значение, все прекрасно.

Проверяем
Код
uint32_t  XML_PARSER_NewElement(char *xml_str, char *parent, char* el_name)
{
    char *pchr_test=NULL;

    if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test));
        return 0;
}

pchr_test остается 0. Подскажите где ошибка.
andrew_b
Цитата(Jenya7 @ Dec 20 2016, 13:33) *
Подскажите где ошибка.

В функцию передаётся копия указателя, поэтому вы изменяете копию.
Передавать надо указатель на указатель.

Код
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char** pchr)
   {
       uint32_t el_size = strlen(el_name);
       char buf[el_size+4];
    
       memcpy(&buf[0], "<", 1);
       memcpy(&buf[1], el_name, el_size);
       memcpy(&buf[el_size+1], "/>\0", 3);
      
       *pchr = strstr(xml_str, buf);
       if(*pchr == NULL) return 0;
       else return 1;
   }

uint32_t  XML_PARSER_NewElement(char *xml_str, char *parent, char* el_name)
   {
       char *pchr_test=NULL;
  
       if (!XML_PARSER_FindElementEnd(xml_str, parent, &pchr_test));
           return 0;
   }
Сергей Борщ
QUOTE (Jenya7 @ Dec 20 2016, 12:33) *
Подскажите где ошибка.
Ошибка в вашем стойком нежелании учить язык путем чтения документации. Потратьте наконец один день на чтение Кернигана и Ритчи.

Аргументы в функцию передаются по значению.
novikovfb
Цитата(Jenya7 @ Dec 20 2016, 14:33) *
Есть такая функция.
Код
// pchr - входное значение типа "указатель на char"
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char* pchr)
{
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
  
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], "/>\0", 3);
    
    pchr = strstr(xml_str, buf);// игнориуем исходное значение, заменяем его на результат strstr
    if(pchr == NULL) return 0;
    else return 1;
}

Внутри функции pchr принимает правильное значение, все прекрасно.

Проверяем
Код
uint32_t  XML_PARSER_NewElement(char *xml_str, char *parent, char* el_name)
{
    char *pchr_test=NULL;

    if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test));
        return 0;
}

pchr_test остается 0. Подскажите где ошибка.

При "проверке" внутри функции значение pchr меняется так, как написано, но нигде не сказано компилятору, что значение надо оттуда вытащить наружу в вызывающую функцию.
Для языка C можно переписать так:
Код
// ppchr - входное значение типа "указатель на указатель на char"
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char** ppchr)
{
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
  
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], "/>\0", 3);
    
    *ppchr = strstr(xml_str, buf);// по адресу ppchr записываем результат strstr
    if(ppchr == NULL) return 0;
    else return 1;
}
uint32_t  XML_PARSER_NewElement(char *xml_str, char *parent, char* el_name)
{
    char *pchr_test=NULL;

    if (!XML_PARSER_FindElementEnd(xml_str, parent, &pchr_test));// передаем адрес pchr_test - указатель на указатель на char
        return 0;
}

для языка C++ есть более интересная возможность - передача по ссылке
ucMike
if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test));
return 0;

Точка с запятой в первой строчке - так задумано?
Jenya7
Цитата(ucMike @ Dec 20 2016, 16:57) *
if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test));
return 0;

Точка с запятой в первой строчке - так задумано?

описка.

Цитата(novikovfb @ Dec 20 2016, 16:46) *
При "проверке" внутри функции значение pchr меняется так, как написано, но нигде не сказано компилятору, что значение надо оттуда вытащить наружу в вызывающую функцию.

упс... точно. надо указатель на указатель использовать. char** pchr. спасибо.

Цитата(Сергей Борщ @ Dec 20 2016, 16:46) *
Ошибка в вашем стойком нежелании учить язык путем чтения документации. Потратьте наконец один день на чтение Кернигана и Ритчи.

Аргументы в функцию передаются по значению.

Цитата
его пример другим наука.

sm.gif
megajohn
Цитата(Jenya7 @ Dec 20 2016, 13:33) *
Код
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char* pchr)
{
    char buf[el_size+4];
  
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], "/>\0", 3);
}


какая то магия понаписана

может попроще для людей сделать ?

Код
char buf[ el_size + sizeof( "</>" ) ];
sprintf( buff, "<%s/>",  el_name );
Jenya7
Цитата(megajohn @ Dec 20 2016, 17:48) *
какая то магия понаписана

может попроще для людей сделать ?

Код
char buf[ el_size + sizeof( "</>" ) ];
sprintf( buff, "<%s/>",  el_name );

вы считаете что монструозная sprint это попроще? sm.gif
Jenya7
кстати сделал проверку
Код
   #if USE_MEMCPY
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], ">\0", 2);
    #else
    memset(buf, '\0', el_size+4);
    strcat(buf,"<");
    strcat(buf, el_name);
    strcat(buf, ">");
    #endif

посмотрел листинг - размер кода с strcat почти в 2 раза меньше.
conan
Цитата(Jenya7 @ Dec 20 2016, 16:14) *
посмотрел листинг - размер кода с strcat почти в 2 раза меньше.
Зато memcpy скорее всего быстрее

Код
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
Хорошо, что в C++ пока нет такой мерзости как локальные массивы переменного размера
arhiv6
conan, а чем они Вам не нравятся?
Jenya7
Цитата(conan @ Dec 21 2016, 08:38) *
Зато memcpy скорее всего быстрее

Код
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
Хорошо, что в C++ пока нет такой мерзости как локальные массивы переменного размера

я думал над этим. тут конечно есть опасность stack overflow. но я думаю есть механизмы контроля. вроде регистр SP доступен. можно посмотреть где мы находимся в стаке и вычислить сколько осталось места?
Сергей Борщ
Не, массивы переменной длины иногда могут быть полезны. Но этот код является наглядной иллюстрацией к "если бы строители строили дома так же, как программисты пишут программы, то первый же залетный дятел порушил бы цивилизацию":
CODE
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
Если входной файл вдруг будет испорчен - можно легко нарваться на переполнение стека.

QUOTE (Jenya7 @ Dec 21 2016, 08:37) *
но я думаю есть механизмы контроля. вроде регистр SP доступен. можно посмотреть где мы находимся в стеке и вычислить сколько осталось места?
И где тут такие проверки?
Просто возвращайте 0 если el_size больше какого-то предела, на который у вас достаточно стека и в который заведомо укладываются все необходимые вам элементы.
Jenya7
Цитата(Сергей Борщ @ Dec 21 2016, 12:51) *
Не, массивы переменной длины иногда могут быть полезны. Но этот код является наглядной иллюстрацией к "если бы строители строили дома так же, как программисты пишут программы, то первый же залетный дятел порушил бы цивилизацию":
Код
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
Если входной файл вдруг будет испорчен - можно легко нарваться на переполнение стека.

И где тут такие проверки?
Просто возвращайте 0 если el_size больше какого-то предела, на который у вас достаточно стека и в который заведомо укладываются все необходимые вам элементы.

допустим размер стака 1К. А el_size 0.5К - вроде как места хватает. но я не знаю насколько заполнен стак до выделения места под el_size. есть код до него. вложенные ф-ции и.т.д и.т.п.
поэтому я думаю правильней сделать END_OF_STACK – SP.
conan
Цитата(arhiv6 @ Dec 21 2016, 09:15) *
conan, а чем они Вам не нравятся?

Не эстетично же. Как минимум sizeof выносится в runtime


Цитата(Jenya7 @ Dec 21 2016, 10:03) *
допустим размер стака 1К. А el_size 0.5К - вроде как места хватает. но я не знаю насколько заполнен стак до выделения места под el_size. есть код до него. вложенные ф-ции и.т.д и.т.п.
поэтому я думаю правильней сделать END_OF_STACK – SP.

Чушь
esaulenka
Цитата(Jenya7 @ Dec 20 2016, 15:05) *
вы считаете что монструозная sprint это попроще? sm.gif

Вообще-то, вся монструозная XML_PARSER_FindElementEnd() - это ад и ужас.
Не проще написать свою strstr(), которая знает, что шаблон, который мы ищем, должен быть с кавычками? Расход стека - единицы байт.

Это если "в лоб". А если XML-ка может быть испорченной, готовьте мыло с верёвкой. Полноценный парсер, который проверит все возможные ошибки, написать не очень просто. Даже если уметь писать на языке си...
Jenya7
Цитата(esaulenka @ Dec 21 2016, 15:37) *
Вообще-то, вся монструозная XML_PARSER_FindElementEnd() - это ад и ужас.

Вы еще другие мои ф-ции не видели.

Цитата(esaulenka @ Dec 21 2016, 15:37) *
Не проще написать свою strstr(), которая знает, что шаблон, который мы ищем, должен быть с кавычками? Расход стека - единицы байт.

Это если "в лоб". А если XML-ка может быть испорченной, готовьте мыло с верёвкой. Полноценный парсер, который проверит все возможные ошибки, написать не очень просто. Даже если уметь писать на языке си...


я пользовался minixml парсером. он конечно написан красиво. с полным функционалом. цена - 35К. он написан под GCC. перешел на IAR - в IAR не компилируется. вот решил написать свой велосипед.

а что страшного в обрамлении строки кавычками. строку по любому придется грузить в стек.
x893
Цитата(esaulenka @ Dec 21 2016, 12:37) *
Вообще-то, вся монструозная XML_PARSER_FindElementEnd() - это ад и ужас.
Не проще написать свою strstr(), которая знает, что шаблон, который мы ищем, должен быть с кавычками? Расход стека - единицы байт.

Это если "в лоб". А если XML-ка может быть испорченной, готовьте мыло с верёвкой. Полноценный парсер, который проверит все возможные ошибки, написать не очень просто. Даже если уметь писать на языке си...


На любом языке не просто. Но можно.
esaulenka
Цитата(Jenya7 @ Dec 21 2016, 13:34) *
а что страшного в обрамлении строки кавычками. строку по любому придется грузить в стек.

Один раз или два? В текущем варианте сначала в стеке (или не в стеке, я уж не знаю, что там за пределами этой функции) оказывается вариант без кавычек, а потом в стек кладётся вариант с кавычками.
Решение "найти '<', проверить, что сразу за ним нужная строка, проверить, что сразу за ним '/>' " никаких строк никуда не копирует.



Но я за решение "не строить свои велосипеды". Особенно такие велосипеды, которые могут поворачивать только налево (направо не предусмотрено. или даже просто не оттестировано).

Вот, к примеру, каркас для создания парсера: https://dev.yorhel.nl/yxml/man
Маллоков нет, размер минимальный.

Ну и mini-xml написан не под GCC, а на стандартном Си. Проще подточить под IAR, чем делать с нуля.
Jenya7
Цитата(esaulenka @ Dec 21 2016, 17:41) *
Один раз или два? В текущем варианте сначала в стеке (или не в стеке, я уж не знаю, что там за пределами этой функции) оказывается вариант без кавычек, а потом в стек кладётся вариант с кавычками.
Решение "найти '<', проверить, что сразу за ним нужная строка, проверить, что сразу за ним '/>' " никаких строк никуда не копирует.



Но я за решение "не строить свои велосипеды". Особенно такие велосипеды, которые могут поворачивать только налево (направо не предусмотрено. или даже просто не оттестировано).

Вот, к примеру, каркас для создания парсера: https://dev.yorhel.nl/yxml/man
Маллоков нет, размер минимальный.


Я хотел работать с Yxml. он только парсит элементы. а мне нужно и добавлять.
к тому же
Код
  #define BUFSIZE 4096
  void *buf = malloc(BUFSIZE);
  yxml_t x;
  yxml_init(&x, buf, BUFSIZE);

так и я умею sm.gif
Цитата(esaulenka @ Dec 21 2016, 17:41) *
Ну и mini-xml написан не под GCC, а на стандартном Си. Проще подточить под IAR, чем делать с нуля.

Да как подточить. Там инклюдиться куча системных хедеров которых в IAR не существует.

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.