Io 将两个文件收集到另一个文件
我有两个文件,Io 将两个文件收集到另一个文件,io,prolog,swi-prolog,Io,Prolog,Swi Prolog,我有两个文件,file1.txt,file2.txt,我想在检查两个文件的行之后在file3.txt中收集它们 例如: file1.txt line 1 T line 2 F line 3 T line 4 T line 5 F line 6 F line 1 T line 2 T line 3 F line 4 T line 5 F line 6 T file1 *******************
file1.txt
,file2.txt
,我想在检查两个文件的行之后在file3.txt
中收集它们
例如:
file1.txt
line 1 T
line 2 F
line 3 T
line 4 T
line 5 F
line 6 F
line 1 T
line 2 T
line 3 F
line 4 T
line 5 F
line 6 T
file1
********************
number of line = 6
number of true = 3
number of false = 3
********************
line 1 T
line 3 T
line 4 T
file2
********************
number of line = 6
number of true = 4
number of false = 2
********************
line 1 T
line 2 T
line 4 T
line 6 T
file2.txt
line 1 T
line 2 F
line 3 T
line 4 T
line 5 F
line 6 F
line 1 T
line 2 T
line 3 F
line 4 T
line 5 F
line 6 T
file1
********************
number of line = 6
number of true = 3
number of false = 3
********************
line 1 T
line 3 T
line 4 T
file2
********************
number of line = 6
number of true = 4
number of false = 2
********************
line 1 T
line 2 T
line 4 T
line 6 T
file3.txt
line 1 T
line 2 F
line 3 T
line 4 T
line 5 F
line 6 F
line 1 T
line 2 T
line 3 F
line 4 T
line 5 F
line 6 T
file1
********************
number of line = 6
number of true = 3
number of false = 3
********************
line 1 T
line 3 T
line 4 T
file2
********************
number of line = 6
number of true = 4
number of false = 2
********************
line 1 T
line 2 T
line 4 T
line 6 T
对于每个文件,生成的文件应包含一个标题,显示行数、为真的行数(T
)和为假的行数(F
)。接下来只打印正确的行
有什么帮助吗?您可以按如下方式执行此操作。我们首先定义一个谓词
merge/2
,第一项是必须读取的文件名列表(此处[file1.txt,file2.txt]
),第二个参数是要写入的文件名(此处file3.txt
)。现在我们将merge/2
定义为:
merge(Inp,Outp) :-
open(Outp,write,Outs),
mergeS(Inp,Outs).
因此,我们打开一个名为Outp
的文件,并获取相应的流Outs
,然后调用mergeS/2
合并/2有两种情况:
- 所有输入文件都已处理,因此我们可以停止处理并关闭流:
mergeS([],OutS) :-
close(OutS).
- 我们至少需要处理一个文件:
mergeS([H|T],OutS) :-
open(H,read,InS),
atom_chars(FileN,H),
process(FileN,InS,OutS),
close(InS),
mergeS(T,OutS).
这个谓词的核心显然是process/3
,但是为了使事情更方便。我们已经在mergeS
中进行了文件处理
接下来,我们的进程/3
谓词如下:
process(Header,InS,OutS) :-
get_lines(InS,Lin,NL,NT,NF),
write(OutS,Header),nl(OutS),
write(OutS,'********************'),nl(OutS),
write(OutS,'number of line = '),write(OutS,NL),nl(OutS),
write(OutS,'number of true = '),write(OutS,NT),nl(OutS),
write(OutS,'number of false = '),write(OutS,NF),nl(OutS),
write(OutS,'********************'),nl(OutS),
print_lines(OutS,Lin),
nl(OutS).
我们首先使用get\u lines/5
收集文件内容。该谓词将同时计算统计信息,如行数、True数和false数。接下来,我们使用大量的write/2
和nl/1
语句将统计信息写入输出文件,然后使用谓词print\u lines/2
,将文件内容写入file3.txt
:
获取线路
和获取线路
get_line/5
使用三个累加器计算统计数据。这是通过初始化三个累加器,然后调用get\u lines/8
:
get_lines(Ins,Lin,NL,NT,NF) :-
get_lines(Ins,Lin,0,0,0,NL,NT,NF).
get_lines/8
是一个递归函数,一次处理一行,确定该行是T
还是F
,更新累加器,并解析下一行。然而,我们有可能得到一个空文件。为了使我们的方法更加稳健,我们这样写道:
get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
at_end_of_stream(InS),
!.
以及递归情况:
get_lines(InS,[H|T],NL0,NT0,NF0,NL,NT,NF) :-
get_line(InS,HCs),
inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1),
atom_chars(H,HCs),
get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).
get_line/2
只需读取文件的下一行,并返回一个字符流。它终止于'\n'
(包括在内,但不在结果中)
检查/7
现在我们仍然需要使用inspect/7
检查我们的生产线。我们再次使用三个累加器(根据get\u lines/8
的实现,您可能已经猜到了)。首先,我们获取行的最后一个字符。如果不存在这样的字符,统计信息就不会改变(可能在某个地方引入了空行)。否则,我们使用last/2
获取最后一个字符,并使用inspect\u last/7
检查它:
inspect(L,NL0,NT0,NF0,NL,NT,NF) :-
last(L,LL),
!,
NL is NL0+1,
inspect_last(LL,NT0,NF0,NT,NF).
inspect(_,NL0,NT,NF,NL1,NT,NF) :-
!,
NL1 is NL0+1.
get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
at_end_of_stream(InS),
!.
get_lines(InS,Res,NL0,NT0,NF0,NL,NT,NF) :-
get_line(InS,HCs),
inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1),
atom_chars(H,HCs),
( NT1 > NT0
-> Res =[H|T]
; Res = T
),
get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).
inspect\u last
确定最后一个字符是T
、F
还是其他字符,并相应地更新累加器:
inspect_last('T',NT0,NF,NT1,NF) :-
!,
NT1 is NT0+1.
inspect_last('F',NT,NF0,NT,NF1) :-
!,
NF1 is NF0+1.
inspect_last(_,NT,NF,NT,NF).
打印行/2
:
最后,我们仍然需要将文件打印到输出。这是使用非常简单的打印行/2
完成的:
print_lines(_,[]) :-
!.
print_lines(OutS,[H|T]) :-
write(OutS,H),
nl(OutS),
print_lines(OutS,T).
完整代码
完整代码:
merge(Inp,Outp) :-
open(Outp,write,Outs),
mergeS(Inp,Outs).
mergeS([],OutS) :-
close(OutS).
mergeS([H|T],OutS) :-
open(H,read,InS),
atom_chars(FileN,H),
process(FileN,InS,OutS),
close(InS),
mergeS(T,OutS).
process(Header,InS,OutS) :-
get_lines(InS,Lin,NL,NT,NF),
write(OutS,Header),nl(OutS),
write(OutS,'********************'),nl(OutS),
write(OutS,'number of line = '),write(OutS,NL),nl(OutS),
write(OutS,'number of true = '),write(OutS,NT),nl(OutS),
write(OutS,'number of false = '),write(OutS,NF),nl(OutS),
write(OutS,'********************'),nl(OutS),
print_lines(OutS,Lin),
nl(OutS).
get_lines(Ins,Lin,NL,NT,NF) :-
get_lines(Ins,Lin,0,0,0,NL,NT,NF).
get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
at_end_of_stream(InS),
!.
get_lines(InS,[H|T],NL0,NT0,NF0,NL,NT,NF) :-
get_line(InS,HCs),
inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1),
atom_chars(H,HCs),
get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).
get_line(InS,[]) :-
at_end_of_stream(InS),
!.
get_line(InS,[H|T]) :-
get_char(InS,H),
H \= '\n',
!,
get_line(InS,T).
get_line(_,[]).
inspect(L,NL0,NT0,NF0,NL,NT,NF) :-
last(L,LL),
!,
NL is NL0+1,
inspect_last(LL,NT0,NF0,NT,NF).
inspect(_,NL0,NT,NF,NL1,NT,NF) :-
!,
NL1 is NL0+1.
inspect_last('T',NT0,NF,NT1,NF) :-
!,
NT1 is NT0+1.
inspect_last('F',NT,NF0,NT,NF1) :-
!,
NF1 is NF0+1.
inspect_last(_,NT,NF,NT,NF).
print_lines(_,[]) :-
!.
print_lines(OutS,[H|T]) :-
write(OutS,H),
nl(OutS),
print_lines(OutS,T).
如果现在有人提出疑问:
?- merge(["file1.txt","file2.txt"],"file3.txt").
true.
名为file3.txt
的文件由以下内容构成:
file1.txt
********************
number of line = 6
number of true = 3
number of false = 3
********************
line 1 T
line 2 F
line 3 T
line 4 T
line 5 F
line 6 F
file2.txt
********************
number of line = 6
number of true = 4
number of false = 2
********************
line 1 T
line 2 T
line 3 F
line 4 T
line 5 F
line 6 T
这或多或少是你想要的。如果出现进一步的错误,请发表评论
编辑
不知怎的,我没有明白你想过滤这些行,只显示那些是真的(t
)。只需修改获取行/7
即可:
inspect(L,NL0,NT0,NF0,NL,NT,NF) :-
last(L,LL),
!,
NL is NL0+1,
inspect_last(LL,NT0,NF0,NT,NF).
inspect(_,NL0,NT,NF,NL1,NT,NF) :-
!,
NL1 is NL0+1.
get_lines(InS,[],NL,NT,NF,NL,NT,NF) :-
at_end_of_stream(InS),
!.
get_lines(InS,Res,NL0,NT0,NF0,NL,NT,NF) :-
get_line(InS,HCs),
inspect(HCs,NL0,NT0,NF0,NL1,NT1,NF1),
atom_chars(H,HCs),
( NT1 > NT0
-> Res =[H|T]
; Res = T
),
get_lines(InS,T,NL1,NT1,NF1,NL,NT,NF).
这里有一个粗略的草图,让您开始使用和
我们采用相关问题“”中my@mat定义的行//1
。使用,然后我们写:
?- set_prolog_flag(double_quotes , codes),
set_prolog_flag(toplevel_print_anon, false).
true.
?- phrase_from_file(lines(_Ls), 'file1.txt'),
maplist(reverse, _Ls, _Rs),
tpartition(prefix_of_t("T"), _Rs, _Ts0, _Fs),
maplist(reverse, _Ts0, _Ts),
forall(member(X,_Ts), format('~s~n',[X])).
line 1 T
line 3 T
line 4 T
true.
?-(,代码),
设置prolog标志(顶层打印,false)。
对。
?-((_Ls),“file1.txt”),
(,_Ls,_Rs),
(“T”)、“Rs”、“Ts0”、“Fs),
地图列表(反向,_Ts0,_Ts),
((X,_Ts),('~s~n',[X])。
1号线T
3号线T
4号线T
对。
F
或T
将始终是行中的最后一个字符?是的,但保留空白并不重要。行本身是“T”、“F”等,还是“第1t行”、“第2f行”等?@WillemVanOnsem,Boris,到目前为止,我所做的是实现一个谓词文件到列表(文件,列表)
结果:列表=['line-1-T','line-2-F,…]@AnsPiter:你想缩进file3
还是打字错误?我有个问题:merge(['file1','file2','file3')!权限错误:无法打开文件'c:/users/coper/file3'!不可写!目标:open(file3,write,_201)
@AnsPiter:这本身就说明了问题:不知何故,你的操作系统阻止了对该目录的访问。我不知道如何为Windows解决这个问题:Linux只运行了7年。@Willem Van Onsem thnx无论如何,我会安装它linux@AnsPiter:文件是否已存在?可能是您的操作系统阻止了文件被覆盖。。@WWillem Van Onsem file.txt或prolog(SPIDER plugin)中的相同文件?它与PDT eclipse(SWI)一起工作,但到目前为止,我必须使用SICStus prologSWI。它比SICStus好吗?@AnsPiter。两者都有优点和缺点,所以我的答案是双重的:(1)这取决于。(2)YMMV!:)我认为这在很大程度上取决于库的精髓,所以RMV。