我想获取文件中以特定格式显示的数字列表。但是我没有任何格式的数字(例如%s%d)。
我的文件包含以下文本:
[1;2] [2] 5
[45;37] [9] 33
[3] [2;4] 1000
我尝试了以下
value split_input str fmt = Scanf.sscanf str fmt (fun x y z -> (x,y,z));
value rec read_file chin acc fmt =
try let line = input_line chin in
let (a,b,c) = split_input line fmt in
let acc = List.append acc [(a,b,c)] in
read_file chin acc fmt
with
[ End_of_file -> do { close_in chin; acc}
];
value read_list =
let chin = open_in "filepath/filename" in
read_file chin [] "%s %s %d";
问题在于在结尾处指定的格式。我使用了相同的代码从其他文件中获取数据,其中数据的格式为(字符串*字符串*整数)。
要重用相同的代码,我必须以字符串形式接收上述文本,然后根据需要进行拆分。我的问题是:是否存在像%s%d这样的整数列表格式,以便我直接从文件中获取列表,而不用编写其他代码将字符串转换为列表。
答案 0 :(得分:1)
Scanf
中没有列表的内置说明符。可以使用%r
说明符将解析委派给自定义扫描程序,但是Scanf
并非真正用于解析复杂格式:
let int_list b = Scanf.bscanf b "[%s@]" (fun s ->
List.map int_of_string @@ String.split_on_char ';' s
)
然后使用这个int_list
解析器,我们可以编写
let test = Scanf.sscanf "[1;2]@[3;4]" "%r@%r" int_list int_list (@)
并获取
val test:int list = [1; 2; 3; 4]
符合预期。但是同时,使用String.split_on_char
进行拆分更容易。通常,解析复杂的格式最好用
regexp库,解析器组合器库或解析器生成器。
P.S:您可能应该避免使用经过修订的语法,因为它已被废弃。