QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: EricE on February 21, 2020, 05:52:29 pm

Title: The strpbrk function - Should it not be used in QB64 programs?
Post by: EricE on February 21, 2020, 05:52:29 pm
The C language "string pointer break" function,  strpbrk, has this prototype:
Quote
char* strpbrk(char* dest, const char* breakset );
and it performs this function:
Quote
Scans the null-terminated byte string pointed to by dest for any character from the null-terminated byte string pointed to by breakset, and returns a pointer to that character.
https://en.cppreference.com/w/cpp/string/byte/strpbrk (https://en.cppreference.com/w/cpp/string/byte/strpbrk)

In QB64 the strpbrk function is made callable using the declaration:
Code: QB64: [Select]
  1.         'Find the first occurrence in x$ of any of the characters in y$.
  2.         FUNCTION strpbrk%& (x$, y$)
  3.     END DECLARE
  4.  

The strpbrk returns a pointer to a character in a string, but QB64 might at any time move a string to another memory location.
If QB64 relocates the string after strpbrk has been called, then the returned character address will no longer be valid.

Should we conclude that the strpbrk function not be used in QB64 programs?

Some more question about how QB64 works.

Title: Re: The strpbrk function - Should it not be used in QB64 programs?
Post by: SMcNeill on February 21, 2020, 06:10:08 pm
I’d say:

1) Use with fixed length string *only*, as they never move in memory.
2) QB64 strings aren’t null terminated by default, so either add a CHR$(0) to your strings, or manually error check:

Startpos = _OFFSET(fixedlengthstring$)
Findpos = strpbrk(fixedlengthstring$, “foo”)
If Findpos - Startpos > LEN(fixedlengthstring$) THEN Findpos = 0 ‘null terminator outside string memory area


Note: I can’t swear the above still wouldn’t give error messages if the function failed to find a CHR$(0) before hitting restricted memory.  I don’t think ‘d personally consider it safe to use, except when I knew I was working with null-terminated strings.
Title: Re: The strpbrk function - Should it not be used in QB64 programs?
Post by: FellippeHeitor on February 21, 2020, 06:18:22 pm
Any advantages to using the C call instead of INSTR (http://www.qb64.org/wiki/INSTR), for example?
Title: Re: The strpbrk function - Should it not be used in QB64 programs?
Post by: TempodiBasic on February 21, 2020, 06:20:23 pm
Hi EricE
welcome to the forum!
Waiting other coders more expert and/or the developers of QB64  with their accurately answers
my 2 cents
about 
Quote
Should we conclude that the strpbrk function not be used in QB64 programs?
I can observe that  "string pointer break" function,  strpbrk works like INSTR of Qbasic but using pointers and String Null terminated, like C usually is used to do.

about
Quote
Does QB64 pass the x$ and y$ strings to the strpbrk%& function by reference, or by value?
IMHO QB has always passed arguments as reference except some cases among these there are external procedure see here http://www.qb64.org/wiki/DECLARE_LIBRARY (http://www.qb64.org/wiki/DECLARE_LIBRARY) and here http://www.qb64.org/wiki/Parenthesis (http://www.qb64.org/wiki/Parenthesis)

about
Quote
Will the strpbrk function see the x$ and y$ parameters as null-terminated character strings?
I think no because I have seen many example code with interface with C/C++ in which you must manually add CHR$(0) at the end of string before use them as parameter of a C function. See here http://www.qb64.org/wiki/Windows_Libraries#Windows_API (http://www.qb64.org/wiki/Windows_Libraries#Windows_API)

PS Too late :-)))
Title: Re: The strpbrk function - Should it not be used in QB64 programs?
Post by: EricE on February 22, 2020, 03:00:05 pm
Thank you SMcNeill, FellippeHeitor, and TempodiBasic for your replies.
Thank you TempodiBasic for the welcome to the forum.

The answer to my question is that the strpbrk function can be used in QB64 programs.
The requirements for calling the function are:
There is another consideration.
Here is QB64 code for the sinstr% (x$, y$) function.
It uses strpbrk to find the string position in x% of the first occurrence of any character in y$.

Code: QB64: [Select]
  1. DECLARE FUNCTION sinstr% (str1$, set1$)
  2.  
  3. a$ = "Hello"
  4. b$ = "ol"
  5.  
  6. i% = sinstr(a$, b$)
  7.  
  8.  
  9. '-------------------------------------------------------------------------------
  10. ' Function: sinstr% (str1$, set1$)
  11. ' Finds position in str1$ of first occurrence of any of the characters in set1$
  12. '
  13. '------------------------------------------------
  14. ' References:
  15. ' https://www.qb64.org/wiki/MEM
  16. ' http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/forum/index_topic_5967-30/
  17. '------------------------------------------------
  18.  
  19. FUNCTION sinstr% (str1$, set1$)
  20.         'Find the first character in x$ of any of the characters in y$.
  21.         FUNCTION strpbrk%& (x$, y$)
  22.     END DECLARE
  23.  
  24.     DIM m AS _MEM 'Define a memblock
  25.  
  26.     ' copy variable strings to fixed length strings
  27.     ' add terminating null.
  28.     str1$1024 = str1$ + CHR$(0)
  29.     set1$ = set1$ + CHR$(0)
  30.  
  31.     find_first_of%& = strpbrk%&(str1$1024, set1$)
  32.     IF find_first_of%& <> 0 THEN
  33.         'Strings are unit-based in QB64, so we must add 1.
  34.         find_first_of%& = find_first_of%& - _OFFSET(str1$1024) + 1
  35.     END IF
  36.     m = _MEM(find_first_of%&)
  37.  
  38.     $IF 64BIT THEN
  39.         'On 64 bit OSes, an OFFSET is 8 bytes in size.
  40.         _MEMGET m, m.OFFSET, temp&&
  41.         sinstr% = temp&&
  42.     $ELSE
  43.         'However, on 32 bit OSes, an OFFSET is only 4 bytes.
  44.         _MEMGET m, m.OFFSET, temp&
  45.         sinstr% = temp&
  46.     $END IF
  47.  
  48.     _MEMFREE m 'Free the memblock
  49.  
Title: Re: The strpbrk function - Should it not be used in QB64 programs?
Post by: EricE on February 22, 2020, 03:11:49 pm
FellippeHeitor wrote:
Quote
Any advantages to using the C call instead of INSTR, for example?
Definitely not!
Using INSTR to implement the sinstr% function requires only 10 lines of QB64 code.
The code simpler and looks much better than the version using strpbrk.
Also the INSTR version does not require worrying about strings being of fixed length and null terminated.
It just works!

Code: QB64: [Select]
  1. DECLARE FUNCTION sinstr% (str1$, set1$)
  2.  
  3. a$ = "Hello"
  4. b$ = "lo"
  5.  
  6. i% = sinstr(a$, b$)
  7.  
  8.  
  9. 'Find the first character in str1$ of any of the characters in set1$.
  10.  
  11. FUNCTION sinstr% (str1$, set1$)
  12.     sinstr% = 0
  13.     FOR i% = 1 TO LEN(str1$)
  14.         ptr% = INSTR(set1$, CHR$(ASC(str1$, i%)))
  15.         IF ptr% <> 0 THEN
  16.             sinstr% = i%
  17.             EXIT FOR
  18.         END IF
  19.     NEXT i%
Title: Re: The strpbrk function - Should it not be used in QB64 programs?
Post by: FellippeHeitor on February 22, 2020, 03:39:24 pm
Glad to hear you found your way around it. You can also replace two function calls - the CHR$(ASC(str1$, i%)) bit - with one: MID$(str1$, i%, 1).