LINUX.ORG.RU

HEX to char (в программе на СИ)

 


0

1

Здравствуйте.

Есть сервер на СИ, который должен принимать строку из браузера отправленную POST-запросом через Ajax. Строки (в браузере) вводятся через поля <input>. Так вот, некоторые символы приходят в виде HEX, например - dima:dimon приходит в таком виде - dima%3Adimon.

Как это переводить в читаемые символы?


Ответ на: комментарий от stD

Оставлю это для таких как я)))...

/*char xex[4] = {0,};
  xex[0] = '0';
  xex[1] = 'x';
  xex[2] = '5';
  xex[3] = 'B';*/

  char xex[] = "0x5B"; // символ - [         
               
  long int sim = strtol(xex, NULL, 0);
  printf("SIMVOL:%c\n", (char)sim);
stD
() автор топика
Ответ на: комментарий от mersinvald

Спасибо, что объяснил мою шутку

Спасибо что привнесли глубокую иронию. (без сарказма)

stD
() автор топика

гугли urldecode в сишном исполнении

anonymous
()
Ответ на: комментарий от stD

Ещё немного в продолжение темы. Выше описанным способом, стали приниматься русские буквы, вот кусок кода:

       char *p = NULL;

       if((p = strstr(str_from_buf,"tochdost=")) != NULL) 
        {
          int i = 0;
          int ot = (p - str_from_buf) + 9;
          for(; i < INPUTDAT - 1; i++)
           {
             tochdost[i] = str_from_buf[ot];

             if(tochdost[i] == '%')
              {
                char xex[4] = {0,};
                xex[0] = '0';
                xex[1] = 'x';
                xex[2] = str_from_buf[++ot];
                xex[3] = str_from_buf[++ot];
                long int sim = strtol(xex, NULL, 0);
                char c = (char)sim; 
                tochdost[i] = c;
              }

             ot++;

             if(tochdost[i] == '&') 
              {
                tochdost[i] = '\0';
                printf("R1:%s_END\n", tochdost);
                break;
              }
           }
        }

Понимаю что построил «велосипед» и делать подобное нужно с помощью указателей, но тем не менее, имеет ли право на существование такая конструкция?

stD
() автор топика
Ответ на: комментарий от anonymous

А почему 5 ? (char xex[5]=«0xff»;)

stD
() автор топика
Ответ на: комментарий от mersinvald

Если хех[4], то пишет это:

==6465== Conditional jump or move depends on uninitialised value(s)
==6465==    at 0x50925C6: ____strtol_l_internal (strtol_l.c:438)
==6465==    by 0x40255A: main (in /home/dima/Dropbox/ci/mrardumining/mrardumining)
==6465== 
==6465== Conditional jump or move depends on uninitialised value(s)
==6465==    at 0x5092594: ____strtol_l_internal (strtol_l.c:442)
==6465==    by 0x40255A: main (in /home/dima/Dropbox/ci/mrardumining/mrardumining)
==6465== 
==6465== Use of uninitialised value of size 8
==6465==    at 0x509269D: ____strtol_l_internal (strtol_l.c:466)
==6465==    by 0x40255A: main (in /home/dima/Dropbox/ci/mrardumining/mrardumining)
==6465== 
R1:дима_END

А если хех[5], то эта ошибка исчезает. Если не затруднит, поясните, что это значит?

stD
() автор топика
Ответ на: комментарий от stD

                    12345 +1 ( +1 потоому что автоматически добавляется \0 в конец)
    char str1[6] = "hello";

                   1   2   3   4   5   6  << если считать по количеству 
                   0   1   2   3   4   5  << если считать по индексам с 0
    char str2[6]={'h','e','l','l','o','\0'}; << другая запись того же самого
              ^
              |-> размер массива задаётся по количеству элементов
  

Deleted
()
Ответ на: комментарий от stD

Я идиот.

