URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 10022
[ Назад ]

Исходное сообщение
"sscanf парсер"

Отправлено microbash , 08-Июл-15 12:32 
Прошу совета как получить желаемый результат.

Код такой:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char  p1[100];

char *soap=
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<rows> <row> AAA <row> <row> BBB <row> </rows>\
</soap:Body>\
</soap:Envelope>\
";

char *soap_template =
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<rows> %s </rows>\
</soap:Body>\
</soap:Envelope>\
";

int main()
{

   sscanf( soap, soap_template, &p1);

   printf("%s",p1);
   printf("\n");

   return(0);
}


Результат:
<row>

Желаемый результат:
<row> AAA <row> <row> BBB <row>



Содержание

Сообщения в этом обсуждении
"sscanf парсер"
Отправлено fail , 08-Июл-15 13:53 
> Прошу совета как получить желаемый результат.
> char *soap=
> "\
> <soap:Envelope>\
>  <soap:Header>\
>  </soap:Header>\
>  <soap:Body>\
>  <rows> <row> AAA <row> <row> BBB <row> </rows>\

для начала, а не <row> AAA </row> <row> BBB </row> ?

>  </soap:Body>\
>  </soap:Envelope>\
> ";


"sscanf парсер"
Отправлено microbash , 08-Июл-15 14:22 
У меня есть как бы блок записей. Этих записей заранее неизвестно сколько, от 0 до 20 например. Также есть могу добавить тег с количеством этих записей. Например так:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char  p1[100], p2[100];

char *soap=
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<count> 2 </count>
<rows> <row> AAA <row> <row> BBB <row> </rows>\
</soap:Body>\
</soap:Envelope>\
";

char *soap_template =
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<count> %s </count>
<rows> %s </rows>\
</soap:Body>\
</soap:Envelope>\
";

