-- Author Mohit Jain
{-
== Problem statement ==
Implement a simplified version of scanf.
== INPUT ==
2 strings as command line arguments.
String 1: Format string
String 2: Data string
== OUTPUT ==
$./myscanf %3d%2x%5s 123ffHello
dec integer: 123, hex integer: 255, char string: Hello
$
== Other Samples ==
- %2d 10
- dec integer: 10
- %2x 10
- dec integer: 16
- %2s 10
- char string: 10
== Rules ==
1. [input 1] First argument specifies the scan pattern.
- Length of scan pattern is always 3n (0 < n <= 10)
- Character at index 3m (0 < m < n) is always '%'
- Character at index 3m + 1 (0 < m < n) is always in range ['1' - '9'] specifying length of data.
- Character at index 3m + 2 (0 < m < n) is always ['d', 'x', 's'] specifying scan pattern.
- Format specifier ['d', 'x', 's'] are always lowercase.
2. [input 2] Second argument specified the input data.
- Length of input data is less than 100 bytes.
- input data contains only ['a'-'z', 'A'-'Z', '0'-'9', <space>, <comma>]
3. [output] For every scan pattern read the data and print.
- d: print string "dec integer: " followed by decimal and hex representation of scanned number.
- x: print string "hex integer: " followed by decimal and hex representation of scanned number.
- s: print string "char string: " followed by the scanned string.
4. Length of second argument is equal to the sum of format lengths.
-}
module Main where
import List
import Char
main = putStrLn $ similarScanf "%2d%5s%3x" "12Hello100"
similarScanf :: String -> String -> String
-- This function reads the format string and data string
-- And scans data string based on format string
similarScanf [] _ = ""
similarScanf format dataStr = init $ init $ similarScanfHelper format dataStr
-- I used init twice in above line of code because, output of similarScanfHelper
-- is a string. similarScanfHelper recursively appends the result and adds separator ", "
-- after each result formatted text. Calling init twice removes last two separator characters
-- [FIXME]:: similarScanfHelper should return [String] and intercalate "," or
-- concatenate $ intersperse ", " should be used.
similarScanfHelper ::String -> String -> String
-- This function parses the format string and unformatted data string
-- And returns the formatted data string
similarScanfHelper [] _ = ""
similarScanfHelper f d = outList where -- Example: f = "%3d%2s", d = "213ab"
sizeOfData = digitToInt (f!!1) -- Example: sizeOfData = 3
typeOfData = (f!!2) -- Example: typeOfData = 'd'
unformattedData = take sizeOfData d -- Example: unformattedData = "213"
remainingFormat = drop 3 f -- Example: remainingFormat = "%2s"
remainingData = drop sizeOfData d -- Example: remainingData = "ab"
outList = formattedData ++ ", " ++ similarScanfHelper remainingFormat remainingData
formattedData = case typeOfData of
's' -> "Char string: " ++ unformattedData
--'d' -> show $ read unformattedData
'd' -> "Decimal integer: " ++ unformattedData
'x' -> "Hex integer: " ++ (show $ readMyHex unformattedData)
readMyHex ::[Char] -> Int
-- Returns the integer equivalent of input hex string
-- Test input: "100"
-- Test output: 256
readMyHex [] = 0
readMyHex x = (digitToInt $ last x) + 16 * (readMyHex $ init x)