Ничего подобного, к этому просто нужно привыкнуть, у меня ситуация наоборот была. Я когда то на хлебозаводе работал оператором, а у нас грузчик палец поломал ну и домой ушёл и экспедитора не было, а хлеб то свежий надо быстро грузить в машины и развозить быстрее ну я и загрузил и маршрутные листы составил.... только вот лотки с хлебом загружая в машины я считал с нуля ахахаха в итоге отправил не помню уже по документам 110 лотков вместо 100 ахах )) Было дело, вот тогда то я реально чувствовал себя идиотом и ведь не объяснишь никому почему я так посчитал ))))) Так что, просто зазубри это касательно сишных «строк» ))

Deleted
()
Ответ на: комментарий от stD

Пойду в кубики играть.

А чё бы нет, некоторые вон сначала блок схемы алгоритмов рисуют, потом документируют, потом TDD пишут, а уже потооом сам результирующий код. Я иногда перед тем как писать просто в блокнотике рисую как данные в структурах лучше хранить, какой набор функций мне понадобится для их обработки и прочее. Взял кубиков маленьких оклеил их бумагой белой нарисовал на них блок элементы и вот в такой позе сиди от скуки на столе алгоритм складывай ::)

Deleted
()
Ответ на: комментарий от stD

Тулсетом лучше обрасти и пручись его не игнорировать, на сишке все равно нельзя писать без инструментов даже если у тебя icq >> 100.

https://eax.me/c-static-analysis/

Если нуб, то посиди какое-то хотя бы на -Wextra — оно выводит на кучу того, о чем даже не подозреваешь.

anonymous
()
Ответ на: комментарий от Deleted

А чё бы нет, некоторые вон сначала блок схемы алгоритмов рисуют, потом документируют, потом TDD пишут, а уже потооом сам результирующий код.

Я где-то читал
О людях, что спят по ночам.
Ты можешь смеяться - клянусь, я читал это сам...
(БГ)
hobbit ★★★★★
()
Ответ на: комментарий от Deleted

Поиграл я в кубики и пришёл к выводу, что в данном случае я не согласен с компилятором. Зачем мне там ноль на конце если эта конструкция в середине строки находится.

stD
() автор топика
Ответ на: комментарий от stD

Нультерминал тоесть '\0' Нужен для указания конца строки, строк как таковых в си нет и не надо, это просто массивы uint8_t значений запись вида «hello» это упращение, сахар по иному что бы не писать {'h','e','l','l','o','\0'} ты можешь вставить нуль терминал в середину любой строки и все обрабатывающие функции printf/str_blablabla будут считать что там где ты его вставил кончилась строка. Если тебе нужно точно указать то просто вместо «hello» пишешь {'h','e','l','l','o'} без нуль терминала, но!!! таую «строку» нельзя передавать в функции типа printf и подобные, тоесть в те что принимают char * str без указания размера, потому что ты словишь сегфолт тоесть выход за пределы массива, как по твоему функции определят где кончаются твои данные? По '\0' они это и узнают или по явному указанию размера если они это поддерживают. В си нет контроля границ данных, именно ты должен это контролировать. Но так как '\0' нужно часто было введено упращение записи символьных массивов в виде заключения в двойные кавычки )

Deleted
()
Ответ на: комментарий от stD

Зачем мне там ноль на конце если эта конструкция в середине строки находится.

Ну и хрен с ней, тебе 8бит жалко?

Deleted
()
Ответ на: комментарий от stD

А в целом тебе ещё многое узнать придётся, язык только с виду простой ))))))))) Но по моему мнению он золотая середина среди всех ) У тебя всегда есть выбор как и что делать.

Deleted
()
Ответ на: комментарий от stD

пришёл к выводу, что в данном случае я не согласен с компилятором

В компиляторах бывают баги, и достаточно часто. Но вероятность того, что ты столкнёшься с одним из них, исчезающе мала.

Если тебя не устраивает язык, который ты выбрал, значит ты выбрал не тот язык. Очень похоже, что вместо решения задачи ты воюешь с компилятором и отладчиком. Возьми скриптовый язык, например Python.

