how to simulate zstring?
#1
hello
I am trying to to use the mpfr library http://www.mpfr.org but am stumped on how to print to a QB64 string, the function mpfr_sprintf is declared as: int mpfr_sprintf(char *buf, const char *template, ...)
my attempt to use QB strings in place of the char pointer fails, I understand that a char pointer string is a zero terminated string, how do I simulate a zstring in QB64?
Code:
TYPE mpfr_struct
    mpfr_prec AS _OFFSET
    mpfr_sign AS LONG
    mpfr_exp AS _OFFSET
    mpfr_d AS _OFFSET
END TYPE

DECLARE LIBRARY "/usr/local/lib/mpfr"
    SUB mpfr_init2 ALIAS "mpfr_init2" (op1 AS mpfr_struct, BYVAL prec AS _OFFSET)
    SUB mpfr_clear ALIAS "mpfr_clear" (op1 AS mpfr_struct)
    FUNCTION mpfr_sprintf& ALIAS "mpfr_sprintf" (result AS STRING, frmt AS STRING, op1 AS mpfr_struct)
    FUNCTION mpfr_set_ui& ALIAS "mpfr_set_ui" (op1 AS mpfr_struct, BYVAL ui AS _UNSIGNED _OFFSET, BYVAL rd AS LONG)
    FUNCTION mpfr_const_pi& ALIAS "mpfr_const_pi" (op1 AS mpfr_struct, BYVAL rd AS LONG)
END DECLARE

DIM pi as mpfr_struct
DIM c AS LONG
DIM s AS STRING, frmt AS STRING

CALL mpfr_init2(pi, 512)
c = mpfr_const_pi&(pi, 0) 
s = SPACE$(128)
frmt = "%32.28R*g"
c = mpfr_sprintf&(s, frmt, pi) 
PRINT s
CALL mpfr_clear(pi)
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 20.0px Verdana; color: #111111; -webkit-text-stroke: #111111} span.s1 {font-kerning: none}
Reply
#2
hmm i dont know how things work in qb64 but i know that zstring is not
same type as char, char is array of strings so maybe you may use string array
like in DIM A$ as string *255 or something like that ..
wait for hard-coders of qb64
Reply
#3
DECLARE LIBRARY "/usr/local/lib/mpfr"
....ooups this is for linux hmm then i really dont know
Reply
#4
@Aurel,

