$CPP Directive

Purpose: $CPP directive attempts C++ compliance in the translated code and also names the output file FileName.cpp. This directive is equivalent to using the BCX command line -c flag.

$CPPHDR Directive

When the $CPPHDR directive is used, the BCX translator automatically adds the following code to the .cpp file translation produced by BCX.


 // Additional lines may be needed
 #if defined(__cplusplus)
   #include <iostream>
   #include <fstream>
   #include <sstream>
   #include <iomanip>
   typedef std::string stdstr;
 #endif

To add other Standard C++ Library header files to the BCX code to be translated use the directive


 #include <Filename>

$NOIO directive

Purpose:The $NOIO directive disables the inclusion of the <iostream> C++ header file.

By default, when the $CPPHDR directive is used, the BCX translation includes the <iostream> C++ header file. You can disable the inclusion by adding the line $NOIO to your BCX program source code, placing it immediately after the $CPPHDR directive.

The C++ Tutorial for BCX Users

With the permission of the original author Eric Brasseur, the following is an abridged BCX version of Brasseur's "The C++ tutorial for C users".

Chapter 3. Console input and output streams

Input from the keyboard and output to the screen can be performed through std::cin >> and std::cout <<.

Example C03.bas:


 $NOMAIN
 
 #include <iostream>
 
 FUNCTION MAIN()
 
   DIM age%
   DIM name$
          
   std::cout << "This is a sample program." << std::endl
          
   std::cout << std::endl    ' Just a line feed (end of line)
    
   std::cout << "Type your age : "
   std::cin >> age%
          
   std::cout << "Type your name: "
   std::cin >> name$
          
   std::cout << std::endl
          
   std::cout << "Hello " << name$ << " you're " << age% << " years old." << std::endl
   std::cout << std::endl << std::endl << "Bye!" << std::endl
 
 END FUNCTION

Result:


 This is a sample program.

 Type your age : 19
 Type your name: BCX

 Hello BCX you're 19 years old.

 Bye!

Chapter 7. Global variables can be accessed even if a local variables have the same name.

A global variable can be accessed even if another variable with the same name has been declared inside the function.

Example C07.bas:


 $NOMAIN

 #include <iostream>
   
 DIM a# = 128
     
 FUNCTION MAIN ()
    
   DIM a# = 256
        
   std::cout << "Local a:  " << a#   << std::endl
   std::cout << "Global a: " << ::a# << std::endl
     
 END FUNCTION


 Local a:  256
 Global a: 128

Chapter 8. It is possible to declare a REFERENCE to another variable.

It is possible to make one variable be another.

Example C08_01.bas:


 $NOMAIN
 
 #include <iostream>
 
 FUNCTION MAIN ()
  
   DIM a# = 3.1415927
       
   DIM AS DOUBLE &b = a      ' b is a#
    
   b = 89
       
   std::cout << "a# contains: " << a# << std::endl
 
 END FUNCTION

Result:


 a# contains: 89

If you are used to pointers and absolutely want to know what happens, simply think


 DOUBLE &b = a 

is translated to


 DOUBLE *b = &a 

and all subsequent b are replaced by *b.

The value of REFERENCE b cannot be changed after its declaration. For example you cannot write, a few lines further,

&b = c

expecting that b is now c. It won't work. Everything is said on the declaration line of b. Reference b and variable a are married on that line and nothing will separate them.

References can be used to allow a function to modify a calling variable

Example C08_02.bas:


 $NOMAIN
 
 #include <iostream>
     
 SUB Change (r AS DOUBLE &, s AS DOUBLE)
   r = 100
   s = 200
 END SUB
 
 FUNCTION MAIN ()
 
   RAW AS DOUBLE k, m
      
   k = 3
   m = 4
      
   CALL Change(k, m)
      
   std::cout << k << ", " << m << std::endl
 
 END FUNCTION

Result:


 100, 4

A reference can be used to let a function return a variable.

Example C08_03.bas:


 $NOMAIN
 
 #include <iostream>
     
 FUNCTION biggest (r AS DOUBLE &, s AS DOUBLE &) AS DOUBLE &
   IF r > s THEN FUNCTION = r
   FUNCTION = s
 END FUNCTION
 
 FUNCTION MAIN ()
  
   RAW AS DOUBLE k = 3
   RAW AS DOUBLE m = 7
      
   std::cout << "k: " << k << std::endl
   std::cout << "m: " << m << std::endl
   std::cout << std::endl
      
   biggest (k, m) = 10
      
   std::cout << "k: " << k << std::endl
   std::cout << "m: " << m << std::endl
   std::cout << std::endl
      
   biggest (k, m) ++
      
   std::cout << "k: " << k << std::endl
   std::cout << "m: " << m << std::endl
   std::cout << std::endl
 
 END FUNCTION

Result:


 k: 3
 m: 7

 k: 3
 m: 10

 k: 3
 m: 11

Chapter 9. Namespaces can be declared.

Namespaces can be declared. The variables declared within a namespace can be used thanks to the :: operator

Example C09.bas:


 $NOMAIN
  
 #include <iostream>
     
 NAMESPACE first
   RAW AS INT a
   RAW AS INT b
 END NAMESPACE
     
 NAMESPACE second
   RAW AS DOUBLE a
   RAW AS DOUBLE b
 END NAMESPACE
  
 FUNCTION MAIN()
         
   first::a = 2
   first::b = 5
         
   second::a = 6.453
   second::b = 4.1e4
         
   std::cout << first::a + second::a << std::endl
   std::cout << first::b + second::b << std::endl
  
 END FUNCTION

Result:


 8.453
 41005

Chapter 10. A function can be declared inline

If a function contains just simple lines of code, doesn't use for loops or the like, it can be declared inline. This means its code will be inserted everywhere the function is used. That's somewhat like a macro. The main advantage is the program will be faster. A small drawback is it will be bigger, because the full code of the function was inserted everywhere it is used.

Example C10.bas:


 $NOMAIN
 
 #include <iostream>
     
 inline FUNCTION hypothenuse (a AS DOUBLE, b AS DOUBLE) AS DOUBLE
   
 FUNCTION = sqrt (a * a + b * b)
 END FUNCTION
 
 FUNCTION MAIN ()
     
   RAW AS DOUBLE k = 6, m = 9
      
   ' Next two lines produce exactly the same result:
    
   std::cout << hypothenuse (k, m) << std::endl
   std::cout << sqrt (k * k + m * m) << std::endl
 
 END FUNCTION

