Diese Seite mit anderen teilen ...

Informationen zum Thema:
Forum:
WinDev Forum
Beiträge im Thema:
17
Erster Beitrag:
vor 8 Jahren, 4 Monaten
Letzter Beitrag:
vor 8 Jahren, 4 Monaten
Beteiligte Autoren:
DarrenF, Alexandre Leclerc, Fabrice Harari, Al, Peter H., Louis Verbraak, Paulo Oliveira, Arie, Fred

[WD12] Parsing strings by words...

Startbeitrag von DarrenF am 08.04.2010 07:39

Hi guys,

Is there a string function that can help me parse a string word by word? I've looked at the help and can't see it.

I have a string such as "Thankyou very much for your custom - we do hope you call again" and want to print it onto a receipt where I only have a character width of 42 and I want fit as many complete words on a line, so without splitting a word if you know what I mean?

I know I can do it char by char, but was wondering if there is a nicer (easier) way?

Thanks...

Antworten:

check the help for extractstring

von Paulo Oliveira - am 08.04.2010 08:28
have a look at FOR EACH STRING in the help

von Arie - am 08.04.2010 08:55
Hi Darren

considering that you may have different separators in your string (not only space but commas, dots, and so on), none of the built in functions (being extractstring or for each) will do easily what you want...

In a case like yours, I would start by cutting at 42, and loop back for the first 'accepted' separator (" ,.-/:!/...")...


Best regards



von Fabrice Harari - am 08.04.2010 12:41
Thanks all,

Agreed Fabrice, there doesn't seem to be any built in function I can use - just thought I'd confirm.

In my case, the text string to be put on the receipt can be upto 100 chars (fixed) and the 42 length I mentioned is actaully a variable that is currently set to 42. If the printer char set changes then this width variable may change.

I've been thinking of several ways to do this and of course, your suggestion of cutting and scanning backwards would work.

However, I was thinking of parsing from the start of the string and storing the position of the last known separator.

Doing it this way, when I hit my 42 (variable) char limit, if the 42nd and 43rd chars aren't separators, I can then go back to the last known separator and that's my 1st line, then start from this last known separator char as I know that's the start of the next line and so on...

von DarrenF - am 08.04.2010 13:04
Hi Darren

it would certainly work too, but more slowly, as you have to scan ALL characters while my solution only scans from the end of the line till the last separator. If speed is not an issue, then it's certainly doable the way you describe it

Best regards


von Fabrice Harari - am 08.04.2010 13:35
Yes, agreed... it will be slower, but (for want of a better phrase), it's client side code, so speed isn't really an issue.

Thanks again...


von DarrenF - am 08.04.2010 13:49
Hello Darren,

You could use Replace (to replace all seperating characters for a space) and then use ExtractString or FOR EACH.

HTH.

von Louis Verbraak - am 09.04.2010 14:07
Or with WD14, you can give an array for the separator (third arg) :

// Browse all the sub-strings
// The separators are found in an array
sString is string = "Strawberry, RaspberryLemonChocolate and Banana"
sResult is string = ExtractString(sString,firstRank,[", " , " and ",""])
WHILE sResultEOT
Trace(sResult)
sResult = ExtractString(sString,nextRank,[", " , " and ",""])
END

Regards,
Fred.

von Fred - am 09.04.2010 16:28
Two options:
1) StringToArray()
2) FOR EACH Word OF Sentence SEPARATED BY " "

It is always best to first strip your string from unwanted characters and double spaces etc... For that you can use the Strip*** methods from a class I've posted on the ressource site of PCSoft:

Cheers,

Peter

von Peter H. - am 12.04.2010 12:16
Hi Peter,

Thanks for your reply - the stringtoarray sounds like it may do the trick :spos:

I'm not worried about double spaces and special chars - this bit of processing is to print a user defined promo message onto a receipt.

The user will enter it as they wish. If they don't like a double space for example, I'll tell them to remove it via a maintenance option. Also, the message will be the same on every receipt, so I'll build the string once, probably in the init event of the window.

Thanks again for getting involved - it's appreciated... :cheers:

von DarrenF - am 12.04.2010 12:50
Hello Darren

I appreciate that you can only print in blocks of 42 characters, so why not collect it in that format ?
I gather this is a one off collection of data from the user which you store in a file and then print on each receipt and they may edit the data very occasionally so the collection of the info doesn't have to be pretty.
If they need to print a three line message with each line being 42 characters, give them three 42 character input fields on the screen and let them figure it out ?
Or give them a multiline string input field locked to mutliples of 42 characters in length and just let if wrap when you print it.

Regards
Al

von Al - am 12.04.2010 13:22
Hi Al,

It's a thought and I know what you're saying.

It's the 42 that's (potentially) variable tho depending on the charcter set used on the receipt. This particular receipt is 42 chars wide (at the moment) but may change before "go live".

I think I'm going for the middle ground with this - I'm not going to worry about double spaces or special characters. The user will enter what they want as a single 100 char string and it will be split into words by the presence of a space.

If I use stringtoarray then (as long as I can find the "true" length of each individual array element/word using the Length function), I don't think I'll have a problem.

Thanks for your suggestion - all ideas are welcome... :spos:

von DarrenF - am 12.04.2010 13:49
Hi Darren,

I would personally have done as Fabrice suggested. This is a simple / efficient solution. The following code is not very nice but it serves as a quick example.


SAI_Saisie1 = CutString("When you choose characters as word separators,"+...
" other than a whitespace, be carefull of the context."+...
" You do not want to cut a 10.50$ price in half! In that"+...
" case the period is desired!")

PROCEDURE CutString(LOCAL s is string, nMaxSize is int = 42)

sResult is string
WHILE s""
n is int = Min(nMaxSize+1,Length(s))
IF n > nMaxSize THEN
WHILE n>0 _AND_ s[[n]]" "
n--
END
IF NOT n THEN n = nMaxSize+1 // no sep. found: cut at nMaxSize
ELSE
n++
END
sResult += [CR] + s[[TO n-1]]
s = s[[n+1 TO]]
END

RESULT sResult


(And instead of manipulating s you could simply have a "start pointer" and change the while condition to loop until the "start pointer" reaches the end of the string: WHILE nStart

von Alexandre Leclerc - am 12.04.2010 18:25
Alexandre,

Wow - that's great!

I set up a test of your solution - it works great except it chops off the very last char - I fixed that and it's a good solution :spos: Thanks!

I had to slot in an extra line of code to centre the text within the 42 block of chars and we're done!

...but it's more than that - because I learnt a few new WinDev techniques for handling strings as well :spos:

It's good to get real coding examples - other people may learn something new as well, which should be a big part of what a forum is about :cool:

von DarrenF - am 13.04.2010 08:54
Hi Darren,

I'm glad it's helping you and thank you for the "bug report" :-). I edited the post to add "ELSE n++" in the IF..END. And now we have better code! (The synergy of sharing knowledge - the moment it's for doing good.)

Best regards,
Alexandre Leclerc

von Alexandre Leclerc - am 13.04.2010 12:52
Yes, exactly what I added as well - an ELSE n++ :spos:

von DarrenF - am 13.04.2010 17:12
Zur Information:
MySnip.de hat keinen Einfluss auf die Inhalte der Beiträge. Bitte kontaktieren Sie den Administrator des Forums bei Problemen oder Löschforderungen über die Kontaktseite.
Falls die Kontaktaufnahme mit dem Administrator des Forums fehlschlägt, kontaktieren Sie uns bitte über die in unserem Impressum angegebenen Daten.