How can I generate text file with all the prime numbers in progress 4gl - progress-4gl

In the below code i am importing a text file with numbers 3 to 99 .
i have partially written code to find out the prime numbers from the given numbers.
define variable a as integer.
define variable b as integer.
define variable i as integer initial 0.
INPUT FROM Value ( "C:\src\New folder\bingo.txt").
repeat :
IMPORT a.
b = a mod i.
if b=0 then
do:
if a=i then
do:
message " prime number"a view-as alert-box.
end.
else if a<>i then
do:
i=i + 1.
message " not prime number"a view-as alert-box.
end.
else if a < i then
do:
message "not prime number"a view-as alert-box.
end.
end.
END.
if b<>0 then
do:
i=i + 1.
message "b<>0"b view-as alert-box.
end.
end.
Output To Value( "C:\src\New folder\even.txt")append.
export a space.
output close.
end.
end.
help me with .
to program

I think it will make more sense to store the prime check in a function or a procedure. This prime check isn't necessary perfect but it will work for these conditions.
Also it's best to define and use streams when working with both in- and output.
DEFINE VARIABLE a AS INTEGER NO-UNDO.
DEFINE VARIABLE b AS INTEGER NO-UNDO.
DEFINE STREAM strIn.
DEFINE STREAM strOut.
FUNCTION isPrime RETURNS LOGICAL (INPUT iNum AS INTEGER ):
DEFINE VARIABLE iDiv AS INTEGER NO-UNDO.
DO iDiv = 2 TO INTEGER(SQRT(iNum)):
IF iNum MOD iDiv = 0 THEN
RETURN FALSE.
END.
RETURN TRUE.
END.
OUTPUT STREAM strOut TO VALUE ("c:\temp\primes.txt").
INPUT STREAM strIn FROM Value ( "C:\temp\bingo.txt").
repeat :
IMPORT STREAM strIn a.
IF isPrime(a) THEN DO:
/*MESSAGE "prime number" a view-as alert-box. */
PUT STREAM strOut UNFORMATTED a SKIP.
END.
ELSE DO:
/*MESSAGE "not prime number" a view-as alert-box. */
END.
END.
INPUT STREAM strIn CLOSE.
OUTPUT STREAM strOut CLOSE.

Related

Progress 4GL - update

how can I check if update was successful when I run this For Each
FOR EACH products
WHERE products.name = "ProductsName":
update price = 1000.
END.
Sometimes this For Each is ok, but sometimes when record is lock it doesn't work. I need run this For Each via WebSpeed and return true when For Each is successful or false when not. How can I get this result?
You should add more details to your request, but try this it might help get you started:
procedure update_items:
define output parameter records_read as integer no-undo.
define output parameter records_updated as integer no-undo.
define output parameter records_locked as integer no-undo.
define buffer item for item.
define buffer item_update for item.
define variable retry_count as integer no-undo.
for each item no-lock:
accumulate 1 (total).
records_read = (accum total 1).
retry_count = 0.
repeat for item_update:
find item_update exclusive-lock
where rowid(item_update) = rowid(item)
no-wait no-error.
if locked item_update then do:
if retry_count > 5 then do:
records_locked = records_locked + 1.
leave.
end.
retry_count = retry_count + 1.
do on endkey undo, leave:
pause 3 no-message.
end.
undo, next.
end.
if not available item_update then do:
/*If that matters you can code for it too*/
leave.
end.
item_update.Price = 1000.
release item_update.
records_updated = records_updated + 1.
leave.
end.
end.
end.
define variable items_read as integer no-undo.
define variable items_updated as integer no-undo.
define variable items_locked as integer no-undo.
run update_items(output items_read,
output items_updated,
output items_locked).
display items_read items_updated items_locked with side-labels 1 col.

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.

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.