Result:


 10.8167
 10.8167

Chapter 11. The exception structure has been added.

You know the classical control structures of C: *for*, *if*, *do*, *while*, *switch*... C++ adds one more control structure named EXCEPTION.

Example C11.bas:


 $NOMAIN
 
 #include <iostream>
 
 FUNCTION MAIN ()
    
   DIM AS INT a, b, c
    
   std::cout << "Type a number: "
   std::cin >> a
   std::cout << std::endl
        
 TRY
   IF a > 100 THEN THROW 100
   IF a < 10 THEN  THROW 10
   c = a/3
   THROW  c
 CATCH (result AS INT)
   std::cout << "Result is: " << result << std::endl
   b = result + 1
 END TRY
        
 std::cout << "b contains: " << b << std::endl
        
 std::cout << std::endl
        
 ' another example of EXCEPTION use:
       
 RAW zero []     = "zero" AS CHAR
 RAW even []     = "even" AS CHAR
 RAW notprime [] = "not prime" AS CHAR
 RAW prime []    = "prime" AS CHAR
        
 TRY
   IF a = 0 THEN THROW zero
   IF (a / 2) * 2 = a THEN THROW even
   XFOR INT i = 3 WHILE i <= sqrt((float)a) BY i++
    std::cout << "Testing " << i << std::endl
    IF (a / i) * i = a THEN THROW notprime
   XNEXT
   THROW prime
 CATCH (conclusion AS CONST CHAR PTR)
   std::cout << "The number you typed is "<< conclusion << std::endl
 END TRY
        
 std::cout << std::endl
 
 END FUNCTION

Result:


 Type a number: 5

 Result is: 10
 b contains: 11

 The number you typed is prime

Chapter 12. A function can have default parameters.

It is possible to define default parameters for functions.

Example C12.bas:


 $NOMAIN

 #include <iostream>
   
 FUNCTION test (a AS DOUBLE, b = 7 AS DOUBLE) AS DOUBLE
   FUNCTION = a - b
 END FUNCTION
 
 FUNCTION MAIN ()
 
 std::cout << test (14, 5) << std::endl
 std::cout << test (14) << std::endl 

 END FUNCTION

Result:


 9
 7

Chapter 13. FUNCTION OVERLOAD: several functions can be declared with the same name provided there is a difference in their parameter list.

One important advantage of C++ is the FUNCTION OVERLOAD. Different functions can have the same name provided something allows the compiler to distinguish between them: number of parameters, type of parameters...

Example C13.bas:


 $NOMAIN

 #include <iostream>
   
 FUNCTION test (a AS DOUBLE, b AS DOUBLE) AS DOUBLE
   FUNCTION = a + b
 END FUNCTION
   
 FUNCTION test (a AS INT, b AS INT) AS INT
   FUNCTION = a - b
 END FUNCTION

 FUNCTION MAIN ()
  
 RAW AS DOUBLE   m = 7,  n = 4
 RAW AS INT      k = 5,  p = 3
   
 std::cout << test(m, n) << " , " << test(k, p) << std::endl

 END FUNCTION

Result:


 11 , 2

Chapter 14. The symbolic operators (+ - * / ...) can be defined for new data types

OPERATOR OVERLOADING can be used to redefine the basic symbolic operators for new kinds of parameters.

Example C14.bas:


 $NOMAIN

 #include <iostream>
   
 TYPE bcx_vector
   DIM AS DOUBLE x
   DIM AS DOUBLE y
 END TYPE
    
 FUNCTION operator*(a AS DOUBLE, b AS bcx_vector) AS bcx_vector
   DIM AS bcx_vector r
   
   r.x = a * b.x
   r.y = a * b.y
   
   FUNCTION = r
 END FUNCTION

 FUNCTION MAIN ()
  
 DIM AS bcx_vector k, m  ' No need to type "struct bcx_vector"
  
 k.x =  2                ' To be able to write
 k.y = -1                ' k = bcx_vector (2, -1)
  
 m = 3.1415927 * k       ' Magic!
  
 std::cout << "(" << m.x << ", " << m.y << ")" << std::endl

 END FUNCTION

Result:


 (6.28319, -3.14159)

Chapter 15. Different functions for different data types will automatically be generated provided you define a template function.

Tired of defining the same function five times? One definition for *int* type parameters, one definition for *double* type parameters, one definition for *float* type parameters... Didn't you forget one type? What if a new data type is used? No problem: the C++ compiler can automatically generate every version of the function that is necessary! Just tell it how the function looks like by declaring a *template* function

Example C15.bas:


 $NOMAIN

 #include <iostream>
   
 template <class ttype>

 FUNCTION minimum (a AS ttype, b AS ttype) AS ttype
   RAW AS ttype r
   
   r = a
   IF b < a THEN r = b
   
   FUNCTION = r
 END FUNCTION

 FUNCTION MAIN ()
       
 RAW AS INT i1, i2, i3
 i1 = 34
 i2 = 6
 i3 = minimum (i1, i2)
 std::cout << "Most little: " << i3 << std::endl
   
 RAW AS DOUBLE d1, d2, d3
 d1 = 7.9
 d2 = 32.1
 d3 = minimum (d1, d2)
 std::cout << "Most little: " << d3 << std::endl
 std::cout << "Most little: " << minimum (d3, 3.5) << std::endl

 END FUNCTION

Result:


 Most little: 6
 Most little: 7.9
 Most little: 3.5

Chapter 16. The keywords new and delete are much better to allocate and deallocate memory

The keywords NEW and DELETE can be used to allocate and deallocate memory. They are cleaner than the functions malloc and free from standard C.