int main()
{

   sscanf( soap, soap_template, &p1, &p2);

   printf("%s %s",p1,p2);
   printf("\n");

   return(0);

Если вы предлагает рассмотреть второй вариант без тегов <rows> </rows>, то как к нему задать шаблон при переменном значении записей?



"sscanf парсер"
Отправлено fail , 08-Июл-15 16:20 

> Если вы предлагает рассмотреть второй вариант без тегов <rows> </rows>, то как
> к нему задать шаблон при переменном значении записей?

Честно говоря со sscanf() не пересекался плотно,
взгляд резануло вот это :
>> <rows> <row> AAA <row> <row> BBB <row> </rows>

<row> AAA <row> <= закрывающий тег - нету ?!
<row> BBB <row> <= ... тоже

P.S.:
из man sscanf
...
s Matches a sequence of non-white-space characters; the next pointer must be a pointer  to char, and the array must be large enough to accept all the sequence and the termi-
nating  NUL character.  The input string stops at white space or at the maximum field width, whichever occurs first.
...

если правильно понял, должно быть что-то вроде { без пробальных символов(пробел, табуляция и т.д.) }:
...<rows><row>AAA</row><row>BBB</row></rows>...


"sscanf парсер"
Отправлено microbash , 08-Июл-15 19:47 
Закрывающиеся теги есть конечно. Это ошибка в моем описании.
Вот верный вариант.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char  p1[100], p2[100];

char *soap=
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<count> 2 </count>
<rows> <row> AAA </row> <row> BBB </row> </rows>\
</soap:Body>\
</soap:Envelope>\
";

char *soap_template =
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<count> %s </count>
<rows> %s </rows>\
</soap:Body>\
</soap:Envelope>\
";

int main()
{

   sscanf( soap, soap_template, &p1, &p2);

   printf("%s %s",p1,p2);
   printf("\n");

   return(0);


"sscanf парсер"
Отправлено fail , 08-Июл-15 16:30 
> Если вы предлагает рассмотреть второй вариант без тегов <rows> </rows>, то как
> к нему задать шаблон при переменном значении записей?

Думается,
вариант из вопроса (самый первый)

>> <rows> <row> AAA <row> <row> BBB <row> </rows>\

отсюда пробелы нафиг.

P.S.:
читаем мануалы внимательней



"sscanf парсер"
Отправлено microbash , 08-Июл-15 20:35 
Пока не совсем понимаю разницу с пробелами и без. Результат вроде бы одинаковый. Или не совсем?



"sscanf парсер"
Отправлено fail_ , 08-Июл-15 21:23 
> Пока не совсем понимаю разницу с пробелами и без. Результат вроде бы
> одинаковый. Или не совсем?

due to ( man sscanf ):

...
s Matches a sequence of non-white-space characters; the next pointer must be a pointer  to char, and the array must be large enough to accept all the sequence and the termi-
nating  NUL character.  The input string stops at white space or at the maximum field width, whichever occurs first.
...

имo, причиниа в этом - Matches a sequence of non-white-space characters...

Из:
>> Прошу совета как получить желаемый результат.
>> Код такой:
>> ...
>> <rows> <row> AAA <row> <row> BBB <row> </rows>\

заменить на
<rows> <row>AAA</row><row>BBB</row> </rows>\


"sscanf парсер"
Отправлено microbash , 09-Июл-15 08:03 
Большое спасибо за идеи.
Тут ключ к пониманию - "The input string stops at white space".
Теперь сделал вот так:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char  p1[100];

char *soap=
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<rows>\
<row>AAA</row>\
<row>BBB</row>\
<row>CCC</row>\
<row>DDD</row>\
<row>EEE</row>\
<row>FFF</row>\
<row>GGG</row>\
<row>JJJ</row>\
<row>HHH</row>\
</rows>\               // One white space before </rows> for stop input
</soap:Body>\
</soap:Envelope>\
";

char *soap_template =
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<rows>%s</rows>\
</soap:Body>\
</soap:Envelope>\
";

int main()
{

   sscanf( soap, soap_template, &p1);

   printf("%s",p1);
   printf("\n");

   return(0);
}

Результат:
<row>AAA</row><row>BBB</row><row>CCC</row><row>DDD</row><row>EEE</row><row>FFF</row><row>GGG</row><row>JJJ</row><row>HHH</row>

На данной стадии вполне годится. :)


"sscanf парсер"
Отправлено fail , 09-Июл-15 09:30 
> Большое спасибо за идеи.
> Тут ключ к пониманию - "The input string stops at white space".

и

"Matches a sequence of non-white-space characters "

> Результат:
> <row>AAA</row><row>BBB</row><row>CCC</row><row>DDD</row><row>EEE</row><row>FFF</row><row>GGG</row><row>JJJ</row><row>HHH</row>
> На данной стадии вполне годится. :)