i-rinat ★★★★★
()
Ответ на: комментарий от Deleted

Ну и хрен с ней, тебе 8бит жалко?

Конечно не жалко, просто мне думалось, что этот ноль разобьёт строку.

stD
() автор топика
Ответ на: комментарий от i-rinat

В компиляторах бывают баги

Я не говорил что это баг, просто не могу правильно изложить ход своих мыслей. Понятно что инициализация массива происходит не правильно (char xex[4] = {0,};) и на конце нужен ноль чтоб разделить области памяти, но мне то в данном случае это не нужно.

А язык мне чертовски нравится, а питоны всякие в жопу. По мере изучения понимаю, что на нём можно написать ВСЁ и главное для чего угодно (я ещё с МК играюсь).

stD
() автор топика
Ответ на: комментарий от stD

Помогите разобраться с valgrind'ом, почитал про него вот здесь - https://www.opennet.ru/base/dev/valgrind_memory.txt.html и вроде что-то понятно, но всё равно не понятно))).

Вот его вывод:

==20050== Process terminating with default action of signal 2 (SIGINT)
==20050==    at 0x4E466DD: ??? (syscall-template.S:81)
==20050==    by 0x401C3F: main (in /home/dima/Dropbox/ci/mrardumining/mrardumining)
==20050== 
==20050== HEAP SUMMARY:
==20050==     in use at exit: 544 bytes in 2 blocks
==20050==   total heap usage: 19 allocs, 17 frees, 4,065 bytes allocated
==20050== 
==20050== Searching for pointers to 2 not-freed blocks
==20050== Checked 16,875,072 bytes
==20050== 
==20050== 272 bytes in 1 blocks are possibly lost in loss record 1 of 2
==20050==    at 0x4C2C9B4: calloc (vg_replace_malloc.c:711)
==20050==    by 0x4012FE4: allocate_dtv (dl-tls.c:296)
==20050==    by 0x4012FE4: _dl_allocate_tls (dl-tls.c:460)
==20050==    by 0x4E3FD92: allocate_stack (allocatestack.c:589)
==20050==    by 0x4E3FD92: pthread_create@@GLIBC_2.2.5 (pthread_create.c:500)
==20050==    by 0x401A5A: main (in /home/dima/Dropbox/ci/mrardumining/mrardumining)
==20050== 
==20050== 272 bytes in 1 blocks are possibly lost in loss record 2 of 2
==20050==    at 0x4C2C9B4: calloc (vg_replace_malloc.c:711)
==20050==    by 0x4012FE4: allocate_dtv (dl-tls.c:296)
==20050==    by 0x4012FE4: _dl_allocate_tls (dl-tls.c:460)
==20050==    by 0x4E3FD92: allocate_stack (allocatestack.c:589)
==20050==    by 0x4E3FD92: pthread_create@@GLIBC_2.2.5 (pthread_create.c:500)
==20050==    by 0x401AA0: main (in /home/dima/Dropbox/ci/mrardumining/mrardumining)
==20050== 
==20050== LEAK SUMMARY:
==20050==    definitely lost: 0 bytes in 0 blocks
==20050==    indirectly lost: 0 bytes in 0 blocks
==20050==      possibly lost: 544 bytes in 2 blocks
==20050==    still reachable: 0 bytes in 0 blocks
==20050==         suppressed: 0 bytes in 0 blocks
==20050== 
==20050== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==20050== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Где искать эти ошибки? То есть как действовать дальше?

stD
() автор топика
Ответ на: комментарий от stD

Если ты про xex[], то тебе так или иначе придется ставить ноль после hex-цифр, иначе strtol не поймет, где кончается строка и начнинается UB. Сегодня тебе повезло, завтра будет новый день. Если просто про литералы, то они всегда на ноль кончаются, независимо от согласия.

anonymous
()
Ответ на: комментарий от stD

Ищешь среди имен функций знакомые, смотришь где лично делал этот *alloc/new/create, смотришь где соответствующий ему *free/delete/release/destroy и почему он не вызывается. Если не нашел, спрашиваешь себя почему его нет. Как-то так.

