How to check if string is a palindrome in open edge progress 4gl - progress-4gl

How can I check whether a given string is a palindrome or not in open edge progress 4gl? Is there any reverse string function built-in with progress 4gl?
FUNCTION reverseString RETURNS CHARACTER (
INPUT i_c AS CHARACTER
):
DEFINE VARIABLE cresult AS CHARACTER NO-UNDO.
DEFINE VARIABLE ii AS INTEGER NO-UNDO.
DO ii = LENGTH( i_c ) TO 1 BY -1:
cresult = cresult + SUBSTRING( i_c, ii, 1 ).
END.
RETURN cresult.
END FUNCTION.
display reverseString( "asdf" ).

The complete OpenEdge doc set can be found here:
https://community.progress.com/community_groups/openedge_general/w/openedgegeneral/1329.openedge-product-documentation-overview.aspx
As you can see, there is no built-in reverse string function.
A function like the one that you illustrate above is what you need.
To determine if a string is a palindrome using that function:
myString = "asdf".
if myString = reverseString( myString ) then
message "yes," myString "is a palindrome".
else
message "no," myString "is not a palindrome".

Related

Generic Procedure to generate report from browse in progress 4gl

Procedure should handle any table linked to browse means it should be generic.
please help.
/* below code is sample to Show the data in message box ,
but only first data it is showing right now.*/
DEFINE INPUT PARAMETER hRecord AS WIDGET-HANDLE.
DEFINE INPUT PARAMETER hQuery AS WIDGET-HANDLE .
DEF VAR hFld AS HANDLE NO-UNDO.
DEFINE VARIABLE iCOunt AS INTEGER INITIAL 0.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE j AS integer INITIAL 1.
MESSAGE hRecord:NUM-COL VIEW-AS ALERT-BOX.
DO WHILE TRUE:
hQuery:GET-NEXT().
iCount = iCount + 1.
DO i = 1 TO hRecord:NUM-COL:
hfld = hRecord:GET-BROWSE-COL(i).
MESSAGE hfld:SCREEN-VALUE.
END.
j = j + 1.
END.
MESSAGE iCount VIEW-AS ALERT-BOX.
END PROCEDURE.
You can get a buffer field like so:
hfld = hRecord:GET-BUFFER-FIELD(i).
and then get the field's value:
DISPLAY hfld:BUFFER-VALUE.
See the docs for an explanation of what these do.

Convert the decimal value to get the split binary in Progress 4gl

I have to make a program which has the output like this :
def var vbit as logical extent 64 initial "false".
def var x as char form "x(16)" /* to store the decimal input */
Input : 2220010000000000
convert the value into:
22=00100010
20=00100000
01=00000001
00=00000000
00=00000000
00=00000000
00=00000000
then if the binary is sorted,the output will be:
123456789012345678901234
00100010001000000000000100000000000000000000000000000000
from this binary, change the vbit [x] like on the image.
Thanks a lot for the answer.
This is a quick example, most likely not usable for production like enviroments...
As far as I know there are no built in functions or methods to create binary numbers. So I've borrowed a function from here:
http://knowledgebase.progress.com/articles/Article/P125416
I've modified the function to return the integers with a 4 digit format, this will work for this specific example but of course not for larger binary numbers.
DEFINE VARIABLE vbit AS LOGICAL EXTENT 64 NO-UNDO .
DEFINE VARIABLE cString AS CHARACTER NO-UNDO FORMAT "x(16)".
DEFINE VARIABLE cBinary AS CHARACTER NO-UNDO.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
ASSIGN
cString = "2220010000000000".
FUNCTION getBinary RETURNS CHARACTER (INPUT piValue AS INTEGER):
DEFINE VARIABLE cReturn AS CHARACTER NO-UNDO .
DEFINE VARIABLE iReturn AS INTEGER NO-UNDO FORMAT "9999".
DO WHILE piValue > 0:
ASSIGN
cReturn = STRING( piValue MOD 2 ) + cReturn
piValue = TRUNCATE( piValue / 2, 0 )
.
END.
IF cReturn = "" THEN cReturn = "0".
iReturn = INTEGER(cReturn).
RETURN STRING(iReturn, "9999").
END FUNCTION.
/* Convert the string of integers into a binary format */
DO i = 1 TO LENGTH(cString):
cBinary = cBinary + getBinary(INTEGER(SUBSTRING(cString, i, 1))).
END.
/* Move the binary numbers into the boolean variable */
DO i = 1 TO LENGTH(cBinary).
IF SUBSTRING(cBinary, i, 1) = "1" THEN
vbit[i] = TRUE.
ELSE
vbit[i] = FALSE.
END.
/* Uncomment this to output
123456789012345678901234
00100010001000000000000100000000000000000000000000000000
*/
/*
DISP "123456789012345678901234" SKIP
cBinary FORMAT "x(70)" WITH FRAME fr1 4 DOWN WIDTH 90.
*/
/* Display the boolean variable in the specified format */
DISP vbit WITH FRAME fr2 SIDE-LABELS 4 COLUMNS WIDTH 90 25 DOWN.