Example C16.bas:


 $NOMAIN

 #include <iostream>

 FUNCTION MAIN ()
       
 RAW AS DOUBLE PTR d  ' d is a variable whose purpose
                      ' is to contain the address of a
                      ' zone where a double is located
      
 d = NEW DOUBLE       ' new allocates a zone of memory
                      ' large enough to contain a double
                      ' and returns its address.
                      ' That address is stored in d.
      
 *d = 45.3            ' The number 45.3 is stored
                      ' inside the memory zone
                      ' whose address is given by d.
      
 std::cout << "Type a number: "
 std::cin >> *d
       
 *d = *d + 5
       
 std::cout << "Result: " << *d << std::endl
       
 DELETE d             ' delete deallocates the
                      ' zone of memory whose address
                      ' is given by pointer d.
                      ' Now we can no more use that zone.
           
 d = NEW DOUBLE[15]   ' allocates a zone for an array
                      ' of 15 doubles. Note each 15
                      ' double will be constructed.
                      ' This is pointless here but it
                      ' is vital when using a data type
                      ' that needs its constructor be
                      ' used for each instance.
      
 d[0] = 4456
 d[1] = d[0] + 567
       
 std::cout << "Content of d[1]: " << d[1] << std::endl
       
 DELETE [] d          ' delete [] will deallocate the
                      ' memory zone. Note each 15
                      ' double will be destructed.
                      ' This is pointless here but it
                      ' is vital when using a data type
                      ' that needs its destructor be
                      ' used for each instance (the ~
                      ' method). Using delete without
                      ' the [] would deallocate the
                      ' memory zone without destructing
                      ' each of the 15 instances. That
                      ' would cause memory leakage.
      
 RAW AS INT n = 30
       
 d = NEW DOUBLE[n]    ' new can be used to allocate an
                      ' array of random size.
 XFOR INT i = 0 WHILE i < n BY i++
   d[i] = i
 XNEXT
       
 DELETE [] d
       
 DIM AS CHAR PTR s
       
 s = NEW CHAR[100]
       
 s$ = "Hello!"
       
 std::cout << s << std::endl
       
 DELETE [] s

 END FUNCTION

Result:


 Type a number: 6
 Result: 11
 Content of d[1]: 5023
 Hello!

Chapter 17. You can add METHODS to a class or struct.

In standard C a struct contains only data. In C++ a struct definition can also include functions. Those functions are owned by the struct and are meant to operate on the data of the struct. Those functions are called METHODS. The example below defines the method surface() on the struct vector.

Example C17.bas:


 $NOMAIN

 #include <iostream>
   
 PPTYPE bcx_vector
   RAW AS DOUBLE x
   RAW AS DOUBLE y
   
   FUNCTION surface () AS DOUBLE
     RAW AS DOUBLE s
     s = x * y
     IF s < 0 THEN s = -s
     FUNCTION = s
   END FUNCTION
 END PPTYPE

 FUNCTION MAIN ()
  
 RAW AS bcx_vector a
       
 a.x = 3
 a.y = 4
       
 std::cout << "The surface of a: " << a.surface() << std::endl

 END FUNCTION

Result:


 The surface of a: 12

Chapter 18. The CONSTRUCTOR and the DESTRUCTOR can be used to initialize and destroy an instance of a class.

Very special and essential methods are the CONSTRUCTOR and DESTRUCTOR. They are automatically called whenever an instance of a class is created or destroyed (variable declaration, end of program, *new*, *delete*...).

The constructor will initialize the variables of the instance, do some calculations, allocate some memory for the instance, output some text... whatever is needed.

Here is an example of a class definition with two overloaded constructors

Example C18.bas:


 $NOMAIN

 #include <iostream>
  
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   CONSTRUCTOR bcx_vector ()   ' same name as class
    x = 0
     y = 0
   END CONSTRUCTOR
    
   CONSTRUCTOR bcx_vector (a AS DOUBLE, b AS DOUBLE)
     x = a
     y = b
   END CONSTRUCTOR
 END CLASS

 FUNCTION MAIN ()
  
 RAW AS bcx_vector k         ' bcx_vector () is called
   
 std::cout << "bcx_vector k: " << k.x << ", " << k.y << std::endl << std::endl
    
 RAW AS bcx_vector m (45, 2) ' bcx_vector (double, double) is called
   
 std::cout << "bcx_vector m: " << m.x << ", " << m.y << std::endl << std::endl
    
 k = bcx_vector (23, 2)      ' bcx_vector created, copied to k, then erased
   
 std::cout << "bcx_vector k: " << k.x << ", " << k.y << std::endl << std::endl

 END FUNCTION

Result:


 vector k: 0, 0

 vector m: 45, 2

 vector k: 23, 2

Chapter 19. Complex classes need the COPY CONSTRUCTOR and an overload of the = operator.

If you cast an object like a vector, everything will happen correctly. For example, if vector *k* contains *(4, 7)*, after the cast *m = k* the vector *m* will contain *(4, 7)* too. The values of k.x and k.y have simply been copied to m.x and m.y.

Now suppose you're playing with objects like the person class above. Those objects contain a pointer to a character string. If you cast the person object by writing *p = r* it is necesary that some function does the work to make *p* be a correct copy of *r*. Otherwise, p.name will point to the same physical character string as r.name. What's more, the former character string pointed to by p.name is lost and becomes a memory zombie. The result will be catastrophic: a mess of pointers and lost data. The methods that will do the job are the COPY CONSTRUCTOR and an overload of the = operator

Example C19.bas:


 $NOMAIN

 #include <iostream>
   
 CLASS person
   PUBLIC:
   RAW AS CHAR PTR name
   RAW AS INT age
    
   CONSTRUCTOR person (n = "no name" AS CONST CHAR PTR, a = 0 AS INT)
     name = NEW CHAR[100]
     name$ = n$
     age = a
   END CONSTRUCTOR
    
   CONSTRUCTOR person (s AS CONST person &) ' The COPY CONSTRUCTOR
   name = NEW CHAR[100]
     name$ = s.name$
     age = s.age
   END CONSTRUCTOR
    
   FUNCTION operator= (s AS CONST person &) AS person&  ' overload of =
     name$ = s.name$
     age = s.age
     FUNCTION = *this
   END FUNCTION
    
   DESTRUCTOR ~person ()
     delete [] name
   END DESTRUCTOR
 END CLASS
    
 SUB modify_person (h AS person&)
   h.age += 7
 END SUB
    
 FUNCTION compute_person (h AS person) AS person
   h.age += 7
   FUNCTION = h
 END FUNCTION

 FUNCTION MAIN ()
  
 RAW AS person p
      
 std::cout << p.name << ", age " << p.age << std::endl << std::endl
   
 ' output: no name, age 0
 
 RAW AS person k ("John", 56)
 std::cout << k.name << ", age " << k.age << std::endl << std::endl
 ' output: John, age 56

 p = k
 std::cout << p.name << ", age " << p.age << std::endl << std::endl
 ' output: John, age 56

 p = person ("Bob", 10)
 std::cout << p.name << ", age " << p.age << std::endl << std::endl
 ' output: Bob, age 10

 ' Neither the copy constructor nor the overload
 ' of = are needed for this operation that modifies
 ' p since just the reference towards p is passed to
 ' the function modify_person:
 modify_person (p)
 std::cout << p.name << ", age " << p.age << std::endl << std::endl
 ' output: Bob, age 17
 
 ' The copy constructor is called to pass a complete
 ' copy of p to the function compute_person. The
 ' function uses that copy to make its computations
 ' then a copy of that modified copy is made to
 ' return the result. Finally, the overload of = is
 ' called to paste that second copy inside k:
 = compute_person (p)
 
 std::cout << p.name << ", age " << p.age << std::endl << std::endl
 ' output: Bob, age 17

 std::cout << k.name << ", age " << k.age << std::endl << std::endl
 ' output: Bob, age 24

 END FUNCTION

