|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Появилась необходимость чуть подправить свои же вымученные когда-то C-коды. В общем смысл в следующем: есть две строки, разделенные сепаратором, например. 1) "12345" 2) "67890" Сепаратор задается/выбирается, например ";SEPARATOR=", или "#", или "@@@" (пользователем в настройках). Его может и не быть вовсе, тогда вторая часть отсутствует. В общем предположим он задан как ";SEPARATOR=" Т.е. исх. строка будет 12345;SEPARATOR=67890 нужно получить первую и вторую часть В VB.Net выглядит так: Код: vbnet 1. 2. 3. 4. 5. 6. 7.
Но надо сделать это в C (?++). Мучаюсь уже долго. Код: plaintext 1.
В общем у меня здесь на входе pFaxRoute->CallerId (LPCWSTR) Она имеет формат 12345;SEPARATOR=67890 Нужно получить два полагаю WCHAR Вот нарыл swscanf непосильным трудом. Код: plaintext 1. 2. 3. 4. 5. 6. 7.
Дебаг отдает пока Код: plaintext 1. 2. 3.
В RoutingInfo надо получить 67890 (пока пусто) До кучи надо еще проверить, что в pFaxRoute->CallerId содержится мой "SEPARATOR", который в общем случае WCHAR (но это я получу), а не константа. Поможете осилить? Чет совсем отупел, а сделать надо. Со всякими std:: здесь не работаю, много вымучено на эту тему в связи с рантаймами и т.п. Т.е. код использует ф-ции в духе StringCchCopy, StringCchCat, StringCchPrintf, ZeroMemory и т.п., сделан из SDK примера, компилируется с определенным рантаймом в VC++2005. Его еще надо не испортить с точки зрения запуска exe на разных OS. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.11.2018, 05:55 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Код: plaintext 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.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
... |
|||
:
Нравится:
Не нравится:
|
|||
07.11.2018, 08:53 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Cerebrum, прежде всего спасибо что откликнулись. Меня что смущает. У Вас я так понимаю std, т.е. C++ (комментарий в конце моего первого поста). А попроще никак нельзя? В духе C (без плюс), Microsoft SDK, классического msdn так сказать. В SDK (6.1, 7.1) кстати примеров нигде быть не может? Сходу не нашел. Попытаюсь как бы еще раз сформулировать задачу (в свете исходного кода): 1) код отдает мне исходную строку LPCWSTR CallerId 2) есть разделитель получаемый в коде как WCHAR sSeparator (который может быть пустой/нулевой длины) 3) надо получить WCHAR sPart1 и WCHAR sPart2 по следующему алгоритму: Код: plaintext 1. 2. 3. 4. 5. 6. 7.
разделитель известен или отсутствует(нулевой длины) строка его содержит или не содержит, не более одного разделителя регистр , там по определению точное соответствие будет, тот кто дописывает разделитель + то что после разделителя считывает тот же параметр в ini-файле что и текущая функция, через GetPrivateProfileString, с дефолтным значением "" (строка нулевой длины, не NULL, означает отсутствие разделителя и соотв. второй части) Т.е. грубо говоря, у меня модем пишет в CallerID сам CallerID(NMBR=) и еще и DID (NDID= т.е. Called Number) через сепаратор, а задача C -кода с которым я вожусь (моя dll -RoutingExtension) распарсить это дело обратно. MS Fax Service написан в 90-х, там тупо нет поля DID, есть RoutingInfo, но через драйвер модема и майкрософтовский FSP в RoutingInfo DID не запихнуть (через свой FSP можно) отсюда пляски. === CallerId сейчас используется далее следующим образом: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Переделать надо примерно так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
Могу конечно отдать CallerID вместе с DID нераспарсенным в VB-код (кой код собственно и делает всю логические действа) как есть, но так некрасиво. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.11.2018, 15:29 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Дмитрий77Меня что смущает. У Вас я так понимаю std, т.е. C++ (комментарий в конце моего первого поста). wcslen, swscanf_s - это тоже std Дмитрий77А попроще никак нельзя? В духе C (без плюс), Microsoft SDK, классического msdn так сказать. Я тебе показал как сделать , а заменить std-функции можно на свои собственные аналоги Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
Не понимаю в чем проблема с std? Если не хочется повсюду таскать vcruntime, то просто собери статическую сборку, получишь 1 красивый exe-шник, который будет работать везде, начиная с Windows XP и заканчивая Windows Server 2019 ... |
|||
:
Нравится:
Не нравится:
|
|||
07.11.2018, 16:29 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
а Std::vector, который я использовал для сбора подстрок, можешь вообще выкинуть, написать вместо SplitToElements функцию в духе ForEach с callback'ом, в который пулять каждый найденный сегмент для анализа и обработки и тут же от него избавляться, а не накапливать. Или написать свой собственный класс динамического масссива, что тоже не особо трудно. В моем коде все сделано для простоты восприятия человека забывшего про тонкости языка, как раз в духе Platform SDK. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.11.2018, 16:34 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
CerebrumЕсли не хочется повсюду таскать vcruntime, то просто собери статическую сборку, получишь 1 красивый exe-шник, который будет работать везде, начиная с Windows XP и заканчивая Windows Server 2019 Вот здесь когда-то обсуждали: Проект dll(надо и 32 и 64 бит версии) в VS2013 Ultimate C++ -чтоб от XP до Win10 И не все там просто было особенно с "с Windows XP" на статрантаймах, в частности из-за std. И в итоге забил на эти 13-е студии и собрал проверенным образом: Microsoft Visual Studio 2005 Version 8.0.50727.762 (SP.050727-7600) Код: plaintext 1. 2. 3. 4. 5. 6. 7.
Код: plaintext 1. 2. 3. 4. 5. 6. 7.
что ИМХО есть надежно по определению, поэтому и C++ с std там не должно быть проблем с точки зрения "от и до" (проверено многолетним опытом). Но по "религиозным соображениям" таки не хочется. Ладно, спасибо, посмотрю вечером, м.б. чего-нибудь рожу рабочее. Мне даже "функций" и "классов" никаких не надо (путают они меня), а просто пару абзацев реально рабочего кода который делает мне эти две WCHAR из анализа исходного LPCWSTR и сераратора WCHAR (в 4-х местах скопирую, не проблема). То что легких путей нет, это уже дошло. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.11.2018, 17:00 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Дмитрий77, strspn / strcspn ... |
|||
:
Нравится:
Не нравится:
|
|||
07.11.2018, 22:41 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Siemarglstrspn / strcspn Но оно выполняет поиск символов строки string2 в строке string1 а мне надо поиск строки string2 в строке string1, и потом обрезать концы справа и слева. И честно, я задолбался. И так каждый раз, когда мне надо сделать извините какую-то мелкую ерунду, но в C. swscanf вообще ни фига не работает Код: plaintext 1.
Казалось бы чем не шаблон, так нет, ей какие-то пробелы нужны или \n, а так ложит все в sPart1. Ваш код, с уважением, но сложен он как-то для меня. Хочется простого Код: vbnet 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
07.11.2018, 23:24 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
У меня только так заработало (с std::wstring), ну в таком духе я и раньше не раз делал: Код: plaintext 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.
Код: plaintext 1. 2. 3. 4.
На XP и Win2019 оно конечно работать будет, ибо в правильной студии и рантайме сделано (проверено давно), но конечно не фонтан, да еще с довеском ругани Код: plaintext 1. 2. 3. 4. 5.
которая правда тоже ни на что не влияет. А хотелось культурно, увы. Ладно, пошел писать Г-простыни, тестировать и забывать, надеюсь надолго. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2018, 02:32 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Дмитрий77Как распарсить строку strtok - нарезает куски строки согласно набору разделителей. там есть момент: функция работает непосредственно с исходной строкой и на каждый вызов вставляет нули вместо разделителей в строку(потом убирает), таким образом мы получаем токены. Cerebrumwcslen, swscanf_s - это тоже stdэто стандартная библиотека, но не std(stl) ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2018, 05:18 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Дмитрий77, не нужно приходить сюда ныть, у тебя уже все есть, чтобы сделать что ты хочешь, но ты просто САМ не хочешь ничего делать без классов, чистый WinAPI в стиле С Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2018, 09:03 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Cerebrum, Ну, ныть не ныть а "надо дела делать". Глядючи на ваш код, ну не до конца его понимаю. Вот хотя бы так как здесь , в смысле линейно но без конвертации в std::string сделать то же самое можно? Т.е. грубо s1= s2= или func (...,s1,s2) Callback - это сильная путаница кода уже. В принципе я уже сделал с std::string и вставил в продакшн, оно работает и сойдет ("дела делает", не глючит). Почему мне хотелось без std::string я написал выше и целый пост был разведен однажды, ссылку на кот. дал. У меня есть две моих dll: FSP и RoutingExtension. FSP была с кучей std::string, переделывать тогда не стал. RoutingExtension до сего момента была "по стандарту MS", без std::string, счас вот "изгадил". Ну да бог с ним, все одно они в паре идут, первую все одно переделывать не буду, будучи откомпилированной 8.0.50727.762 (SP.050727-7600), полет таких штук много лет нормальный включая std::string, а вот в VS2013 там извините задница с "мультисистемностью", хоть static, хоть dynamic. Но на 2013+ я с C забил. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2018, 16:12 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Дмитрий77, это все отмазки, тем кому надо, тот берет и делает Код: plaintext 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.
Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
output 1234567 8903987654321 без классов написать такой код, который хочешь ты нереально, но тебя они путают... ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2018, 18:01 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Cerebrum, вот это вроде красиво выглядит, попробую разобраться. М.б. даже и заменю сразу пока "горячо". >это все отмазки Ну я и сам всегда говорил что я пожизненно тупой(C) что касается C+/-. У меня с WIN API рука очень даже набита, но все делаю в VB.Net (ранее в VB6). Я отпишусь в теч. нескольких дней. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2018, 21:29 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Cerebrum, Потестировал, склоняюсь к вашему варианту. Я бы сам такой код не осилил. Максимум м.б. содрал бы откуда-то, если б хватило ума нагуглить (на момент написания топика не хватило). Спасибо. Позволил себе одну замену, надеюсь не критично Код: plaintext 1. 2.
CompareStringEx function Minimum supported client Windows Vista [desktop apps | UWP apps] Minimum supported server Windows Server 2008 [desktop apps | UWP apps] Я от поддержки XP формально не отказывался, и не ловит ее VS2005 + SDK 6.1 И поэтому CompareStringW function Minimum supported client Windows 2000 Professional [desktop apps only] Minimum supported server Windows 2000 Server [desktop apps only] Тестовый код: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
Ну вроде как успешно. Пойдет? Ничего не упустил. У меня могут быть такие случаи: 1) сепаратор задан и есть обе части им разделенные, заполнить s1 и s2 соответственно 2) сепаратор вообще не задан (L""), тогда копирование sFull->s1 целиком, s2 пустая 3) сепаратор задан, но отсутствует в sFull, тогда тоже копирование sFull->s1 целиком, s2 пустая Значения NULL в s1 и s2 нежелательны, надо L"". Пустой sSep в реальном коде всегда считывается как L"" (вроде как) Код: plaintext 1. 2. 3.
Насчет sFull, это pFaxRoute->CallerId, отдаваемый MS Fax, на всякий случай проверил с NULL тоже, черт его знает что он туда кладет если номер не определен (NMBR=<пусто>, если смотреть в HyperTerminal в модеме). Если вдруг что-то увидели в тест-коде непотребное, скажите please. Особенно переживаю за NULL={null}=пусто=Nothing и L""='\0'=строка нулевой. Стараюсь за этим следить, но иногда что-то упускаю и вдруг стреляет. Планирую таки воспользоваться этим вариантом и убрать все std::string, но это уже видимо на след. неделе. Спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2018, 06:46 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Дмитрий77Ну вроде как успешно. Пойдет? Ничего не упустил. В PrintOut изменить последнюю строчку на Код: plaintext 1. 2. 3. 4.
и помнить, что максимум в структуре FOREACHCONTEXT памяти выделено на 10 лексем, если будет 11 - будет беда, поэтому, чтобы избежать перелета, контролируем CALLBACK. Даже если в строке никогда не будет больше 2х, дополнительная подстраховка от ошибок разработчика не помешает Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2018, 09:09 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Какие то проблемы на ровном месте. Если не извращаться с со словами-сепараторами, то 1 (одна) строка со strtok Если даже извращаться - простейший цикл со strstr Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2018, 11:09 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Cerebrum, ваш код не отсекает случая когда сепаратор отсутствует =L"" и надо вернуть sFull ->s1, поэтому его надо разобрать сразу. Также лучше сразу отсечь sFull == NULL. (sFull == "" обработается по Else if (ctx.t_count == 1UL)). Тогда до "маловероятно" и "что-то пошло не так, что будем делать ?" дело вряд ли дойдет, в этих обоих случаях возвращаем L"" в s1 и s2. Плюс кухню с ForEachToken лучше пихать под условие, у меня в коде ф-ции присутствуют goto Exit;/Exit: , компилятору это не нравится, если объявлять FOREACHCONTEXT ctx = {0}; безусловно. Я думаю так сойдет (проверил все случаи): Код: plaintext 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.
Cerebrum Код: plaintext 1. 2. 3. 4.
и помнить, что максимум в структуре FOREACHCONTEXT памяти выделено на 10 лексем, если будет 11 - будет беда, поэтому, чтобы избежать перелета, контролируем CALLBACK. Даже если в строке никогда не будет больше 2х, дополнительная подстраховка от ошибок разработчика не помешает Здесь согласен. Никто не мешает юзеру в качестве разделителя задать "0", тогда 10 нулей из CallerID и CalledNumber легко может превыситься, желаемого результата естественно не будет, но краша ясно дело тоже быть не должно. Ну, юзер тоже головой иногда думать должен, всех защит от дураков не сделаешь. Задавать разделитель жестко не хочу, в тек. версии он уже НЕ жестко и есть эстетический момент: этот разделитель отображается в частности в Fax and Scan в поле CallerID, т.е. '74951234567;DID=79039876543' -относительно красиво '74951234567separator79039876543' -относительно фигово смотрится Так что юзер сам на свой вкус решает, чем разделять. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2018, 15:38 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
Дмитрий77ваш код не отсекает случая когда сепаратор отсутствует =L"" действительно, видимо я проверил с сепаратором, которого нет в анализируемой строке и в ответ получил всю строку целиком, но почему-то посчитал, что проверил на пустой сепаратор Тогда я н не понимаю, зачем проверять наличие пустой строки считая в ней символы? Для проверки есть IsNullString, которая как раз и делает то, что требуется без лишнего оверхэда Код: plaintext 1. 2. 3.
но поскольку sSep создается на стеке, то вообще можно сократить до Код: plaintext 1.
и так и так и по вашему тоже будет работать, но правильный код должен писаться так, чтобы программисту не требовалось его комментировать. Чтобы намерения были ясны. Когда в коде встречается Код: plaintext 1.
вместо Код: plaintext 1.
то сразу становится очевидно что хотел разработчик и никаких дополнительных фантазий (не говоря о лишних трудозатратах CPU на посчитанную длину, которая по сути никому не нужна). ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2018, 17:31 |
|
Как распарсить строку например 12345;SEPARATOR=67890 на две 12345 и 67890
|
|||
---|---|---|---|
#18+
CerebrumДля проверки есть IsNullString, которая как раз и делает то, что требуется без лишнего оверхэда Код: plaintext 1. 2. 3.
Ну тогда уж пусть будет Код: plaintext 1. 2. 3. 4. 5. 6.
Просто у меня издержка в первом варианте, если sFull не NULL а L"" (очень даже может быть), то пустые s1 и s2 конечно возвращаются, но после запуска FOREACHCONTEXT, пусть сразу отсекается. Хотя что касается sSep, то NULL там по логике кода реально никогда не будет. Ладно, пошел переделывать свой "продакшн". ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2018, 16:16 |
|
|
start [/forum/topic.php?fid=57&fpage=16&tid=2017727]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
31ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
50ms |
get tp. blocked users: |
2ms |
others: | 260ms |
total: | 391ms |
0 / 0 |