anonymous
()
Ответ на: комментарий от anonymous

Ну вот он пишет - at 0x4C2C9B4: calloc (vg_replace_malloc.c:711)

Но у меня нигде калок не делается, мне кажется что-то с потоками не так.

stD
() автор топика
Ответ на: комментарий от stD

При старте программы пишет это:

--26576-- REDIR: 0x4019e20 (ld-linux-x86-64.so.2:strlen) redirected to 0x38056a61 (vgPlain_amd64_linux_REDIR_FOR_strlen)
--26576-- Reading syms from /usr/local/lib/valgrind/vgpreload_core-amd64-linux.so
--26576-- Reading syms from /usr/local/lib/valgrind/vgpreload_memcheck-amd64-linux.so
==26576== WARNING: new redirection conflicts with existing -- ignoring it
--26576--     old: 0x04019e20 (strlen              ) R-> (0000.0) 0x38056a61 vgPlain_amd64_linux_REDIR_FOR_strlen
--26576--     new: 0x04019e20 (strlen              ) R-> (2007.0) 0x04c2dca0 strlen
--26576-- REDIR: 0x4019bd0 (ld-linux-x86-64.so.2:index) redirected to 0x4c2d850 (index)
--26576-- REDIR: 0x4019df0 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4c2edf0 (strcmp)
--26576-- REDIR: 0x401ab40 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4c31e30 (mempcpy)
--26576-- Reading syms from /lib/x86_64-linux-gnu/libpthread-2.19.so
--26576--   Considering /lib/x86_64-linux-gnu/libpthread-2.19.so ..
--26576--   .. CRC mismatch (computed 1382eed1 wanted 4a16bf62)
--26576--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libpthread-2.19.so ..
--26576--   .. CRC is valid
--26576-- Reading syms from /lib/x86_64-linux-gnu/libc-2.19.so
--26576--   Considering /lib/x86_64-linux-gnu/libc-2.19.so ..
--26576--   .. CRC mismatch (computed dc5fac54 wanted 7053531b)
--26576--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.19.so ..
--26576--   .. CRC is valid
--26576-- REDIR: 0x50e2070 (libc.so.6:strcasecmp) redirected to 0x4a25713 (_vgnU_ifunc_wrapper)
--26576-- REDIR: 0x50e4360 (libc.so.6:strncasecmp) redirected to 0x4a25713 (_vgnU_ifunc_wrapper)
--26576-- REDIR: 0x50e1840 (libc.so.6:memcpy@GLIBC_2.2.5) redirected to 0x4a25713 (_vgnU_ifunc_wrapper)
--26576-- REDIR: 0x50dfad0 (libc.so.6:rindex) redirected to 0x4c2d530 (rindex)
--26576-- REDIR: 0x50dfa90 (libc.so.6:strncpy) redirected to 0x4a25713 (_vgnU_ifunc_wrapper)
--26576-- REDIR: 0x50f4c20 (libc.so.6:__strncpy_sse2_unaligned) redirected to 0x4c2e270 (__strncpy_sse2_unaligned)
--26576-- REDIR: 0xffffffffff600400 (???:???) redirected to 0x38056a4d (vgPlain_amd64_linux_REDIR_FOR_vtime)
--26576-- REDIR: 0x50d7a80 (libc.so.6:malloc) redirected to 0x4c2abb6 (malloc)
--26576-- REDIR: 0x50e0720 (libc.so.6:__GI_strstr) redirected to 0x4c320c0 (__strstr_sse2)
--26576-- REDIR: 0x50dddd0 (libc.so.6:strlen) redirected to 0x4c2dbe0 (strlen)
--26576-- REDIR: 0x50d8120 (libc.so.6:free) redirected to 0x4c2bcd0 (free)
--26576-- REDIR: 0x50e6a90 (libc.so.6:__GI_memcpy) redirected to 0x4c2f790 (__GI_memcpy)
--26576-- REDIR: 0x50e12b0 (libc.so.6:__GI_memcmp) redirected to 0x4c306e0 (__GI_memcmp)
--26576-- REDIR: 0x50dd850 (libc.so.6:__GI_strcpy) redirected to 0x4c2dda0 (__GI_strcpy)
--26576-- REDIR: 0x50dc3c0 (libc.so.6:__GI_strcmp) redirected to 0x4c2ed00 (__GI_strcmp)
--26576-- REDIR: 0x50e8bc0 (libc.so.6:rawmemchr) redirected to 0x4c31990 (rawmemchr)
--26576-- REDIR: 0x50e8dd0 (libc.so.6:strchrnul) redirected to 0x4c31950 (strchrnul)
--26576-- REDIR: 0x50ddf90 (libc.so.6:strnlen) redirected to 0x4c2db80 (strnlen)
--26576-- REDIR: 0x50e1a20 (libc.so.6:__GI_mempcpy) redirected to 0x4c31b60 (__GI_mempcpy)
Write to Warning_Access.log:
START
--26576-- REDIR: 0x50d8550 (libc.so.6:calloc) redirected to 0x4c2c91e (calloc)
--26576-- REDIR: 0x50e18d0 (libc.so.6:memset) redirected to 0x4c31090 (memset)