"sscanf парсер"
Отправлено microbash , 11-Июл-15 13:10 
Вообщем в итоге пока приостановил опыты с sscanf, т.к. есть претензии к его функционалу.
Неоднозначные результаты на различные входящие данные.
:(



"sscanf парсер"
Отправлено Andrey Mitrofanov , 08-Июл-15 14:46 
> Желаемый результат:
> <row> AAA <row> <row> BBB <row>

 <soap:Body>\
-<rows> %s </rows>\
+<rows> %31c </rows>\
</soap:Body>\


"sscanf парсер"
Отправлено microbash , 08-Июл-15 15:40 
Решение оригинальное, но к сожалению подходит только под конкретные исходные данные.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char  p1[100];

char *soap=
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<rows>\
<row> AAA </row>\
<row> BBB </row>\
<row> CCC </row>\
<row> DDD </row>\
<row> EEE </row>\
</rows>\
</soap:Body>\
</soap:Envelope>\
";

char *soap_template =
"\
<soap:Envelope>\
<soap:Header>\
</soap:Header>\
<soap:Body>\
<rows> %200c </rows>\
</soap:Body>\
</soap:Envelope>\
";

int main()
{

   sscanf( soap, soap_template, &p1);

   printf("%s",p1);
   printf("\n");

   return(0);
}


Результат:
<row> AAA </row> <row> BBB </row> <row> CCC </row> <row> DDD </row> <row> EEE </row> </rows> </soap:Body> </soap:Envelope>



"sscanf парсер"
Отправлено Andrey Mitrofanov , 08-Июл-15 18:19 
> Прошу совета как получить желаемый результат.
>    sscanf( soap, soap_template, &p1);
> Результат:
> <row>
> Желаемый результат:
> <row> AAA <row> <row> BBB <row>

Я извиняюсь, именно Си и именно scanf() обязательны?

Если можно шеллом с пайпом, то 1 grep (чтоб токенизацию не делать awk-ом) + 1 awk в одну строку.


"sscanf парсер"
Отправлено Andrey Mitrofanov , 08-Июл-15 18:22 
>в одну строку.

&& забить на таги Envelope/Header/Body.


"sscanf парсер"
Отправлено microbash , 08-Июл-15 19:51 
Нужен C или С++, т.е. универсальный компилятор, который работает на любой платформе, в том числе мобильной. Я не хочу быть привязан к платформе или к ОС.


"sscanf парсер"
Отправлено Andrey Mitrofanov , 08-Июл-15 19:55 
> Нужен C или С++, т.е. универсальный компилятор, который работает на любой платформе,

Парсеры пишет bison, токенайзеры - flex. Определяешь грамматику - и вперёд!

> в том числе мобильной. Я не хочу быть привязан к платформе или к ОС.

А ещё можешь iZEN-а позвать и попилить с ним на джавве прямо на форуме. Показательно.

++Дедушка Мо^WяЗЕН, выходи!


"sscanf парсер"
Отправлено Alex_S , 10-Июл-15 04:47 
>> Нужен C или С++, т.е. универсальный компилятор, который работает на любой платформе,
> Парсеры пишет bison, токенайзеры - flex. Определяешь грамматику - и вперёд!
>> в том числе мобильной. Я не хочу быть привязан к платформе или к ОС.
> А ещё можешь iZEN-а позвать и попилить с ним на джавве прямо
> на форуме. Показательно.
> ++Дедушка Мо^WяЗЕН, выходи!

кстати, чо ,  strtok  щас чо, некошерен ?   можно ж , накрайняк .


"sscanf парсер"
Отправлено microbash , 10-Июл-15 10:38 
Каким образом из strtok можно получить простой xml-парсер?



"sscanf парсер"
Отправлено Andrey Mitrofanov , 10-Июл-15 18:20 
> Каким образом из strtok можно получить простой xml-парсер?

Программированием и, по необходимости, упрощением.

Впрочем, попробуйте Ваш способ -- ждать удовлетворяющего Вас решения на форуме.


"sscanf парсер"
Отправлено microbash , 11-Июл-15 13:20 
Ну почему же сразу "ждать на форуме".
На форуме я задаю вопрос с тем чтобы услышать мнение людей, у которых уже есть опыт.
Сам конечно тоже самостоятельно веду поиски.
Сейчас нашел вроде бы неплохой легковесный парсер на С: http://dev.yorhel.nl/yxml
Пока с ним эспериментирую.


"sscanf парсер"
Отправлено igor , 27-Июл-15 11:20 
> int main()
> {
>    sscanf( soap, soap_template, &p1);
>    printf("%s",p1);
>    printf("\n");
>    return(0);
> }

Встречный вопрос: чем не угодил libxml2 (XPath) или libexpat ?



"sscanf парсер"
Отправлено pavlinux , 16-Авг-15 02:17 
> Встречный вопрос: чем не угодил libxml2 (XPath) или libexpat ?

Сшник должен написать всё сам.
В конечном итоге должен получиться гигабайтный с-файлик с 1000000 #define,
но умеющий партисить гигабайтный XML за мильярд тактов процессора.