Result:


 no name, age 0

 John, age 56

 John, age 56

 Bob, age 10

 Bob, age 17

 Bob, age 17

 Bob, age 24

The copy constructor allows your program to make copies of instances when doing calculations. It is a key method. During calculations, instances are created to hold intermediate results. They are modified, cast and destroyed without you being aware. This is why those methods can be useful even for simple objects (see Chapter 14.).

In all the examples above, the methods are defined inside the class definition. That automatically makes them inline methods.

Chapter 20. The method bodies can be defined below the class definition.

If a method cannot be inline, or you do not want it to be inline, or if you want the class definition to contain the minimum amount of information (or you simply want the usual separate .h header file and .cpp source code file), then you need only put the prototype of the method inside the class and define the method below the class (or in a separate .cpp source file).

Example C20.bas:


 $NOMAIN
 
 #include <iostream>
   
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   DIM FUNCTION surface() AS DOUBLE
 END CLASS test1,test2
    
 FUNCTION bcx_vector::surface() AS DOUBLE
   RAW AS DOUBLE s = 0
    
   XFOR DOUBLE i = 0 WHILE i < x BY i++
     s = s + y
   XNEXT
    
   FUNCTION = s
 END FUNCTION
    
 FUNCTION MAIN ()
 
   RAW AS bcx_vector k
    
   k.x = 4
   k.y = 5
    
   std::cout << "Surface: " << k.surface() << std::endl
 
 END FUNCTION

Result:


 Surface: 20

Chapter 21. The keyword this is a pointer to the instance a method is acting upon.

When a method is applied to an instance, that method may use the instance's variables, modify them... But sometimes it is necessary to know the address of the instance. No problem, the keyword *this* is intended for that purpose.

Example C21.bas:


 $NOMAIN
 
 #include <iostream>
    
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
     
   CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
     x = a
     y = b
   END CONSTRUCTOR
     
   FUNCTION module() AS DOUBLE
     FUNCTION = sqrt (x * x + y * y)
   END FUNCTION
     
   SUB set_length (a = 1 AS DOUBLE)
     RAW AS DOUBLE length
     
     length = this->module()
     
     x = x / length * a
     y = y / length * a
   END SUB
 END CLASS
 
 FUNCTION MAIN ()
   
   RAW AS bcx_vector c (3, 5)
     
   std::cout << "The module of bcx_vector c: " << c.module() << std::endl
     
   c.set_length(2)    ' Transforms c in a bcx_vector of size 2
    
   std::cout << "The module of bcx_vector c: " << c.module() << std::endl
     
   c.set_length()     ' Transforms b in an unitary bcx_vector.
    
   std::cout << "The module of bcx_vector c: " << c.module() << std::endl
 
 END FUNCTION

Result:


 The module of vector c: 5.83095
 The module of vector c: 2
 The module of vector c: 1

Chapter 22. Arrays of instances can be declared.

Of course, it is possible to declare arrays of objects.

Example C22.bas:


 $NOMAIN

 #include <iostream>
   
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
     x = a
     y = b
   END CONSTRUCTOR
    
   FUNCTION module () AS DOUBLE
     FUNCTION = sqrt (x * x + y * y)
   END FUNCTION
 END CLASS

 FUNCTION MAIN ()
  
   RAW AS bcx_vector s[1000]
    
   RAW AS bcx_vector t[3] = {bcx_vector(4, 5), bcx_vector(5, 5), bcx_vector(2, 4)}
    
   s[23] = t[2]
    
   std::cout << t[0].module() << std::endl

 END FUNCTION

Result:


6.40312

Chapter 23. An example of a complete class declaration

Here is an example of a full class declaration.