Скажите, это ошибки или что это? После этого никаких сообщений больше не выводит.

stD
() автор топика
Ответ на: комментарий от anonymous

Если ты про xex[], то тебе так или иначе придется ставить ноль после hex-цифр, иначе strtol не поймет

За это спасибо.

stD
() автор топика
Ответ на: комментарий от stD

calloc by by by by pthread_create by main

Треды создаешь, но не удаляешь, судя по всему. Смотри то, что сам лично вызывал, все остальное уже внутри pthread_create случилось.

anonymous
()
Ответ на: комментарий от stD

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

anonymous
()
Ответ на: комментарий от anonymous

Треды создаешь, но не удаляешь

У меня там два потока создаётся, которые в цикле работают (один от МК данные принимает, другой как счётчик работает), ну а web-сервер в main крутится.

Видимо эти ошибки...

==20050== LEAK SUMMARY:
==20050==    definitely lost: 0 bytes in 0 blocks
==20050==    indirectly lost: 0 bytes in 0 blocks
==20050==      possibly lost: 544 bytes in 2 blocks
==20050==    still reachable: 0 bytes in 0 blocks
==20050==         suppressed: 0 bytes in 0 blocks
==20050== 
==20050== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==20050== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

...происходят когда я программу останавливаю.

Ещё GDB говорит что в одном потоке «гонки» могут происходить, но это я там мьютексы не припакал. Хотя в мане pthread говорится, что должны применятся реентерабельные функции, но наверно я не правильно это понимаю.

А вот что за редиректы в самом начале происходят? Вот эти например:

==26576== WARNING: new redirection conflicts with existing -- ignoring it
--26576--     old: 0x04019e20 (strlen              ) R-> (0000.0) 0x38056a61 vgPlain_amd64_linux_REDIR_FOR_strlen
--26576--     new: 0x04019e20 (strlen              ) R-> (2007.0) 0x04c2dca0 strlen

Может что-то с версиями компилятора и валгринда не то?

stD
() автор топика
Ответ на: комментарий от anonymous

Ищешь среди имен функций знакомые, смотришь где лично делал этот...

Жаль что никто не подсказал, что компилятору нужно было вначале дать -g, а потом уже valgrind запускать. Так он указывает на строки, в которых ошибка, хотя и не всегда.

stD
() автор топика
Ответ на: комментарий от stD

А язык мне чертовски нравится

Это потому что ты его не понимаешь. :-)

Понятно что инициализация массива происходит не правильно (char xex[4] = {0,};) и на конце нужен ноль чтоб разделить области памяти, но мне то в данном случае это не нужно.

Вот эта фраза выдаёт непонимание того, как оно внутри устроено и зачем. Причём в этом треде уже писали подробное объяснение.

i-rinat ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.