Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Доброго времени суток, уважаемые! На старости лет возникла необходимость переписать часть имеющихся наработок на perl/pascal на языке Си - "политика партии" поменялась, плюс кое-где возникают проблемы с производительностью. Плюс есть желание к саморазвитию. Засел опять за книги, но дело идёт туго, Си для меня оказался очень причудливым языком, в особенности в части работы со строковыми данными, а как раз обработка строк в моих программах - краеугольный камень. Для начала попытался написать несколько функций, которые занимаются подсчетом лексем в строке, вычисляют позицию заданной лексемы в строке и извлекают из строки лексему по порядковому номеру. И вроде бы всё даже работает, но поскольку некоторые моменты работы с указателями я постиг интуитивно, хотелось бы услышать мнение более опытных программистов о качестве данного кода, какие ошибки я мог допустить, и т.п. В общем - посмотрите, пожалуйста, и прокомментируйте, что стоит изменить-исправить. Заранее спасибо. Да, ещё момент - возможно, я изобретаю велосипед (хотя что-то не находил пока готовых библиотек с таким функционалом) - если так, то с благодарностью приму ссылки на готовенькое-проверенное, и тем не менее, все равно прошу прокомментировать мой код - учиться-то надо... Собственно, код: Код: 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. Результат: String - "Hello, my crazy world!", delimeters - " ,.:;?! ""'" Word count - 4 Word number 1 start position - 0 Word number 2 start position - 7 Word number 3 start position - 10 Word number 4 start position - 16 Word number 5 start position - -1 Word number 1 - Hello, Word number 2 - my Word number 3 - crazy Word number 4 - world! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.05.2015, 16:10 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.05.2015, 17:43 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
YesSqlесть готовая функция в стандартной библиотеке C/C++ strtok Благодарю, о наличии этой функции я знаю, здесь я сознательно пошёл на изобретение велосипеда, дабы лучше понять принципы работы с указателями и строками. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 11:20 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Для работы с strtok я написал вот такую обертку: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. И кстати, здесь у меня появился ещё один вопрос: я правильно понимаю - все объявленные внутри функции переменные и выделяемая им память после выхода из функции уничтожаются автоматически, а вся распределенная память также автоматически освобождается и в вызовах free перед выходом из функции нет нужды? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 12:24 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey Vahromkin, А что делает эта обертка? Кроме того что повторяет одно и то же. Зачем она нужна? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 13:53 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey Vahromkinдабы лучше понять принципы работы с указателями и строками. Дабы понять принципы работы с указателями, достаточно иметь представление об устройстве оперативной памяти хотя бы на школьном уровне: в виде ряда пронумерованных коробочек. Указатель это и есть коробочка, хранящая номер другой коробочки. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 14:05 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
YesSqlА что делает эта обертка? Кроме того что повторяет одно и то же. Зачем она нужна? Мне кажется, это самоочевидно. Допустим, нужно извлечь из строки source "aaa bbb ccc ddd eee" вторую и четвертую лексему. Это можно сделать так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Или так: Код: plaintext 1. 2. 3. 4. 5. Второй вариант с функцией-оберткой над strtok _мне_ нравится больше. Потому что строка может быть существенно длиннее, и нужно извлекать из нее не 2, а 12 слов. Если вы считаете, что лучше первый вариант - поясните, почему... Dimitry Sibiryakov Дабы понять принципы работы с указателями, достаточно иметь представление об устройстве оперативной памяти хотя бы на школьном уровне Практика написания программ на Си _очень_ отличается от практики паскаля и даже Перла... Мне пока _очень_ сложно работать со строками на Си. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 15:34 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey VahromkinПрактика написания программ на Си _очень_ отличается от практики паскаля и даже Перла. Это потому, что в Си нет строк. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 16:05 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovAndrey VahromkinПрактика написания программ на Си _очень_ отличается от практики паскаля и даже Перла. Это потому, что в Си нет строк. Да, я заметил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 16:11 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey VahromkinИ кстати, здесь у меня появился ещё один вопрос: я правильно понимаю - все объявленные внутри функции переменные и выделяемая им память после выхода из функции уничтожаются автоматически, а вся распределенная память также автоматически освобождается и в вызовах free перед выходом из функции нет нужды? Нет. Неправильно поняли. Если вы выделили память напрямую через malloc() или неявно через одну из стандартных функций (например strdup и многие другие - см. доки соотв. функций) то и удалять ее надо через free() вручную. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 16:33 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyЕсли вы выделили память напрямую через malloc() или неявно через одну из стандартных функций (например strdup и многие другие - см. доки соотв. функций) то и удалять ее надо через free() вручную. Вот эти-то моменты у меня как раз и вызывают кучу недоумений. Которые не укладываются в нумерованные коробочки, о которых говорил Dimitry Sibiryakov. Вот я объявляю в функции переменные: Код: plaintext 1. Вот им неявно выделяют память Код: plaintext 1. 2. А перед выходом память нужно вернуть. С s проблем нет Код: plaintext 1. 2. А что теперь делать с word? После return вызывать free(word) бессмысленно, до - получим вместо результата бог знает что, и программа, скорее всего, вывалится с ошибкой. И как быть? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 16:54 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey VahromkinИ как быть?прибить память после вызова функции extractword2 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 17:14 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey VahromkinВот эти-то моменты у меня как раз и вызывают кучу недоумений. Которые не укладываются в нумерованные коробочки, о которых говорил Dimitry Sibiryakov. И что там тебя не укладывается? Представь, что malloc пишет на коробочках твоё имя, а free - его стирает. Оставлять коробочки подписанными, когда они тебе уже не нужны - нехорошо. Класть или доставать что-то из неподписанных коробочек - нехорошо вдвойне. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 17:22 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey VahromkinА что теперь делать с word? strtok не выделяет память - поэтому ничего не делать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 17:33 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
И возвращать word тоже нельзя. Т.к. он указывает в память которую вы только что удалили. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 17:35 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
К счастью, есть одно простое и эффективное решение всех этих вопросов. Пишите на С++ и не используйте строк в массивах char, а применяйте std::string. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 17:37 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
egorychприбить память после вызова функции extractword2 Как? Переменная объявлена внутри функции, и в вызывающей её программе она недоступна. Dimitry SibiryakovИ что там тебя не укладывается? Вот все это и не укладывается. Я вошел из комнаты в кладовку и подписал 2 коробочки - s и word -правильно? И положил что-то в эти коробочки. А потом коробочка s мне стала не нужна, и я говорю - free(s), то бишь, стираю с нее свое имя. А дальше - то, что хранится в коробочке word мне надо как-то передать из кладовки в комнату - для этого я делаю return word в конце функции. Теперь с коробочки word надо стереть имя, правильно? А как это сделать? Если до return - я потеряю содержимое коробочки, если после return - коробочка будет уже недоступна. А тут мне ещё и говорят, что strtok работает как-то совсем иначе, чем я представлял... Я уже окончательно запутался. Anatoly Moskovskystrtok не выделяет память - поэтому ничего не делать. И возвращать word тоже нельзя. Т.к. он указывает в память которую вы только что удалили. Так, минуточку. Будьте добры - чуть подробнее. strtok возвращает указатель на последнюю найденную лексему в строке - правильно? Раз есть указатель - значит, есть кусочек памяти на который он указывает, и эта память была как-то кем-то выделена - правильно? Или где же сама эта лексема тогда размещается? Anatoly MoskovskyИ возвращать word тоже нельзя. Т.к. он указывает в память которую вы только что удалили. Опять не понял - что я удалил, и где? Anatoly MoskovskyПишите на С++ Да, возможно, это выход, но я сначала со своими примерами разобраться хочу... А то, чувствую, с c++ я тоже не подружусь, если сейчас все эти непонятки не проясню для себя. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 18:13 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Так, кажется, я понял свою ошибку - нельзя из функции возвращать адрес локальной переменной, по той самой причине, что сам и называл - переменная локальная и при выходе из функции она будет уничтожена. Правильно? Теперь пытаюсь понять, как мне всё-таки вернуть из функции желаемое... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 18:36 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey VahromkinА тут мне ещё и говорят, что strtok работает как-то совсем иначе, чем я представлял... Потому что не надо представлять. Её работа в деталях описана, например, на http://en.cppreference.com/w/c/string/byte/strtok Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.05.2015, 19:17 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey VahromkinОпять не понял - что я удалил, и где? Код: plaintext 1. 2. 3. Ну вот же. strtok возвращает указатель внутрь буфера на который указывает s, который вы присваиваете в word. А потом удаляется память буфера s, и word теперь указывает вникуда ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.05.2015, 01:25 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Andrey VahromkinYesSqlА что делает эта обертка? Кроме того что повторяет одно и то же. Зачем она нужна? Мне кажется, это самоочевидно. Допустим, нужно извлечь из строки source "aaa bbb ccc ddd eee" вторую и четвертую лексему. Допустим у вас текст на 100К и вы хотите 100500 лексему, а затем 100501 лексему. . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.05.2015, 08:46 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Значит, на данный момент я понял, что для возврата строки из функции нужно либо в функции выделить память под нее и потом можно возвращать указатель на эту область памяти (как раз это я и делал в варианте extractword без использования strtok): Код: 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. Либо нужно предварительно выделить память, а в функцию передать указатель на эту выделенную область, чтобы функция помещала результат в нее: Код: 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. Правильно ли я все понял? Какой вариант предпочтительнее? Мне extractword3 кажется нагляднее - после extractword2 следует вызов free, причина которого неочевидна... Еще вопрос. Сначала в функциях extractword2 и extarctword3 вместо конструкции Код: plaintext 1. 2. 3. 4. я использовал Код: plaintext 1. 2. 3. Но с использованием strdup программа падала в кору при втором вызове extractword2/extarctword3 Почему?? Я же явно освобождаю выделенную ею память перед выходом из функции. С calloc/strncpy все работает так, как должно... Спасибо всем за терпение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.05.2015, 17:02 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
extractword2() это бред. Ты выделил память, туда скопировал, чего-то там поделал и память освободил, но пытаешься вернуть указатель на кусок уже освобожденной памяти. Кроме того выделил память под word и проимел указатель на эту память, т.е. утечка памяти. extractword3() тоже бред, но без утечки. Выше уже написали что на лицо полное непонимание как это устроено. Если выделил память, то нельзя ее освобождать пока она используется (она используется т.к. ты возвращаешь на нее указатель), иначе либо вылетит при обращении к несуществующей памяти (в лучшем случае), либо память будет занята чем-то другим, а твой код это не поймет (такое вообще устанешь отлавливать). Надо завести четкое правило где выделять память и где освобождать. Проще и понятнее это делать на вызывающей стороне, т.е. у тебя в main(), т.е. в твоих extractwordX() не должно быть ни calloc() ни free() ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.05.2015, 20:34 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Dima Textractword2() это бред. Ты выделил память, туда скопировал, чего-то там поделал и память освободил, но пытаешься вернуть указатель на кусок уже освобожденной памяти. Кроме того выделил память под word и проимел указатель на эту память, т.е. утечка памяти. extractword3() тоже бред, но без утечки. Выше уже написали что на лицо полное непонимание как это устроено. Если выделил память, то нельзя ее освобождать пока она используется (она используется т.к. ты возвращаешь на нее указатель), иначе либо вылетит при обращении к несуществующей памяти (в лучшем случае), либо память будет занята чем-то другим, а твой код это не поймет (такое вообще устанешь отлавливать). Надо завести четкое правило где выделять память и где освобождать. Проще и понятнее это делать на вызывающей стороне, т.е. у тебя в main(), т.е. в твоих extractwordX() не должно быть ни calloc() ни free()[/ Это хороший совет, попробуйте сделать так ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.05.2015, 01:47 |
|
||
|
Вопросы начинающего - функции для работы со строковыми лексемами
|
|||
|---|---|---|---|
|
#18+
Dima TВыше уже написали что на лицо полное непонимание как это устроено. Если выделил память, то нельзя ее освобождать пока она используется (она используется т.к. ты возвращаешь на нее указатель), иначе либо вылетит при обращении к несуществующей памяти (в лучшем случае), либо память будет занята чем-то другим, а твой код это не поймет (такое вообще устанешь отлавливать). Не серчайте, уважаемый. Я действительно пока плохо понимаю, как всё это работает, но хочу разобраться. Dima TНадо завести четкое правило где выделять память и где освобождать. Проще и понятнее это делать на вызывающей стороне, т.е. у тебя в main(), т.е. в твоих extractwordX() не должно быть ни calloc() ни free() Тогда так. Буду пояснять, что именно я делаю, так будет виднее, понял ли я суть или нет. 1. Внутри функции объявим массив символов char s[STR_BUFFER], и туда будем копировать разбираемую строку. Это будет массив локальный, под него память будет выделена статически, и после выхода из функции эта память будет освобождена автоматом (в принципе, как я понимаю, тут можно и malloc/calloc использовать, главное потом перед выходом из функции не забыть про free - правильно?) 2. Указатель на первый элемент этого массива (правильно говорить именно так, а не "указатель на эту строку" - верно?) будем передавать strtok, а возвращаемый ей указатель присвоим в качестве значения указателю word, который объявлен в теле основной программы и где ему же выделена память. (Тут, наверное, тоже можно использовать массив символов char word[STR_BUFFER], насколько я понимаю, если нам не важно экономить память в ходе выполнения программы)? 3. В теле основной программы calloc'ом выделяем память под разбираемую строку и лексемы (s и word) и затем вызываем функцию извлечения лексем. В заключении освобождаем память, выделенную для исходной строки и лексемы. Код: 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. Что теперь скажете? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.05.2015, 12:01 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=38955416&tid=2018998]: |
0ms |
get settings: |
8ms |
get forum list: |
16ms |
check forum access: |
5ms |
check topic access: |
5ms |
track hit: |
65ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
61ms |
get tp. blocked users: |
1ms |
| others: | 284ms |
| total: | 461ms |

| 0 / 0 |
