Page 1 of 1

From string to integer

Posted: 24 Mar 2021 14:58
by belyy_lis
Hello everyone, I was given a lab to do in Visual Prolog. I have to make a calculator. Read from a text file and write to the list.
Is there a way to convert a string to a number?

Re: From string to integer

Posted: 24 Mar 2021 15:44
by Thomas Linder Puls
Given that the format match that of a Visual Prolog number you can use:

Code: Select all

Number = tryConvert(integer, String)
where integer could instead be for example real.

Re: From string to integer

Posted: 24 Mar 2021 16:05
by belyy_lis

Code: Select all

implement main     open core, file, console, string   domains     result_list = integer*.   class predicates     culc : (inputStream) nondeterm.     suM : (integer, integer).     suB : (integer, integer).     muL : (integer, integer).     diV : (integer, integer).   clauses     suM(F, S) :-         X = F + S,         write(X).     suB(F, S) :-         X = F - S,         write(X).     muL(F, S) :-         X = F * S,         write(X).     diV(F, S) :-         X = F / S,         write(X).       culc(In) :-         In:endOfStream(),         In:close(),         !.     culc(In) :-         frontToken(In:readLine(), FirstParam, R),         write(FirstParam),         Number = tryConvert(integer, "2"),         write(Number - 1),         frontToken(R, Oper, SecondParam),         write(Oper),         write(SecondParam),         culc(In).   clauses     run() :-         init(),         In = inputStream_file::openFile8("sourceIn.txt"),         culc(In),         _ = readLine(),         !         or         _ = readLine().   end implement main   goal     console::run(main::run).
Type Action Description Filename Path
e504 The expression has type '::string', which is incompatible with the type '::integer' main.pro

Re: From string to integer

Posted: 24 Mar 2021 18:27
by Thomas Linder Puls
Sorry, I typed the wrong predicate, it should be:

Code: Select all

Number = tryToTerm(integer, String)

Re: From string to integer

Posted: 24 Mar 2021 19:22
by belyy_lis
Thank you so much. Now it counts, but only the first block works, in my case it is "+". How can I make it jump to the required block depending on the expression?

Code: Select all

implement main     open core, console, string   domains     result_list = integer*.   class predicates     culc : (inputStream) nondeterm.     suM : (integer, integer).     suB : (integer, integer).     muL : (integer, integer).     diVi : (integer, integer).   clauses     suM(F, S) :-         X = F + S,         write(X),         nl.     suB(F, S) :-         X = F - S,         write(X),         nl.     muL(F, S) :-         X = F * S,         write(X),         nl.     diVi(F, S) :-         X = F / S,         write(X),         nl.       culc(In) :-         In:endOfStream(),         In:close(),         !.       culc(In) :-         frontToken(In:readLine(), FirstParam, R),         frontToken(R, Oper, SecondParam),         Oper = "+",         F = tryToTerm(integer, FirstParam),         S = tryToTerm(integer, SecondParam),         suM(F, S),         culc(In),         !.       culc(In) :-         frontToken(In:readLine(), FirstParam, R),         frontToken(R, Oper, SecondParam),         Oper = "-",         F = tryToTerm(integer, FirstParam),         S = tryToTerm(integer, SecondParam),         suB(F, S),         culc(In).       culc(In) :-         frontToken(In:readLine(), FirstParam, R),         frontToken(R, Oper, SecondParam),         Oper = "*",         F = tryToTerm(integer, FirstParam),         S = tryToTerm(integer, SecondParam),         muL(F, S),         culc(In).       culc(In) :-         frontToken(In:readLine(), FirstParam, R),         frontToken(R, Oper, SecondParam),         Oper = "/",         F = tryToTerm(integer, FirstParam),         S = tryToTerm(integer, SecondParam),         diVi(F, S),         culc(In).   clauses     run() :-         init(),         In = inputStream_file::openFile8("sourceIn.txt"),         culc(In),         _ = readChar(),         !         or         _ = readLine().   end implement main   goal     console::run(main::run).

Re: From string to integer

Posted: 25 Mar 2021 12:00
by Harrison Pratt
This would be a good time to learn how to use the debugger and walk through the code as it executes.

Put your cursor on the line with culc(In) in your run clause and press F9 to set a breakpoint.

Then press F5 (or click the single green triangle on the toolbar) to run the code in the debugger.

Press F10 to step through the code and see the execution flow. If you press Ctrl-Alt-V you can see the values of variables as they are created.

Re: From string to integer

Posted: 25 Mar 2021 14:00
by Martin Meyer
Yes, walk through the code by the debugger. Study the VIP Language Reference and tutorials. Doing so you will quickly become used to write programs in VIP.

One way to jump to required blocks depending on the expression would be (including some beautification):

Code: Select all

implement main   class predicates     tryCalc : (string Line) -> integer Result determ. clauses     tryCalc(Line) = Result :-         string::frontToken(Line, FirstParamStr, Line1),         FirstParam = tryToTerm(FirstParamStr),         string::frontToken(Line1, Oper, Line2),         string::frontToken(Line2, SecondParamStr, Line3),         SecondParam = tryToTerm(SecondParamStr),         Line3 = "",         try             Result = tryCalc_evaluate(FirstParam, Oper, SecondParam)         catch _TraceId do             fail         end try.   class predicates     tryCalc_evaluate : (integer FirstParam, string Oper, integer SecondParam) -> integer Result determ. clauses     tryCalc_evaluate(FirstParam, "+", SecondParam) = FirstParam + SecondParam.       tryCalc_evaluate(FirstParam, "-", SecondParam) = FirstParam - SecondParam.       tryCalc_evaluate(FirstParam, "*", SecondParam) = FirstParam * SecondParam.       tryCalc_evaluate(FirstParam, "/", SecondParam) = FirstParam div SecondParam.   clauses     run() :-         %init(), % a call to init is not necessary here in current VIP 9.0.6         InStream = inputStream_file::openFileUtf8(@"..\sourceIn.txt"),         Line = InStream:readLine(),         InStream:close(),         if Result = tryCalc(Line) then             stdIo::write(Line, " = ", Result)         else             stdIo::write("Error in \"", Line, "\"")         end if.   end implement main   goal     console::runUtf8(main::run).
It assumes that you place the sourceIn.txt file in the project directory. Text files can be created and added to the project within the IDE.

Re: From string to integer

Posted: 25 Mar 2021 19:27
by Gukalov
Good evening.
Martin, integer can be negative.

Code: Select all

clauses     run() :-         if string::frontToken("-10+5", Token, Rest) then             console::writef("Token = '%s'; Rest = '%s'", Token, Rest)         end if,         console::write("\n....................."),         _ = console::readLine().   %  Token = '-'; Rest = '10+5'

Re: From string to integer

Posted: 25 Mar 2021 20:46
by Martin Meyer
Correct, integers can be negative. The language accepted in the example is but extremely simple. It accepts only number literals without leading signs.

Optional leading signs would make the example more complicated. Signed numbers are usually implemented in parsers through unary functions "-" and "+". Functions can be nested. For example -+--3 is a legal integer constant in VIP.

A full-blown parser for arithmetical expressions can be constructed with the LALR Parser Generator (in the Commercial Edition). However that is a lot more complicated than the tiny example.