2014-04-26 4 views
0

전 프롤로그를 처음 사용했습니다. Prolog에 대한 기본적인 지식 만 가지고 있습니다. Prolog에서이 코드를 작성했으며이 부분을 구현하는 방법을 모른다.프롤로그에 유효한 값을 입력 할 때까지 반복하십시오.

나는 누군가가 그/그녀의 생일을 입력하고 그/그녀의 생일을 기반으로 다른 계산을 원한다. 가치를 계산하기 전에 나는 그가 입력 한 것을 검증하고 싶습니다.

go:-write('Enter your name:'),nl, 
    read(Name),nl, 
    write('Enter your birth year:'),nl, 
    read(Year),nl, 
    write('Enter your birth month:'),nl, 
    read(Month),nl, 
    write('Enter your birth date:'),nl, 
    read(Date). 

등 :

예를 들어이 코드를 썼다.

위의 입력을 검증하는 방법을 알고 있습니다. 하지만 내가 알고 싶은 것은 올바른 값을 입력 할 때까지 입력 과정을 반복하는 법입니다. 예를 들어 사용자가 잘못된 연도를 입력하면 오류 메시지 (예 : 잘못된 연도)가 표시되고 처음부터 다시 시작하지 않고 다시 입력해야합니다. 입력 된 값이 확인되지 않은 경우

답변

3

또 다른 대안은 입력이 무효 인 경우 돌아 가지에 대한 repeat을 사용하는 것입니다. 그리고 당신은 메시지와 사용자 입력 패턴 술어 작성할 수 있습니다

read_input(Prompt, Value, CheckPred, ErrorMsg) :- 
    repeat, 
     format('~w:~n', [Prompt]), 
     read(Value), 
     ( call(CheckPred, Value) 
     -> true, ! 
     ; format('ERROR: ~w.~n', [ErrorMsg]), 
      fail 
     ). 

go :- 
    read_input('Enter your name', Name, check_name, 'Invalid name'), 
    read_input('Enter your birth year', Year, check_year, 'Invalid year'), 
    read_input('Enter your birth month', Month, check_month, 'Invalid month'), 
    read_input('Enter your birth date', Date, check_date, 'Invalid date'), 
    % Do stuff with Name, Year, Month, Date... 
    . 

을 그리고 검사 술어 만들 :

check_name(Name) :- ... 

check_year(Year) :- ... 

check_month(Month) :- ... 

check_date(Date) :- ... 

당신은 쉽게 확장 할 수를 그래서 check_name도 활용과 같은 몇 가지 "수정 - 업"을 수행 이름.

칙 (당신은 check_...는 두 개의 인수 등을 가지고있는 것) - 수정 - 업

read_input(Prompt, Res, CheckPred, ErrorMsg) :- 
    repeat, 
     format('~w:~n', [Prompt]), 
     read(Value), 
     ( call(CheckPred, Value, Res) 
     -> true, ! 
     ; format('ERROR: ~w.~n', [ErrorMsg]), 
      fail 
     ). 

% Check argument, and provided "fixed-up" argument xxxOut 

check_name(Name, NameOut) :- ... 

check_year(Year, YearOut) :- ... 

check_month(Month, MonthOut) :- ... 

check_date(Date, DateOut) :- ... 

나는, 그러나, 전체 날짜를 입력 할 수 있도록 허용하기 추천 할 것입니다/w를 인수 확인 및 그것을 분석하십시오. SWI Prolog에는 그 목적을 위해 사용할 수있는 날짜 술어가 있습니다. 그런 다음 년, 월, 일을 위의 날짜로 바꿀 수 있으며 DateOut의 경우 birthdate(Month, Day, Year)과 같은 용어를 사용할 수 있습니다.

+0

네, 그게 문제입니다. check_date (Month, Date)와 같은 check_date 술어에 두 개의 인수를 전달하려면 어떻게해야합니까? 내가 어떻게 해. 제발 도와주세요 – Daybreaker

+0

@luker는 위의 문제를 해결하는 방법을 말해 줄 수 있습니까 ?? – Daybreaker

+0

@Daybreaker 내 업데이트 된 답변보기 – lurker

2

당신은 꼬리 재귀를 사용할 수 있습니다

get_data(X,Y) :- 
    ask_user(Z,T), 
    (validate(Z,T) -> 
     (X = Z, Y = T); 
     get_data(X,Y)). 

c -> t ; f는 경우 --다른 다음 패턴이다. 조건 c이 충족되면 t이 실행되고 (따라서 입력 된 데이터를 매개 변수로 바인딩), 그렇지 않은 경우 꼬리 재귀를 사용하여 재 시도합니다.

물론이 호출이 스택을 증가 시키지만, 꼬리 재귀를 수행하면 고급 Prolog 컴파일러가 호출 스택에 추가 호출 프레임을 생성하지 않는다고 말할 수 있습니다.

2

당신은 술어를 작성하고 정확한 답변을 얻는 때까지 재귀 적으로 호출 할 수 있습니다 : 여기

read_name(Name) :- 
    write('Your name: '), 
    read(TmpName), 
    ((atom_codes(TmpName, L), length(L, N), N > 5) -> 
     (Name = TmpName) ; 
     (write('Error!'), nl, read_name(Name)) 
    ). 

이름 (N > 5)을 최소 6 charcters 포함 된 경우 그냥 확인을하지만하여 대체 할 수있는 어떤 네가 원해.

입니다 다른 경우의 구문 :

(Conditions -> ActionIfTrue ; ActionIfFalse) 
+0

감사합니다. 나는 그것이 효과가있을 것이라고 생각한다. – Daybreaker

+0

이것은 바보 같은 질문 일 수 있습니다. 사용자가 자신의 이름을 자본으로 입력하면 어떻게 될까요? 대문자로 시작하는 이름을 얻는 방법이 있습니까? – Daybreaker

+2

@Daybreaker 만약 당신이 swipl을 사용한다면, 내장 된 술어'upcase_atom'을 사용할 수 있습니다. 'Name = salut, upcase_atom (Name, NU), string_to_list (NU, [H | _]), string_to_list (이름, [_ | T]), string_to_list (CapName, [H | T]). 전체 문자열을 대문자로 변환하여 첫 번째 문자를 얻는 것보다 나은 방법이지만, 찾지 못했습니다. – Holt

관련 문제