2010-11-12 11 views
1

J'ai un fichier qui contient ceci:lecture quelque chose d'un fichier et de le mettre sous un type de données

(Float,Float,Float)"sometext" 
(Float,Float,Float)"sometext" 
(Float,Float,Float)"sometext" 
... 
... 

et je voudrais que mon programme pour lire une ligne du fichier, placez le (flotteur, flotteur , flotteur) dans un tripple et « someText » dans une chaîne et tout cela sous un nouveau type de données pour la chose ressemblerait à ceci:

SomeDataType (flotteur, flotteur, flotteur) « someText »

J'ai eu ceci jusqu'à présent:

readFromDisc filePath = do 
         fileHandle <- openFile "/tmp/lala.txt" ReadMode 
         contents <- hGetContents fileHandle 
         putStrLn $ readOneLine contents 

Si le fichier contient ceci:

(5.0,6.0,7.0)"faraway" 
(8.0,9.0,0.0)"holdon" 

je reçois:

"(5.0,6.0,7.0)\"faraway\"" 

Maintenant, depuis que je reçois en tant que chaîne, je pensais à l'aide

breakInput input = break (=='"') input 

Pour obtenir ceci:

("(5.0,6.0,7.0)","\"faraway\"") 

Ce qui est une paire de chaînes, et j'allais utiliser quelque chose pour analyser le triptyque et le texte, mais tout cela ne va pas.

Y a-t-il une meilleure façon de procéder?

Répondre

6

Utilisez la fonction reads. Il va analyser la partie correspondante au début de la chaîne et retourner le reste de la chaîne.

parseLine :: String -> [((Double, Double, Double), String)] 
parseLine line = do 
    (tuple, line') <- reads line 
    (string, _) <- reads line' 
    return (tuple, string) 

-- parseLine "(5.0, 6.0, 7.0)\"faraway\"" ---> ((5.0, 6.0, 7.0), "faraway") 

Ceci retournera une liste de correspondances, et ignorera le courrier indésirable à la fin de la ligne. Puisque votre cas particulier a une analyse non ambiguë, un seul résultat sera produit par une analyse réussie.

+3

+1. Mais utilisez 'Double' au lieu de' Int'. Aussi pour compléter la solution: utiliser 'lines' pour diviser en lignes est plus facile. Tout comme un one-liner: 'retour. carte parseLine. lines = << readFile "r.txt" '. – sastanin

+0

@jetxee Merci d'avoir complété la solution. J'ai corrigé la signature de type. – Heatsink

+0

YOu devrait également envisager sérieusement Parsec, si c'est plus compliqué. – fuz

0
readThat (triple, str) = SomeDataType (read triple :: (Float, Float, Float)) 
             (read str :: String) 

Rapide et sale.

0

Un hack, si vous ne vous souciez pas des erreurs de manipulation:

data SomeDataType = SomeDataType (Float, Float, Float) String 
        deriving Read 

readOneLine s = read ("SomeDataType " ++ s)