A C++ CHAR type is a single 8-Bit integer defined as int8_t in C++ (don't know anything about C). It is not an array of characters.

If you had:

Code:
char MyVar;

MyVar would hold only 8-Bits of data. If you wanted an array of 8-Bits of data, or commonly called a string, you would do:

Code:
char MyVar[7];

Now MyVar holds 7 elements that are 8-Bits each.

About ZString...

ZString, from what I can find information on, is a C library, not C++, that works with zero terminated strings. In C++, you can create such a string as such:

Code:
char MyZString[] = "This is a null terminated string/0";



Quote:but i know that zstring is not same type as char

A zstring is a C-style fixed-size array of chars.

Quote:so maybe you may use string array like in DIM A$ as string *255 or something like that

QB64 does not use null-terminated strings, which means it uses descriptors to store the length and other information, even for fixed-length strings. If one studied the C code generated by QB64, they may see the memory allocated for fixed-length strings are all set to 0, which could hint to a null-terminated string, but that is not the case. Even fixed-length strings in QB64 have descriptors.

Quote:wait for hard-coders of qb64

I am a "hard-coder" of QB64, but only for myself.


@Jack,

Could you share the library you are using so we could attempt to figure out what the issue is?
Dedicated to empowering computer programming hobbyists, tinkerers, amateurs, and enthusiasts.
profile for Walter Whitman at Stack Overflow, Q&A for professional and enthusiast programmers


Reply
#5
hello Aurel and Waltersmind
I edited the code for Windows and included the mpfr dll, hope you can figure this out as I have run out of ideas.
Code:
TYPE mpfr_struct
    mpfr_prec AS LONG
    mpfr_sign AS LONG
    mpfr_exp AS LONG
    mpfr_d AS _OFFSET
END TYPE

DECLARE DYNAMIC LIBRARY "libmpfr-4"
    SUB mpfr_init2 ALIAS "mpfr_init2" (op1 AS mpfr_struct, BYVAL prec AS LONG)
    SUB mpfr_clear ALIAS "mpfr_clear" (op1 AS mpfr_struct)
    FUNCTION mpfr_sprintf& ALIAS "mpfr_sprintf" (result AS STRING, frmt AS STRING, op1 AS mpfr_struct)
    FUNCTION mpfr_set_ui& ALIAS "mpfr_set_ui" (op1 AS mpfr_struct, BYVAL ui AS _UNSIGNED LONG, BYVAL rd AS LONG)
    FUNCTION mpfr_const_pi& ALIAS "mpfr_const_pi" (op1 AS mpfr_struct, BYVAL rd AS LONG)
END DECLARE

DIM pi AS mpfr_struct
DIM c AS LONG
DIM s AS STRING, frmt AS STRING

CALL mpfr_init2(pi, 512)
c = mpfr_const_pi&(pi, 0)
s = SPACE$(128)
frmt = "%32.28R*g"
c = mpfr_sprintf&(s, frmt, pi)
PRINT s
CALL mpfr_clear(pi)


Attached Files .zip   mpfr.zip (Size: 603.25 KB / Downloads: 7)
Reply
#6
@Jack,

I will look into this issue when I get home from work this evening.
Dedicated to empowering computer programming hobbyists, tinkerers, amateurs, and enthusiasts.
profile for Walter Whitman at Stack Overflow, Q&A for professional and enthusiast programmers


Reply
#7
Walter
from Microsoft docs:
Holds unsigned 16-bit (2-byte) code points ranging in value from 0 through 65535. Each code point, or character code, represents a single Unicode character.
Remarks

Use the Char data type when you need to hold only a single character and do not need the overhead of String. In some cases you can use Char(), an array of Char elements, to hold multiple characters.

The default value of Char is the character with a code point of 0.

so this sounds little bit different than you explain:

jack
In your code i dont see any CHAR or ZSTRING defined variable so i really dont get it
what is all for ?
i look into page with this library and it looks to me that this lib work with big decimal numbers and that
is all about ..what is the real point of using such a dll is strange to me .?
Reply
#8
I am glad Walter explained what a z string is, now if only I knew what they are needed for? Wink
B += x
Reply
#9
@Aurel,

Quote:from Microsoft docs:
Holds unsigned 16-bit (2-byte)

Some ZString libraries define a zstring as a wchar_t (WCHAR [16-Bit]), like Microsoft's, and others are char_t (CHAR [8-Bit]). The interesting thing to note is that Microsoft does offer an 8-Bit version called, "cstring", which is defined as char_t (CHAR [8-Bit]).

Interesting note, the latest version of GCC that I am using on QB64-CBE has a szString which in one place it is defined as CHAR and another place, defined as WCHAR.

Quote:Holds unsigned 16-bit (2-byte) code points ranging in value from 0 through 65535.

I have been writing in assembly language for over 30 years and we always called that a "WORD". However, nowdays, some system define a WORD as a 32-Bit value. Strange indeed.

A 16-Bit code point is called UTF-16.

Quote:Each code point, or character code, represents a single Unicode character.

ASCII characters could never support written language characters outside of the English alphabet and numbers. So they created UTF-16. But UTF-16 is a bit outdated itself. They now have UTF-32 which is a 32-Bit unicode character system. Actually, it doesn't use all 32-Bits. I think it is 31-Bits actually, but I can't fully remember.

However, if anyone is interested, here are some links to the Unicode Consortium with a all the information about the Unicode character sets.

Main Site:  https://unicode.org/

Good information about Unicode:  http://www.unicode.org/standard/WhatIsUnicode.html

Download all the character code points in a single *.PDF here:  https://www.unicode.org/Public/UCD/latest/charts/


Quote:In some cases you can use Char(), an array of Char elements, to hold multiple characters.

Actually, it is: char MyVar[] = "String Test";

Here is a working C++ demo to show you what I mean:

Code:
#include <iostream>
#include <conio.h>
#include <windows.h>

using namespace std;

int main(){

    unsigned int i;

    int8_t Msg1[] = "This is a test of The Joyful Programmer.\r\n\r\nThis is only a test.\r\n\r\nThe End\r\n\r\n<PRESS ANY KEY TO CONTINUE>\r\n\r\n";
    char Msg2[] =
        "O Captain! my Captain! our fearful trip is done,\r\n"
        "The ship has weather'd every rack, the prize we sought is won,\r\n"
        "The port is near, the bells I hear, the people all exulting,\r\n"
        "While follow eyes the steady keel, the vessel grim and daring;\r\n"
        "                         But O heart! heart! heart!\r\n"
        "                            O the bleeding drops of red,\r\n"
        "                               Where on the deck my Captain lies,\r\n"
        "                                  Fallen cold and dead.\r\n\r\n"
        "O Captain! my Captain! rise up and hear the bells;\r\n"
        "Rise up-for you the flag is flung-or you the bugle trills,\r\n"
        "For you bouquets and ribbon'd wreaths-for you the shores a-crowding,\r\n"
        "For you they call, the swaying mass, their eager faces turning;\r\n"
        "                         Here Captain! dear father!\r\n"
        "                            This arm beneath your head!\r\n"
        "                               It is some dream that on the deck,\r\n"
        "                                 You've fallen cold and dead.\r\n\r\n"
        "My Captain does not answer, his lips are pale and still,\r\n"
        "My father does not feel my arm, he has no pulse nor will,\r\n"
        "The ship is anchor'd safe and sound, its voyage closed and done,\r\n"
        "From fearful trip the victor ship comes in with object won;\r\n"
        "                         Exult O shores, and ring O bells!\r\n"
        "                            But I with mournful tread,\r\n"
        "                               Walk the deck my Captain lies,\r\n"
        "                                  Fallen cold and dead.\r\n"
        "\r\n\r\n"
        "\r\n\r\n<PRESS ANY KEY TO CONTINUE>";

    char MyFirstName[] = "Walter";
    char MiddleInitial = 'W';
    char LastName[] = "Whitman";

    for (i=0;i < sizeof(Msg1)/sizeof(Msg1[0]);i++)
    {
        cout << Msg1[i];
        Sleep(50);
    }

    getch();

    for (i=0;i < sizeof(Msg2)/sizeof(Msg2[0]);i++)
    {
        cout << Msg2[i];
        Sleep(50);
    }

    getch();

    cout << "\r\n\r\n\r\nTHEN END\r\n\r\n" << MyFirstName << " " << MiddleInitial << " " << LastName;

    return 0;
}
Dedicated to empowering computer programming hobbyists, tinkerers, amateurs, and enthusiasts.
profile for Walter Whitman at Stack Overflow, Q&A for professional and enthusiast programmers


Reply
#10
Walter
I understand your points but I know what i use in Oxygen Basic for example
or before in EB,I never do any programming in C++, some small things in C -yes
o2 use all types in windows 32 bit systems including QUAD and DWORD

As i say before concrete program by Jack - i dont see any CHAR type or ZSTRING defined
variable so i really dont have a clue why he ask about conversion
from CHAR to ZSTRING which is not supported as he says in qb64
Reply
#11
Aurel Wrote:As i say before concrete program by Jack - i dont see any CHAR type or ZSTRING defined 
variable so i really dont have a clue why he ask about conversion
from CHAR to ZSTRING which is not supported as he says in qb64
you confuse me, I don't understand you.
my question is/was quite clear, I need some way to simulate a zstring, actually a pointer to some memory block would probably work also.
Reply
#12
hello Waltersmind
can you tell me why the following code don't work?
Code:
TYPE mpfr_struct
    mpfr_prec AS LONG
    mpfr_sign AS LONG
    mpfr_exp AS LONG
    mpfr_d AS _OFFSET
END TYPE

DECLARE DYNAMIC LIBRARY "libmpfr-4"
    SUB mpfr_init2 ALIAS "mpfr_init2" (op1 AS mpfr_struct, BYVAL prec AS LONG)
    SUB mpfr_clear ALIAS "mpfr_clear" (op1 AS mpfr_struct)
    FUNCTION mpfr_sprintf& ALIAS "mpfr_sprintf" (BYVAL rop AS _OFFSET, BYVAL frmt AS _OFFSET, op AS mpfr_struct)
    FUNCTION mpfr_set_ui& ALIAS "mpfr_set_ui" (op1 AS mpfr_struct, BYVAL ui AS _UNSIGNED LONG, BYVAL rd AS LONG)
    FUNCTION mpfr_const_pi& ALIAS "mpfr_const_pi" (op1 AS mpfr_struct, BYVAL rd AS LONG)
END DECLARE

DIM pi AS mpfr_struct
DIM c AS LONG
DIM s AS STRING * 1000, frmt AS STRING * 30
DIM m AS _MEM, ft AS _MEM
frmt = "%32.28R*g"
ft = _MEM(frmt)
m = _MEM(s)
CALL mpfr_init2(pi, 512)
c = mpfr_const_pi&(pi, 0)
c = mpfr_sprintf&(m.OFFSET, ft.OFFSET, pi)
_MEMGET m, m.OFFSET, s
PRINT s
CALL mpfr_clear(pi)
_MEMFREE m
_MEMFREE ft
Reply
#13
I am so embarrassed Angry
this is what happens when you try to code while sick with the flu, I forgot one argument in the sprintf function
this seems to work
Code:
TYPE mpfr_struct
    mpfr_prec AS LONG
    mpfr_sign AS LONG
    mpfr_exp AS LONG
    mpfr_d AS _OFFSET
END TYPE

DECLARE DYNAMIC LIBRARY "libmpfr-4"
    SUB mpfr_init2 ALIAS "mpfr_init2" (op1 AS mpfr_struct, BYVAL prec AS LONG)
    SUB mpfr_clear ALIAS "mpfr_clear" (op1 AS mpfr_struct)
    FUNCTION mpfr_sprintf& ALIAS "mpfr_sprintf" (result AS STRING, frmt AS STRING, BYVAL rd AS LONG, op1 AS mpfr_struct)
    FUNCTION mpfr_set_ui& ALIAS "mpfr_set_ui" (op1 AS mpfr_struct, BYVAL ui AS _UNSIGNED LONG, BYVAL rd AS LONG)
    FUNCTION mpfr_const_pi& ALIAS "mpfr_const_pi" (op1 AS mpfr_struct, BYVAL rd AS LONG)
END DECLARE

DIM pi AS mpfr_struct
DIM c AS LONG
DIM s AS STRING, frmt AS STRING

CALL mpfr_init2(pi, 512)
c = mpfr_const_pi&(pi, 0)
s = SPACE$(128)
frmt = "%32.28R*g"
c = mpfr_sprintf&(s, frmt, 0, pi)
PRINT s
CALL mpfr_clear(pi)
and so does this code using _MEM
Code:
TYPE mpfr_struct
    mpfr_prec AS LONG
    mpfr_sign AS LONG
    mpfr_exp AS LONG
    mpfr_d AS _OFFSET
END TYPE

DECLARE DYNAMIC LIBRARY "libmpfr-4"
    SUB mpfr_init2 ALIAS "mpfr_init2" (op1 AS mpfr_struct, BYVAL prec AS LONG)
    SUB mpfr_clear ALIAS "mpfr_clear" (op1 AS mpfr_struct)
    FUNCTION mpfr_sprintf& ALIAS "mpfr_sprintf" (BYVAL rop AS _OFFSET, BYVAL frmt AS _OFFSET, BYVAL rd AS LONG, op AS mpfr_struct)
    FUNCTION mpfr_set_ui& ALIAS "mpfr_set_ui" (op1 AS mpfr_struct, BYVAL ui AS _UNSIGNED LONG, BYVAL rd AS LONG)
    FUNCTION mpfr_const_pi& ALIAS "mpfr_const_pi" (op1 AS mpfr_struct, BYVAL rd AS LONG)
END DECLARE

DIM pi AS mpfr_struct
DIM c AS LONG
DIM s AS STRING * 1000, frmt AS STRING * 30
DIM m AS _MEM, ft AS _MEM
frmt = "%32.28R*g"
ft = _MEM(frmt)
m = _MEM(s)

CALL mpfr_init2(pi, 512)
c = mpfr_const_pi&(pi, 0)
c = mpfr_sprintf&(m.OFFSET, ft.OFFSET, 0, pi)
_MEMGET m, m.OFFSET, s
PRINT s
CALL mpfr_clear(pi)
_MEMFREE m
_MEMFREE ft
Reply
#14
@Jack,

Don't feel too bad about that. We all have our days.

However, I have been studying this and got most of it working except for "mpfr_sprintf". I even downloaded the source code to the project, but it only shows two parameters and the ellipse specifier that allows a function to contain a variable amount of parameters:

Code:
mpfr_fprintf (FILE *fp, const char *fmt, ...)

The code doesn't suggest usage of any extra parameter's, so I have no idea what you could pass it.

Code:
int mpfr_sprintf (char *buf, const char *fmt, ...)
{
  char *str;
  int ret;

  GET_STR (ret, str, fmt);
  ret = sprintf (buf, "%s", str);

  mpfr_free_str (str);
  return ret;
}

While I could get all the other commands working just fine, this one didn't. I scoured the documentation (which can be seen at http://www.mpfr.org/mpfr-current/mpfr.ht...05fsprintf) to find out what the extra parameters could be used for, but no luck.

But once I added the missing piece you shared, it worked great. Very interesting library and thank you for sharing it.

I have been under the weather this week as well as this weekend, so I understand how you feel.

Here is my test code:

Code:
TYPE mpfr_struct
    mpfr_prec AS _OFFSET
    mpfr_sign AS LONG
    mpfr_exp AS _OFFSET
    mpfr_d AS _OFFSET
END TYPE

DECLARE DYNAMIC LIBRARY "libmpfr-4"
    SUB mpfr_init2 (op1 AS mpfr_struct, BYVAL prec AS _OFFSET)
    SUB mpfr_clear (op1 AS mpfr_struct)
    FUNCTION mpfr_sprintf& (result AS STRING, frmt AS STRING, BYVAL rd AS LONG, op1 AS mpfr_struct)
    FUNCTION mpfr_set_ui& (op1 AS mpfr_struct, BYVAL ui AS _UNSIGNED _OFFSET, BYVAL rd AS LONG)
    FUNCTION mpfr_const_pi& (op1 AS mpfr_struct, BYVAL rd AS LONG)
END DECLARE

DIM pi AS mpfr_struct
DIM c AS LONG
DIM s AS STRING, frmt AS STRING

PRINT "pi.mpfr_prec: "; pi.mpfr_prec
PRINT "pi.mpfr_sign: "; pi.mpfr_sign
PRINT "pi.mpfr_exp: "; pi.mpfr_exp
PRINT "pi.mpfr_d: "; pi.mpfr_d
PRINT
PRINT "CALL mpfr_init2(pi, 512)"
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

mpfr_init2 pi, 512

PRINT "pi.mpfr_prec: "; pi.mpfr_prec
PRINT "pi.mpfr_sign: "; pi.mpfr_sign
PRINT "pi.mpfr_exp: "; pi.mpfr_exp
PRINT "pi.mpfr_d: "; pi.mpfr_d
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

PRINT "c: "; c
PRINT "c = mpfr_const_pi&(pi, 0)"
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

c = mpfr_const_pi&(pi, 0)

PRINT "c: "; c
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

PRINT "s = SPACE$(127)"
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

s = SPACE$(127)

PRINT "frmt = '%32.28R*g'"
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

frmt = "%32.28R*g"

PRINT "c = mpfr_sprintf&(s, frmt, 1, pi)"
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

c = mpfr_sprintf&(s, frmt, 2, pi)

PRINT "PRINT s"
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

PRINT "s: '"; s; "'"
PRINT
PRINT "CALL mpfr_clear(pi)"
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

mpfr_clear pi

PRINT
PRINT "DONE..."
PRINT
PRINT "<PRESS ANY KEY>"
PRINT
SLEEP

For all others, please be sure to place the *.DLL in the same folder/directory as the QB64.exe

Also, you do not need the ALIAS designation if the actual library procedure name is the same as the one you defined using the ALIAS designation.
Dedicated to empowering computer programming hobbyists, tinkerers, amateurs, and enthusiasts.
profile for Walter Whitman at Stack Overflow, Q&A for professional and enthusiast programmers


Reply
#15
thank you Waltersmind
you are right about the lack of information on mpfr_sprintf, just for fun I did a google search and came across a GitHub repository that was supposed to have examples on it's usage but their example omitted the rounding parameter, so it makes me wonder if author tested the code.
one thing that could cause problems is the different type size on different platforms, I wrote a very simple C program to print the type-size
Code:
//
//  test-size.c
//  
//
#include <stdio.h>
#include "gmp.h"
#include "mpfr.h"

int main()
{
    printf("SizeOf int %lu\n",sizeof(int));
    printf("SizeOf unsigned int %lu\n",sizeof(unsigned int));
    printf("SizeOf long int %lu\n",sizeof(long int));
    printf("SizeOf unsigned long int %lu\n",sizeof(unsigned long int));
    printf("SizeOf long %lu\n",sizeof(long));
    printf("SizeOf unsigned long int %lu\n",sizeof(unsigned long int));
    printf("SizeOf long long int %lu\n",sizeof(long long int));
    printf("SizeOf unsigned long long int %lu\n",sizeof(unsigned long long int));
    printf("=====================\n");
    printf("SizeOf mp_bitcnt_t %lu\n",sizeof(mp_bitcnt_t));
    printf("SizeOf size_t %lu\n",sizeof(size_t));
    printf("SizeOf mp_limb_t %lu\n",sizeof(mp_limb_t));
    printf("SizeOf mp_size_t %lu\n",sizeof(mp_size_t));
    printf("SizeOf mpfr_t %lu\n",sizeof(mpfr_t));
    printf("SizeOf mpfr_rnd_t %lu\n",sizeof(mpfr_rnd_t));
    printf("SizeOf mpfr_exp_t %lu\n",sizeof(mpfr_exp_t));
    printf("SizeOf mpfr_prec_t %lu\n",sizeof(mpfr_prec_t));
    printf("SizeOf mpfr_void %lu\n",sizeof(mpfr_void));
    printf("SizeOf mpfr_int %lu\n",sizeof(mpfr_int));
    printf("SizeOf mpfr_long %lu\n",sizeof(mpfr_long));
    printf("SizeOf mpfr_sign_t %lu\n",sizeof(mpfr_sign_t));
    //printf("SizeOf intmax_t %lu\n",sizeof(intmax_t));
    printf("SizeOf long double %lu\n",sizeof(long double));

    return 0;
}
Reply
#16
The one thing I want to let everyone know while I am thinking about it, whenever you see me share a lot of information in my posts, I do that to share extra knowledge to the community, not to make myself look "big" or others to look "dumb". I do a bit of research on things before I post (usually), so I try to share some extra information, but too much. I have been accused of writing or sharing too much information, but I disagree. You never know what tidbits of information will change a person's life forever, as it has done me numerous times over the years.
Dedicated to empowering computer programming hobbyists, tinkerers, amateurs, and enthusiasts.
profile for Walter Whitman at Stack Overflow, Q&A for professional and enthusiast programmers


Reply