Example C23.bas:


 $NOMAIN
 
 #include <iostream>
   
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   DIM CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
   DIM CONSTRUCTOR bcx_vector ()
    
   DIM FUNCTION operator + (a AS bcx_vector) AS bcx_vector
   DIM FUNCTION operator - (a AS bcx_vector) AS bcx_vector
   DIM FUNCTION operator - () AS bcx_vector
   DIM FUNCTION operator * (a AS DOUBLE) AS bcx_vector
   DIM FUNCTION module() AS DOUBLE
   DIM SUB set_length (A  AS DOUBLE = 1)
 END CLASS
    
 CONSTRUCTOR bcx_vector::bcx_vector (a AS DOUBLE, b AS DOUBLE)
   x = a
   y = b
 END CONSTRUCTOR
    
 CONSTRUCTOR bcx_vector::bcx_vector ()
   x = 0
   y = 0
 END CONSTRUCTOR
    
 FUNCTION bcx_vector::operator + (a AS bcx_vector) AS bcx_vector
   FUNCTION = bcx_vector (x + a.x, y + a.y)
 END FUNCTION
    
 FUNCTION bcx_vector::operator - (a AS bcx_vector) AS bcx_vector
   FUNCTION = bcx_vector (x - a.x, y - a.y)
 END FUNCTION
    
 FUNCTION bcx_vector::operator - () AS bcx_vector
   FUNCTION = bcx_vector (-x, -y)
 END FUNCTION
    
 FUNCTION bcx_vector::operator * (a AS DOUBLE) AS bcx_vector
   FUNCTION = bcx_vector (x * a, y * a)
 END FUNCTION
    
 FUNCTION bcx_vector::module() AS DOUBLE
   FUNCTION = sqrt (x * x + y * y)
 END FUNCTION
    
 SUB bcx_vector::set_length (a AS DOUBLE)
   RAW AS DOUBLE length = this->module()
    
   x = x / length * a
   y = y / length * a
 END SUB
    
 FUNCTION operator << (o AS std::ostream&, a AS bcx_vector) AS std::ostream&
   o << "(" << a.x << ", " << a.y << ")";
   FUNCTION = o
 END FUNCTION
    
 FUNCTION MAIN ()

   RAW AS bcx_vector a
   RAW AS bcx_vector b
   RAW AS bcx_vector c (3, 5)
    
   a = c * 3
   a = b + c
   c = b - c + a + (b - a) * 7
   c = -c
    
   std::cout << "The module of bcx_vector c: " << c.module() << std::endl
    
   std::cout << "The content of bcx_vector a: " << a << std::endl
   std::cout << "The opposite of bcx_vector a: " << -a << std::endl
    
   c.set_length(2)         ' Transforms c in a bcx_vector of size 2.
   
   a = bcx_vector (56, -3)
   b = bcx_vector (7, c.y)
    
   b.set_length()          ' Transforms b in an unitary bcx_vector.
   
   std::cout << "The content of bcx_vector b: " << b << std::endl
    
   DIM AS DOUBLE k
   k = bcx_vector(1, 1).module()   ' k will contain 1.4142.
  std::cout << "k contains: " << k << std::endl

 END FUNCTION

Result:


 The module of bcx_vector c: 40.8167
 The content of bcx_vector a: (3, 5)
 The opposite of bcx_vector a: (-3, -5)
 The content of bcx_vector b: (0.971275, 0.23796)
 k contains: 1.41421

Chapter 23a. An example of a complete class declaration with destructor.

A destructor has been added to the Chapter 23 example to show the use of the tilde "~" with destructors.

Example C23a.bas:


 $NOMAIN
 
 #include <iostream>
   
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   DIM CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
   DIM CONSTRUCTOR bcx_vector ()
   'need ~ below
  DIM DESTRUCTOR ~bcx_vector()
   DIM FUNCTION operator + (a AS bcx_vector) AS bcx_vector
   DIM FUNCTION operator - (a AS bcx_vector) AS bcx_vector
   DIM FUNCTION operator - () AS bcx_vector
   DIM FUNCTION operator * (a AS DOUBLE) AS bcx_vector
   DIM FUNCTION module() AS DOUBLE
   DIM SUB set_length (A  AS DOUBLE = 1)
 END CLASS
    
 CONSTRUCTOR bcx_vector::bcx_vector (a AS DOUBLE, b AS DOUBLE)
   x = a
   y = b
 END CONSTRUCTOR
    
 CONSTRUCTOR bcx_vector::bcx_vector ()
   x = 0
   y = 0
 END CONSTRUCTOR
 'need ~ below
DESTRUCTOR bcx_vector::~bcx_vector()
        
 END DESTRUCTOR
    
 FUNCTION bcx_vector::operator + (a AS bcx_vector) AS bcx_vector
   FUNCTION = bcx_vector (x + a.x, y + a.y)
 END FUNCTION
    
 FUNCTION bcx_vector::operator - (a AS bcx_vector) AS bcx_vector
   FUNCTION = bcx_vector (x - a.x, y - a.y)
 END FUNCTION
    
 FUNCTION bcx_vector::operator - () AS bcx_vector
   FUNCTION = bcx_vector (-x, -y)
 END FUNCTION
    
 FUNCTION bcx_vector::operator * (a AS DOUBLE) AS bcx_vector
   FUNCTION = bcx_vector (x * a, y * a)
 END FUNCTION
    
 FUNCTION bcx_vector::module() AS DOUBLE
   FUNCTION = sqrt (x * x + y * y)
 END FUNCTION
    
 SUB bcx_vector::set_length (a AS DOUBLE)
   RAW AS DOUBLE length = this->module()
    
   x = x / length * a
   y = y / length * a
 END SUB
    
 FUNCTION operator << (o AS std::ostream&, a AS bcx_vector) AS std::ostream&
   o << "(" << a.x << ", " << a.y << ")";
   FUNCTION = o
 END FUNCTION
    
 FUNCTION MAIN ()

   RAW AS bcx_vector a
   RAW AS bcx_vector b
   RAW AS bcx_vector c (3, 5)
    
   a = c * 3
   a = b + c
   c = b - c + a + (b - a) * 7
   c = -c
    
   std::cout << "The module of bcx_vector c: " << c.module() << std::endl
    
   std::cout << "The content of bcx_vector a: " << a << std::endl
   std::cout << "The oposite of bcx_vector a: " << -a << std::endl
    
   c.set_length(2)         ' Transforms c in a bcx_vector of size 2.
   
   a = bcx_vector (56, -3)
   b = bcx_vector (7, c.y)
    
   b.set_length()          ' Transforms b in an unitary bcx_vector.
   
   std::cout << "The content of bcx_vector b: " << b << std::endl
    
   DIM AS DOUBLE k
   k = bcx_vector(1, 1).module()   ' k will contain 1.4142.
  std::cout << "k contains: " << k << std::endl

 END FUNCTION

Result:


 The module of bcx_vector c: 40.8167
 The content of bcx_vector a: (3, 5)
 The opposite of bcx_vector a: (-3, -5)
 The content of bcx_vector b: (0.971275, 0.23796)
 k contains: 1.41421

Chapter 24. static variables inside a class definition

One or more variables in a class can be declared *static*. In which case, only one instance of those variables exist, shared by all instances of the class. It must be initialised outside the class declaration.

