Haskell Bytestring изменить ASCII? - PullRequest
1 голос
/ 16 августа 2011
import qualified Data.ByteString.Lazy.Char8 as BS

stuff <- BS.readFile "stuff.txt"

Как взять определенный символ из строки байтов, затем изменить его ASCII и затем вернуть обратно?Я использую readInt или что-то в этом роде?

Например: "aaaaa", "a" равно 97, поэтому минус 1, и у вас есть "aa`aa"

Ответы [ 3 ]

2 голосов
/ 16 августа 2011

Как насчет BS.map pred?Вы также можете использовать fromEnum и toEnum для преобразования в / из Int s.

2 голосов
/ 16 августа 2011

Другие решали проблему выполнения операций с байтами, поэтому я сосредоточусь на другой половине вашего вопроса: выборе и обновлении определенного байта в пределах ByteString. Давайте начнем с реализации операции для простых списков, используя более знакомый интерфейс:

onNth :: Int -> (a -> a) -> ([a] -> [a])
onNth n f xs = case splitAt n xs of
    (beginning, x:ending) -> beginning ++ f x : ending
    _ -> xs -- happens when n is out-of-bounds

Вы могли бы эквивалентно реализовать это, используя take и drop вместо splitAt. Теперь, как мы можем перевести это, чтобы работать на ByteString с? Ну, интерфейс ByteString предлагает take, drop, splitAt, append и cons; единственное, что у нас не совсем получилось, это сопоставление с образцом, которое мы сделали в x:ending части выше. К счастью, ByteString предлагает нечто подобное:

uncons :: ByteString -> Maybe (Word8, ByteString)

Итак, используя это, мы можем написать новую onNth функцию, которая работает для ByteString s:

second :: (b -> c) -> (a, b) -> (a, c)
second f (a, b) = (a, f b)

onNth :: Int -> (Word8 -> Word8) -> (ByteString -> ByteString)
onNth n f bs = case second uncons (splitAt n bs) of
    (beginning, Just (x, ending)) -> append beginning (cons (f x) ending)
    _ -> bs -- again, for out-of-bounds cases

Наконец, мы можем обсудить, какую функцию мы должны использовать в качестве аргумента f :: Word8 -> Word8 выше. Хотя вы говорите о тексте выше, я укажу, что вы все равно не должны использовать ByteString для текста (ByteString s - это последовательности байтов, а не последовательности Char s). Поэтому, если вы решили использовать ByteString, вы должны говорить о байтах, а не о тексте. ; -)

Следовательно, вы действительно хотели спросить о функции, которая уменьшает байт на единицу, по-видимому, оборачиваясь на границе. subtract 1 - это функция, которая делает именно это, поэтому для преобразования pack [97, 97, 97, 97, 97] в pack [97, 97, 96, 97, 97] вы можете написать onNth 2 (subtract 1). Читает почти как на английском!

1 голос
/ 16 августа 2011

После того, как вы преобразовали байты в Char s с помощью BS.unpack, вы можете использовать fromEnum :: Char -> Int (или, что эквивалентно, ord из Data.Char), чтобы преобразовать Char в его значение ASCII,которыми вы можете манипулировать как обычное целое число.Чтобы преобразовать значение ASCII из Int обратно в Char, используйте toEnum или Data.Char.chr, и затем Char s можно преобразовать обратно в ByteString с BS.pack или подобным.

...