Бесплатный курс по Racket. Зарегистрируйтесь для отслеживания прогресса →

Racket: Оперирование строками

Получение отдельных символов и подстрок

Получить элемент строки, зная его индекс, можно с помощью функции string-ref. Если указанный индекс выйдет за границы строки, то вычисление завершится с ошибкой.

 (string-ref "apple" 3) ; #\l
 (string-ref "apple" 5)
 ; string-ref: index is out of range
 ;   index: 5
 ;   valid range: [0, 4]
 ;   string: "apple"
 ;   context...

Взятие же подстроки выглядит так:

; индексы:  01234
(substring "Apple" 2)   ; "ple"
(substring "Apple" 1 3) ; "pp"
(substring "Apple" 10 20)
; substring: starting index is out of range
;   starting index: 10
;   valid range: [0, 5]
;   string: "Apple"
;   context...

Заметьте, что (substring s n) выделяет подстроку от символа с индексом n и до конца исходной строки s. А вот (substring s n m) выделяет подстроку от индекса n до индекса m, не включая последний! Такое исключение правой границы встречается довольно часто в программировании. И, как и в случае string-ref, Racket следит, чтобы индексы не вышли за границы.

Конкатенация строк

Соединить несколько строк в одну или, как ещё говорят, сконкатенировать, можно с помощью функции string-append:

(string-append "Hello, " "World!") ; "Hello, World!"
(string-append "foo")              ; "foo"
(string-append "b" "a" "r")        ; "bar"

Модуль racket/string

В поставку Racket входит модуль racket/string, предоставляющий большое количество полезных, но более специфических, чем простая конкатенация, функций.

Обычно этот модуль подключать не приходится, потому что #lang racket делает это автоматически.

Например, функция string-join из этого модуля может просто сконкатенировать все строки из заданного списка, добавив между строками строку-разделитель, а ещё способна добавить что-нибудь в начало получаемого текста, в его конец и даже перед последним присоединяемым элементом! На это стоит посмотреть:

(string-join (list "a" "b" "c")) ; "a b c" - разделитель, это пробел

(define (greet names)
 (string-join
  names ", "
  #:before-first "Hello, "
  #:before-last " and "
  #:after-last "!"))

(greet (list "Bob"))               ; "Hello, Bob!"
(greet (list "Bob" "Tom"))         ; "Hello, Bob and Tom!"
(greet (list "Bob" "Tom" "Alice")) ; "Hello, Bob, Tom and Alice!"

Об этой функции узнать побольше и познакомиться с другими функциями модуля вы сможете в документации.

Задание

Реализуйте функцию scroll-left, которая "прокручивает" строку-аргумент влево так, что в строка-результате все символы, начиная со второго, оказываются сдвинуты на одну позицию влево, а первый символ оказывается в конце строки. В пустой строке прокручивать нечего, поэтому пустая строка должна оставаться неизменной.

Примеры:

(scroll-left "") ; ""
(scroll-left "a") ;"a"
(scroll-left "abc") ; "bca"
(scroll-left "*----") ; "----*"
(scroll-left (scroll-left "*----")) ; "---*-"
Упражнение не проходит проверку — что делать? 😶

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

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

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя 🤔

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

В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

Прочитал урок — ничего не понятно 🙄

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

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

Нашли ошибку? Есть что добавить? Пулреквесты приветствуются https://github.com/hexlet-basics
Если вы столкнулись с трудностями и не знаете, что делать, задайте вопрос в нашем большом и дружном сообществе