Example C24.bas:


 $NOMAIN
 
 #include <iostream>
 
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
   STATIC AS INT count
    
   CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
     x = a
     y = b
     count++
   END CONSTRUCTOR
    
   DESTRUCTOR ~bcx_vector()
     count--
   END DESTRUCTOR
 END CLASS
    
 RAW AS INT bcx_vector::count = 0
 
 FUNCTION MAIN ()

   std::cout << "Number of bcx_vectors:" << std::endl
    
   RAW AS bcx_vector a
   std::cout << bcx_vector::count << std::endl
    
   RAW AS bcx_vector b
   std::cout << bcx_vector::count  << std::endl
    
   RAW AS bcx_vector PTR r, u
    
   r = NEW bcx_vector
   std::cout << bcx_vector::count << std::endl
    
   u = NEW bcx_vector
   std::cout << a.count << std::endl
    
   delete r
   std::cout << bcx_vector::count << std::endl
    
   delete u
   std::cout << b.count << std::endl

 END FUNCTION

Result:


 Number of bcx_vectors:
 1
 2
 3
 4
 3
 2

Chapter 25. const variables inside a class definition.

A class variable can also be *const*ant. That's just like static, except it is given a value inside the class declaration and that value cannot be modified.

A const within a CLASS must be a static const of integral or enumeration type initialized by a constant expression.

Some compilers, for example g++, have an extension that allows for const static float and doubles within a CLASS. Also, the C++0x standard has introduced a new type, constexpr, which allows in-CLASS float and doubles constants.

Example C25.bas:


 $NOMAIN
  
 #include <iostream>
 
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
   CONST STATIC INT piint = 3
    
   CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
     x = a
     y = b
   END CONSTRUCTOR
    
   FUNCTION cylinder_volume () AS DOUBLE
     FUNCTION = x * x / 4 * (piint + 0.14159) * y
   END FUNCTION
 END CLASS
 
 FUNCTION MAIN ()
  
   std::cout << "The value of pi: " << bcx_vector::piint + 0.14159 << std::endl << std::endl
    
   bcx_vector k (3, 4)
    
   std::cout << "Result: " << k.cylinder_volume() << std::endl
 
 END FUNCTION

Result:


 The value of pi: 3.14159

 Result: 28.2743

Chapter 26. A class can be DERIVED from another class.

A class can be DERIVED from another class. The new class INHERITS the variables and methods of the BASE CLASS. Additional variables and/or methods can be added.

Example C26.bas:


 $NOMAIN
  
 #include <iostream>
  
 CLASS bcx_vector
   PUBLIC:
    
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
     x = a
     y = b
   END CONSTRUCTOR
    
   FUNCTION module() AS DOUBLE
     FUNCTION = sqrt (x*x + y*y)
   END FUNCTION
    
   FUNCTION surface() AS DOUBLE
     FUNCTION = x * y
   END FUNCTION
 END CLASS
    
 CLASS trivector USING PUBLIC bcx_vector    ' trivector is derived from bcx_vector
  PUBLIC:
   RAW AS DOUBLE z       ' added to x and y from bcx_vector
   
   CONSTRUCTOR trivector (m=0 AS DOUBLE, n=0 AS DOUBLE, p=0 AS DOUBLE) USING bcx_vector (m, n)
     z = p               ' bcx_vector constructor will
  END CONSTRUCTOR       ' be called before trivector
  ' constructor, with parameters
  ' m and n.
   
   CONSTRUCTOR trivector (a AS bcx_vector) ' What to do if a bcx_vector is cast to a trivector
    x = a.x
     y = a.y
     z = 0
   END CONSTRUCTOR
    
   FUNCTION module () AS DOUBLE      ' define module() for trivector
    FUNCTION = sqrt (x*x + y*y + z*z)
   END FUNCTION
    
   FUNCTION volume () AS DOUBLE
     FUNCTION = this->surface() * z    ' or x * y * z
  END FUNCTION
 END CLASS
    
 FUNCTION MAIN ()
  
   RAW AS bcx_vector a (4, 5)
   RAW AS trivector b (1, 2, 3)
    
   std::cout << "a (4, 5)    b (1, 2, 3)    *r = b" << std::endl << std::endl
    
   std::cout << "Surface of a: " << a.surface() << std::endl
   std::cout << "Volume of b: " << b.volume() << std::endl
   std::cout << "Surface of base of b: " << b.surface() << std::endl
    
   std::cout << "Module of a: " << a.module() << std::endl
   std::cout << "Module of b: " << b.module() << std::endl
   std::cout << "Module of base of b: " << b.bcx_vector::module() << std::endl
    
   RAW AS trivector k
   k = a                 ' thanks to trivector(bcx_vector) definition
  ' copy of x and y,       k.z = 0
  RAW AS bcx_vector j
   j = b                 ' copy of x and y.       b.z left out
   
   RAW AS bcx_vector PTR r
   r = &b
    
   std::cout << "Surface of r: " << r->surface() << std::endl
   std::cout << "Module of r: " << r->module() << std::endl
 
 END FUNCTION

Result:


 a (4, 5)    b (1, 2, 3)    *r = b

 Surface of a: 20
 Volume of b: 6
 Surface of base of b: 2
 Module of a: 6.40312
 Module of b: 3.74166
 Module of base of b: 2.23607
 Surface of r: 2
 Module of r: 2.23607

Chapter 27. If a method is declared virtual the program will always check the type of the instance that is pointed to and will use the appropriate method.

In the Chapter 26 example, *r->module()* calculates the vector module, using *x* and *y*, because *r* has been declared a vector pointer. The fact that *r* actually points to a trivector is not taken into account. If you want the program to check the type of the pointed object and choose the appropriate method, then you must declare that method as *virtual* inside the base class.

(If at least one of the methods of the base class is virtual then a "header" of 4 bytes is added to every instance of the classes. This allows the program to determine what a vector actually points to.) (4 bytes is probably implementation specific. On a 64 bit machine maybe it is 8 bytes...)