is it possible to use MaximumFuntion within an Entry Funciton in Progress 4gl

I am new to progress and I am trying to figure out how to get this working. My task is to Get a list of integer values from user as semi colon separated and message the highest and lowest value on that list. Till now I have used an entry function to help me get just the integers entered by the user one after another. like so
repeat I = 1 to totalEntries:
m = entry (I, Userinput, ";").
display m.
end.
After this I would like to find out the maximum value of all the entries. how can I do this since maximum function accepts more than one value for comparison.
There is no built in function to give a maximum or minimum number from given list of numbers. You need to write your own logic as in most of the programming languages. Here is an example:
DEF VAR i AS INT.
DEF VAR nlist AS CHAR INIT "1;2;7;3;6;9".
DEF VAR imin AS INT.
DEF VAR imax AS INT.
imin = INTEGER(ENTRY (1, nlist, ";")).
imax = INTEGER(ENTRY (1, nlist, ";")).
REPEAT i = 2 TO NUM-ENTRIES(nlist, ";"):
IF INTEGER(ENTRY(i, nlist, ";")) > imax THEN
imax = INTEGER(ENTRY(i, nlist, ";")).
IF INTEGER(ENTRY(i, nlist, ";")) < imin THEN
imin = INTEGER(ENTRY(i, nlist, ";")).
END.
MESSAGE imax.
MESSAGE imin.
As Austin sad, there is no built-in function in Progress to give a maximum or minimum number from a list.
In your comment, you've mentioned that MAXIMUM(1,2,3) worked. Yes, it works, but you have to figure that you're passing three parameters to the function, not a list of numbers inside a single CHAR variable.
To solve your problem you can use the solution given by Austin or you can use two functions that receive a CHAR variable with semi colon separated values and return maximum or minimum values.
Here is an example, based on your code.
FUNCTION iMax RETURNS INTEGER
( INPUT pData AS CHAR ):
DEF VAR iOutput AS INT NO-UNDO.
DEF VAR iCount AS INT NO-UNDO.
iOutput = ?.
DO iCount = 1 TO NUM-ENTRIES(pData,';'):
IF iOutput = ? THEN DO:
iOutput = INT(ENTRY(iCount,pData,';')).
NEXT.
END.
iOutput = MAX(iOutput,INT(ENTRY(iCount,pData,';'))).
END.
RETURN iOutput.
END FUNCTION.
FUNCTION iMin RETURNS INTEGER
( INPUT pData AS CHAR ):
DEF VAR iOutput AS INT NO-UNDO.
DEF VAR iCount AS INT NO-UNDO.
iOutput = ?.
DO iCount = 1 TO NUM-ENTRIES(pData,';'):
IF iOutput = ? THEN DO:
iOutput = INT(ENTRY(iCount,pData,';')).
NEXT.
END.
iOutput = MIN(iOutput,INT(ENTRY(iCount,pData,';'))).
END.
RETURN iOutput.
END FUNCTION.
/****************/
Define variable NumberEntry as character view-as fill-in no-undo.
Define variable UsersInput as character no-undo.
Define variable i as integer no-undo.
Define variable totalEntries as integer no-undo.
Define variable m as character no-undo.
Define variable n as character no-undo.
Define button bFind.
Define frame main numberEntry label "Enter numbers separated by semi colon" skip
bFind label "Find Max and Min" with side-labels. /*Trigger for button*/
On choose of bFind in frame main do: /*Retrieve the users input*/
Usersinput = (numberEntry:screen-value). /*to find out how many characters the user has enterd.*/ totalEntries = num-entries(UsersInput,';'). Display totalentries. /*Logic to extract Users input values one by one.*/
Repeat i = 1 to totalEntries: M = entry(i, UsersInput, ";").
Display m.
End. /*Logic to find the maximum element. */ .....
MESSAGE 'MAXIMUM :' iMax(UsersInput) SKIP
'MINIMUM :' iMin(UsersInput)
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END.
VIEW FRAME main.
ENABLE ALL WITH FRAME main.
WAIT-FOR CHOOSE OF bfind.
You can call iMax() or iMin() and get MAX or MIN values from Progress MAXIMUM and MINIMUM function using a CHAR list of INTEGER values separated by semi colons without need to make a full code block to do the comparision and get the information for each situation that presents necessary.
Hope it helps.

OpenEdge: how to remove HTML tags from a string?

