나는 프롤로그 초보자이며 목록에 문자열을 구문 분석하는 데 막혔습니다. 나는 형태프롤로그에서 목록으로 변환 문자열
1..2...3..4
나는이 기능을 달성 할 수있는 방법
[1, _, _, 2, _, _, _, 3, _, _, 4]
과 같은리스트로 변환 할 문자열을 가지고?
나는 프롤로그 초보자이며 목록에 문자열을 구문 분석하는 데 막혔습니다. 나는 형태프롤로그에서 목록으로 변환 문자열
1..2...3..4
나는이 기능을 달성 할 수있는 방법
[1, _, _, 2, _, _, _, 3, _, _, 4]
과 같은리스트로 변환 할 문자열을 가지고?
다른 해결책은 DCG를 사용하는 것입니다. 코드는 간단하다 :
digit(N) -->
[ D ], { member(D, ""), number_codes(N, [D]) }.
dot(_) --> ".".
token(T) --> digit(T).
token(T) --> dot(T).
tokens([T|Ts]) --> token(T), tokens(Ts).
tokens([]) --> "".
parse_codes(In, Out):-
phrase(tokens(Out), In, "").
parse_atom(In, Out):-
atom_codes(In, Codes),
parse_codes(Codes, Out).
(실제로는 단지 코드의 목록입니다) "문자열"와 SWI - 프롤로그에
테스트 : 단지 코드로 변환됩니다
?- parse_codes("1..24.4", Out).
Out = [1, _G992, _G995, 2, 4, _G1070, 4] .
그리고 원자와 함께 () 같은 술어를 사용하기 전에 : 조금 애호가 표기법
?- parse_atom('1..22.4', Out).
Out = [1, _G971, _G974, 2, 2, _G1049, 4] .
SWI-Prolog에 인쇄 익명 변수 (_)하지만 그렇지 않으면 당신이 필요로하는 동일한 결과를해야합니다.
수 당신의 문자열에서 문자 및 목록의 요소 사이의 관계를 설명하는 술어 :
char_to_el(DigitChar, Digit) :- % a character between '0' and '9'
DigitChar >= 0'0, DigitChar =< 0'9,
number_codes(Digit, [DigitChar]).
char_to_el(0'., _). % the element is the '.' characther
캐릭터가 참으로 자리하고 정수로 변환 여부를 첫 번째 절을 확인합니다. 문자의 정수 값에서 0'0
을 간단히 빼기 때문에 number_code/2를 사용하는 대신 Digit is DigitChar - 0'0
을 쓸 수 있습니다.
당신은 사용할 수 있어야 maplist/3 다음은 GNU 프롤로그 설명서에 따라 : 대신
| ?- maplist(char_to_el, "1..2...3..4", L).
L = [1,_,_,2,_,_,_,3,_,_,4]
yes
있지만 (아마도 오래된 GNU 프롤로그 버전?) 내 시스템에 작동하지 않았다, 그래서 :
str_to_list([], []).
str_to_list([C|Cs], [E|Es]) :-
char_to_el(C, E),
str_to_list(Cs, Es).
| ?- str_to_list("1..2...3..4", L).
L = [1,_,_,2,_,_,_,3,_,_,4]
yes
또 다른 방법은 0..9의 ascii 숫자가 알려진/고정되어 있다는 사실을 활용하면 형식 변환이나 검사가 필요없고 빼기 만하면됩니다.
% case 1: char is in decimal range 0-9, ie ascii 48,49,50,51,52,53,54,55,56,57
% so eg. char 48 returns integer 0
onechar(Char, Out) :-
between(48, 57, Char),
Out is Char -48.
% case 2: case 1 failed, dot '.' is ascii 46, use anonymous variable
onechar(46, _).
% execution
go(InString, OutList) :-
maplist(onechar, InString, OutList).
실행 :
?- go("1..2...3..4", X).
X = [1, _G5638, _G5641, 2, _G5650, _G5653, _G5656, 3, _G5665, _G5668, 4]
편집 :이 문자열은 ASCII 번호 목록으로 표시되기 때문에 작동하므로 문자열 ""가 [48,49,50로 내부적으로 표현되는 말을 잊었다 , 51,52,53,54,55,56,57].
onechar이 해당 목록 항목 중 1 개에 대해 계산을 수행하면 maplist는 모든 목록 항목에서 동일한 조건자를 호출합니다.
편집 2 : 두번째 규칙은 원래이었다
이% case 2: case 1 failed, output is an anon variable
onechar(_, _).
이 너무 관대 - 입력이 0.9 점은 다음 조건에 장애가 포함되지 않은 것으로 추정합니다.
직접 아스키 코드 대신에 '0'표기법을 사용해야합니다. 읽기 쉽고 똑같습니다 (매직 넘버는 없습니다). –
포인트 또는 정수 사이에 한 자리 숫자가 있습니까? 다시 말해'12.23 '은'[1, 2, _, 2, 3]'또는'[12, _, 23]'로 이동합니까? –
한자리 수입니다. 그래서 12.23은 [1, 2, _, 2, 3]이됩니다. –