Example C27.bas:

 
 $NOMAIN
  
 #include <iostream>
   
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
     x = a
     y = b
   END CONSTRUCTOR
    
   FUNCTION module() AS virtual DOUBLE
     FUNCTION = sqrt (x*x + y*y)
   END FUNCTION
 END CLASS
    
 CLASS trivector USING PUBLIC bcx_vector
   PUBLIC:
   RAW AS DOUBLE z
    
   CONSTRUCTOR trivector (m = 0 AS DOUBLE, n = 0 AS DOUBLE, p = 0 AS DOUBLE)
    x = m                   ' Just for the game,
    y = n                   ' here I do not call the bcx_vector
    z = p                   ' constructor and I make the
  END CONSTRUCTOR           ' trivector constructor do the
                            ' whole job. Same result.
   
   FUNCTION module () AS DOUBLE
     FUNCTION = sqrt (x*x + y*y + z*z)
   END FUNCTION
 END CLASS
    
 SUB test (k AS bcx_vector &)
   std::cout << "Test result:            " << k.module() << std::endl
 END SUB
    
 FUNCTION MAIN ()
  
   RAW AS bcx_vector a (4, 5)
   RAW AS trivector b (1, 2, 3)
    
   std::cout << "a (4, 5)    b (1, 2, 3)" << std::endl << std::endl
    
   RAW AS bcx_vector PTR r
    
   r = &a
   std::cout << "module of bcx_vector a: " << r->module() << std::endl
    
   r = &b
   std::cout << "module of trivector b:  " << r->module() << std::endl
    
   test (a)
    
   test (b)
    
   RAW AS bcx_vector &s = b
    
   std::cout << "module of trivector b:  " << s.module() << std::endl
 
 END FUNCTION

Result:


 a (4, 5)    b (1, 2, 3)

 module of bcx_vector a: 6.40312
 module of trivector b:  3.74166
 Test result:            6.40312
 Test result:            3.74166
 module of trivector b:  3.74166

Chapter 28. A class can be derived from more than one base class.

Maybe you wonder if a class can be derived from more than one base class. The answer is yes.

Example C28.bas:


 $NOMAIN
  
 #include <iostream>
   
 CLASS bcx_vector
   PUBLIC:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
     x = a
     y = b
   END CONSTRUCTOR
    
   FUNCTION surface() AS DOUBLE
     FUNCTION = fabs (x * y)
   END FUNCTION
 END CLASS
   
 CLASS number
   PUBLIC:
   RAW AS DOUBLE z
    
   CONSTRUCTOR number (a AS DOUBLE)
     z = a
   END CONSTRUCTOR
    
   FUNCTION is_negative () AS INT
     IF z < 0 THEN
       FUNCTION = 1
     ELSE
       FUNCTION = 0
     END IF
   END FUNCTION
 END CLASS
   
 CLASS trivector USING PUBLIC bcx_vector, PUBLIC number
   PUBLIC:
    
   CONSTRUCTOR trivector(a=0 AS DOUBLE, b=0 AS DOUBLE, c=0 AS DOUBLE) USING bcx_vector(a,b), number(c)
   END CONSTRUCTOR   ' The trivector constructor calls the bcx_vector
                     ' constructor, then the number constructor,
                     ' and in this example does nothing more.
   
   FUNCTION volume() AS DOUBLE
     FUNCTION = fabs (x * y * z)
   END FUNCTION
 END CLASS
   
 FUNCTION MAIN ()
  
   RAW AS trivector a(2, 3, -4)
    
   std::cout << a.volume() << std::endl
   std::cout << a.surface() << std::endl
   std::cout << a.is_negative() << std::endl
 
 END FUNCTION

Result:


 24
 6
 1

Chapter 29. Class derivation allows you to write generic methods.

Class derivation allows you to construct more complex classes built from base classes. There is another application of class derivation: allowing the programmer to write generic functions.

Suppose you define a base class with no variables. It makes no sense to use instances of that class inside your program. But then you write a function whose purpose it is to sort instances of that class. That function will be able to sort any type of object provided it belongs to a class derived from that base class! The only condition is that inside of each derived class definition, all methods that the sort function needs are correctly defined.

Example C29.bas:


 $NOMAIN
  
 #include <iostream>
  
 CLASS octopus
   PUBLIC:
    
   IMPFUNCTION module() = 0 AS virtual DOUBLE
   ' = 0 implies function is not
   ' defined. This makes instances
   ' of this CLASS cannot be declared.
END CLASS
    
 FUNCTION biggest_module (a AS octopus &, b  AS octopus &, c  AS octopus &) AS DOUBLE
   RAW r = a.module() AS DOUBLE
   IF b.module() > r THEN r = b.module()
   IF c.module() > r THEN r = c.module()
   FUNCTION = r
 END FUNCTION
    
 CLASS bcx_vector USING PUBLIC octopus
   PUBLIC:
    
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   CONSTRUCTOR bcx_vector (a = 0 AS DOUBLE, b = 0 AS DOUBLE)
     x = a
     y = b
   END CONSTRUCTOR
    
   FUNCTION module() AS DOUBLE
     FUNCTION = sqrt (x * x + y * y)
   END FUNCTION
 END CLASS
    
 CLASS number USING PUBLIC octopus
   PUBLIC:
    
   RAW AS DOUBLE n
    
   CONSTRUCTOR number (a = 0 AS DOUBLE)
     n = a
   END CONSTRUCTOR
    
   FUNCTION module() AS DOUBLE
     IF n >= 0 THEN FUNCTION = n
     FUNCTION = -n
   END FUNCTION
 END CLASS
    
 FUNCTION MAIN ()
  
   RAW AS bcx_vector k (1,2), m (6,7), n (100, 0)
   RAW AS number p (5),   q (-3),  r (-150)
    
   std::cout << biggest_module (k, m, n) << std::endl
   std::cout << biggest_module (p, q, r) << std::endl
   std::cout << biggest_module (p, q, n) << std::endl
 
 END FUNCTION

Result:


 100
 150
 100

Chapter 30. ENCAPSULATION: public, protected and private

The *PUBLIC:* directive means the variables or the methods below can be accessed and used everywhere in the program.

If you want the variables and methods to be accessible only to methods of the class AND to methods of derived classes, then you must put the keyword *protected:* before them.

If you want variables or methods to be accessible ONLY to methods of the class, then you must put the keyword *private:* before them.

The fact that variables or methods are declared private or protected means that nothing external to the class can access or use them. That's ENCAPSULATION. (If you want to give a specific function the right to access those variables and methods, then you must include that function's prototype inside the class definition, preceded by the keyword *friend*.)

Good practice is to encapsulate all the variables of a class. This can sound strange if you're used to structs in C. Indeed a struct only makes sense if you can access its data... In C++ you have to create methods to access the data inside a class. The example below uses the basic example of chapter 17, yet declares the class data to be protected.