I have tried doing this:
REPLACE(string, "<*>", "").
but it doesn't seem to work.
REPLACE doesn't work like that. There's no wildcard matching in it.
I've included a simple way of doing this below. However, there's lots of cases that this wont work in - non well formed html etc. But perhaps you can start here and move forward by yourself.
What I do is look for < and > in the text and replace everything between it with a pipe (|) (you could select any character - preferably something not present in the text. When that's done all pipes are removed.
Again, this is a quick and dirty solution and not safe for production...
PROCEDURE cleanHtml:
DEFINE INPUT PARAMETER pcString AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER pcCleaned AS CHARACTER NO-UNDO.
DEFINE VARIABLE iHtmlTagBegins AS INTEGER NO-UNDO.
DEFINE VARIABLE iHtmlTagEnds AS INTEGER NO-UNDO.
DEFINE VARIABLE lHtmlTagActive AS LOGICAL NO-UNDO.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DO i = 1 TO LENGTH(pcString):
IF lHtmlTagActive = FALSE AND SUBSTRING(pcString, i, 1) = "<" THEN DO:
iHtmlTagBegins = i.
lHtmlTagActive = TRUE.
END.
IF lHtmlTagActive AND SUBSTRING(pcString, i, 1) = ">" THEN DO:
iHtmlTagEnds = i.
lHtmlTagActive = FALSE.
SUBSTRING(pcString, iHtmlTagBegins, iHtmlTagEnds - iHtmlTagBegins + 1) = FILL("|", iHtmlTagEnds - iHtmlTagBegins).
END.
END.
pcCleaned = REPLACE(pcString, "|", "").
END PROCEDURE.
DEFINE VARIABLE c AS CHARACTER NO-UNDO.
RUN cleanHtml("This is a <b>text</b> with a <i>little</i> bit of <strong>html</strong> in it!", OUTPUT c).
MESSAGE c VIEW-AS ALERT-BOX.

How to test if string is numeric using Progress 4GL

Does Progress 4GL have a function for testing whether a string is numeric, like PHP's is_numeric($foo) function?
I've seen the function example at http://knowledgebase.progress.com/articles/Article/P148549 to test if a character in a string is numeric. Looks like it has a typo, btw.
But I would think the language would be a built-in function for this.
I was looking at this myself recently. The approved answer given to this doesn't work in 100% situations.
If the user enters any of the following special string characters: ? * - or + the answer won't work.
A single plus or minus(dash) is converted to 0 which you may not want.
A single question mark character is valid value which progress recognises as unknown value at which again you may not want.
A single or group asterisks on their own also get converted to 0.
If you run the following code you'll see what I mean.
DISP DECIMAL("*")
DECIMAL("**")
DECIMAL("?")
DECIMAL("+")
DECIMAL("-").
The following additional code maybe useful to get around this
DEFINE VARIABLE iZeroCode AS INTEGER NO-UNDO.
DEFINE VARIABLE iNineCode AS INTEGER NO-UNDO.
DEFINE VARIABLE chChar AS CHARACTER NO-UNDO.
ASSIGN iZeroCode = ASC("0")
iNineCode = ASC("9")
chChar = SUBSTRING(cNumber,1,1).
IF NOT(ASC(chChar) >= iZeroCode AND ASC(chChar) <= iNineCode) THEN DO:
MESSAGE "Invalid Number..." VIEW-AS ALERT-BOX.
END.
Do not need a function can jsut do a straight conversion.
ASSIGN dNumber = DECIMAL(cNumber) NO-ERROR.
IF ERROR-STATUS:ERROR THEN
DO:
{Handle issues}
END.
or if it is always whole numbers can use INTEGER instead of DECIMAL.
The language does not have a built-in "isNum()" type of function.
An alternative to the kbase method would be:
function isNum returns logical ( input s as character ):
define variable n as decimal no-undo.
assign
n = decimal( s )
no-error
.
return ( error-status:num-messages = 0 ).
end.
display isNum( "123" ) isNum( "xyz" ).
This code handles any numeric strings - even if the used Character is longer than the max Decimal length etc.
FUNCTION isNumeric RETURNS LOGICAL (textvalue AS CHAR):
DEF VAR i AS INT NO-UNDO.
IF textvalue = ? THEN RETURN TRUE.
DO i = 1 TO (LENGTH(textvalue) - 1):
INT(SUBSTRING(textvalue, i, (i + 1))) NO-ERROR.
IF ERROR-STATUS:ERROR THEN RETURN FALSE.
END.
RETURN TRUE.
END FUNCTION.
Works 100% of the time
FUNCTION is-num RETURNS LOGICAL
(INPUT cString AS CHARACTER):
DEFINE VARIABLE iZeroCode AS INTEGER NO-UNDO.
DEFINE VARIABLE iNineCode AS INTEGER NO-UNDO.
DEFINE VARIABLE cChar AS CHARACTER NO-UNDO.
DEFINE VARIABLE iCount AS INTEGER NO-UNDO.
DO iCount = 1 TO LENGTH(cString):
ASSIGN iZeroCode = ASC("0")
iNineCode = ASC("9")
cChar = SUBSTRING(cString,iCount,1).
IF NOT(ASC(cChar) >= iZeroCode AND ASC(cChar) <= iNineCode) THEN DO:
RETURN FALSE.
END.
END.
RETURN TRUE.
END.