Example C30_01.bas:


 $NOMAIN
  
 #include <iostream>
   
 CLASS bcx_vector
   PROTECTED:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   PUBLIC:
    
   SUB set_x (n AS INT)
     x = n
   END SUB
    
   SUB set_y (n AS INT)
     y = n
   END SUB
    
   FUNCTION surface () AS DOUBLE
     RAW AS DOUBLE s
     s = x * y
     IF s < 0 THEN s = -s
     FUNCTION = s
   END FUNCTION
 END CLASS
    
 FUNCTION MAIN ()
  
   RAW AS bcx_vector a
    
   a.set_x (3)
   a.set_y (4)
    
   std::cout << "The surface of a: " << a.surface() << std::endl
 
 END FUNCTION

Result:


 The surface of a: 12

The example above is a bit odd since the class data x and y can be set but they cannot be read back. Any attempt in function main () to read a.x or a.y will result in a compilation error. In the next example, x and y can be read back.

Example C30_02.bas:


 $NOMAIN
  
 #include <iostream>
   
 CLASS bcx_vector
   PROTECTED:
   RAW AS DOUBLE x
   RAW AS DOUBLE y
    
   PUBLIC:
    
   SUB set_x (n AS INT)
     x = n
   END SUB
    
   SUB set_y (n AS INT)
     y = n
   END SUB
    
   FUNCTION get_x () AS DOUBLE
     FUNCTION = x
   END FUNCTION
    
   FUNCTION get_y () AS DOUBLE
     FUNCTION = y
   END FUNCTION
    
   FUNCTION surface () AS DOUBLE
     RAW AS DOUBLE s
     s = x * y
     IF s < 0 THEN s = -s
     FUNCTION = s
   END FUNCTION
 END CLASS
    
 FUNCTION MAIN ()
  
   RAW AS bcx_vector a
    
   a.set_x (3)
   a.set_y (4)
    
   std::cout << "The surface of a: " << a.surface() << std::endl
   std::cout << "The width of a:   " << a.get_x() << std::endl
   std::cout << "The height of a:  " << a.get_y() << std::endl
 
 END FUNCTION

Result:


 The surface of a: 12
 The width of a:   3
 The height of a:  4

Chapter 31. Brief examples of file I/O

Let's talk about input/output. In C++ that's a very broad subject. Here is a program that writes to a file

Example C31_01.bas:


 $NOMAIN
  
 #include <iostream>
 #include <fstream>
 
 FUNCTION MAIN ()
  
   RAW AS std::fstream f
    
   f.open("test.txt", std::ios::out)
    
   f << "This is a text output to a file." << std::endl
    
   RAW AS DOUBLE a = 345
    
   f  << "A number: " << a << std::endl
    
   f.close()
   std::cout << "test.txt created" << std::endl
 
 END FUNCTION

Result:


 test.txt created

The content of file test.txt should be


 This is a text output to a file.
 A number: 345

Before you use Example C31_02 be sure to create the test.txt file with Example C31_01.

Example C31_02.bas:


 $NOMAIN
  
 #include <iostream>
 #include <fstream>
 
 FUNCTION MAIN ()
  
   RAW AS std::fstream f
   RAW AS CHAR c
    
   std::cout << "What's inside the test.txt file" << std::endl
   std::cout << std::endl
    
   f.open("test.txt", std::ios::in)
    
   WHILE NOT f.eof()
     f.get(c)    'Or c = f.get()
    std::cout << c
   WEND
    
   f.close()
 
 END FUNCTION

Result:


 What's inside the test.txt file

 This is a text output to a file.
 A number: 345

Chapter 32. Character arrays can be used like files

Generally speaking, it is possible to do on character arrays the same operations as on files. This is very useful to convert data or manage memory arrays.

Here is a program that writes inside a character array.

Example C32_01.bas:


 $NOMAIN
  
 #include <iostream>
 #include <strstream>
     
 FUNCTION MAIN ()
  
   RAW AS CHAR a[1024]
   RAW AS std::ostrstream b(a, 1024)
      
  b.seekp(0)                            ' Start from first char.
  b << "2 + 2 = " << 2 + 2 << std::ends ' ( ends, not std::endl )
                                        ' ends is simply the
                                        ' null character   '\0'
  std::cout << a << std::endl
      
   RAW AS DOUBLE v = 2
      
   a$ = "A sinus: "
      
   b.seekp(LEN (a))
   b << "sin (" << v << ") = " << sin(v) << std::ends
      
   std::cout << a << std::endl
 
 END FUNCTION

Result:


 2 + 2 = 4
 A sinus: sin (2) = 0.909297

A program that reads from a character string

Example C32_02.bas:

 
 $NOMAIN
  
 #include <iostream>
 #include <strstream>
 
 FUNCTION MAIN ()
  
   RAW AS CHAR a[1024]
   RAW AS std::istrstream b(a, 1024)
   
   a$ = "45.656"
      
   RAW AS DOUBLE k, p
      
  b.seekg(0)  ' Start from first character.
  b >> k
      
   k = k + 1
      
   std::cout << k << std::endl
      
   a$ = "444.23 56.89"
      
   b.seekg(0)
   b >> k >> p
      
   std::cout << k << ", " << p + 1 << std::endl
 
 END FUNCTION

Result:


 46.656
 444.23, 57.89

Chapter 33. An example of formatted output

This program performs formatted output two different ways. Please note the *width()* and *setw()* MODIFIERS are only effective on the next item output to the stream. Subsequent items will not be influenced.

Example C33.bas:


 $NOMAIN
  
 #include <iostream>
 #include <iomanip>
 
 FUNCTION MAIN ()
  
   RAW AS INT i
    
   std::cout << "A list of numbers:" << std::endl
   XFOR i = 1 WHILE i <= 1024 BY i *= 2
     std::cout.width (7)
     std::cout << i << std::endl
   XNEXT
    
   std::cout << "A table of numbers:" << std::endl
   XFOR i = 0 WHILE i <= 4 BY i++
     std::cout << std::setw(3) << i << std::setw(5) << i * i * i << std::endl
   XNEXT
 
 END FUNCTION

Result:


 A list of numbers:
      1
      2
      4
      8
     16
     32
     64
    128
    256
    512
   1024
 A table of numbers:
  0    0
  1    1
  2    8
  3   27
  4   64