WOWCube Docs logo
WOWCube Docs
Mission Control
Section Shortcuts
APIExamplesSourceWOWConnectChangelog
Filters
SDK and language defaults persist in cookies.
SDK version
Navigation Tree
Collapsed by default, focused on the active path.
Made byMcKay Seamons
GitHub
  1. Home
  2. Docs
  3. Examples
  4. Strings and Arrays
Mission NodeSDK 6.3C++basicsProject Included

Strings and Arrays

Arrays In the previous examples you have learned how to use varialbles for counting and measuring. You have been using one variable to count seconds, another...

Examples / SDK 6.3 / C++ / basics

Arrays

In the previous examples you have learned how to use varialbles for counting and measuring. You have been using one variable to count seconds, another one for frames per second ratio and so on.

But what if you have got a problem that requires a lot of variables to solve?

What if you need tens of variables to hold some temporary values?

In that case, you should use arrays.

An array is a data structure consisting of a collection of element values, each identified by at least one array index. An array is stored such that the position of each element can be computed from its index

Arrays have many applications: they are used to implement mathematical vectors and matrices, as well as other kinds of rectangular tables.Applications use one-dimentional arrays for storing data records. Arrays are also used to implement other data structures, such as lists, queues and strings. Such data structures are used in game applications extensively. It is an essential part of nearly any game application.

When data objects are stored in an array, individual elements are selected by an index that is a non-negative integer. Indices are also called subscripts.

The first element of the array is indexed by subscript of 0. This leads to simpler implementation where the subscript refers to an offset from the starting position of an array, so the first element has an offset of zero.

Arrays can have multiple dimentions too. Thus, it is not uncommon to access an array using multiplt indices.

For example, a two-dimentional array A with three rows and four columns provides access to the element at the 2nd row and 4th column by the expression A[1][3].

Thus, two indices are used for a two-dimentional array, three for a three-dimentional array, and n for n-dimentional one.

Arrays in C++ language

In C++, an array is a variable that can store multiple values of the same type. For example, suppose a class has 27 students and we need to store grades of all of them. Instead of creating 27 separate variables, we can simply create an array:

Strings and Arrays
CPP
1double grade[27];
2
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Here grade is an array that can hold a maximum of 27 elements of double type.

It is also must be remembered that in C++ the size and type of arrays can not be changed after its declaration.

Each element in an array is associated with a number. The number is known as an array index

So let's see how can we access elements of an array... We can access them by using those indices.

Strings and Arrays
CPP
1//declaration of an array that has 10 integer elements
2int array[10];
3
4//syntax to acess array elements
5int index = 0;
6int myVar = array[index];
7int myVar2 = array[index+1];
8
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

There are several things that should be remembered:

  • The array indices start with 0. Meaning x[0] is the first element stored in the array
  • If the size of an array is n, the last element is stored at index (n-1)
  • Elements of an array have consecutive addresses. For example, let's suppose we have an array of integers int x[10]; the starting address of x[0] is 0x2120. Then the addres of the next element x[1] will be 0x2024, the address of x[2] will be 0x2028 and so on. The address of each element is increased by 4 because it takes 4 bytes to store an integer value in memory.

How do we initialize arrays when application starts?

In C++ language, it is possible to initialize an array during declaration. For example,

Strings and Arrays
CPP
1//declare and initialize an array
2int array[6] = {19, 10, 8, 17, 9, 15};
3
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

or

Strings and Arrays
CPP
1//declare and initialize an array
2int array[] = {19, 10, 8, 17, 9, 15};
3
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

In the above, we have not mentioned the size of the array. In such cases, the C++ compiler automatically computes the size.

Finally, you can initialize an array with empty members too. In C++, if an array has a size n, we can store up to n number of elements in the array. However, what will happen if we store less than n number of elements?

For example,

Strings and Arrays
CPP
1//store only 3 elements in the array
2int array[6] = {19, 10, 8};
3
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Here, the array has a size of 6. However, we have initialized it with only 3 elements. In such cases, the C++ compiler may assign random values to the remaining places. Dependning on version of the compiler, the value may be 0.

C++ allows multidimentional arrays. For example, the following declaration creates a two-dimentioal 5 x 10 integer array:

Strings and Arrays
CPP
1//declare 2d array
2int array2d[5][10];
3
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

A two-dimentional array is, in essence, a list of one-dimentional arrays. It can be think as a table, or a matrix which will have x number of rows and y number of columns. Thus, every element in such array is identified by a pair of indices like array[i][j] where i and j are the subscripts that uniquely identify each element in the array.

Similarily to one-dimentional arrays, multi-dimentional arrays can be initialized by specifying bracketed values for each row. The following is an array with 3 rows and each row has 4 columns:

Strings and Arrays
CPP
1int array[3][4] = {
2 {0, 1, 2, 3} , /* initializers for row indexed by 0 */
3 {4, 5, 6, 7} , /* initializers for row indexed by 1 */
4 {8, 9, 10, 11} /* initializers for row indexed by 2 */
5}
6
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

The nested braces, which indicate the intended row, are optional. The following initialization is equivalent to previous example:

Strings and Arrays
CPP
1int array[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
2
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Vectors in C++ language

As we've learned above, in C++ an array is a fixed-size collection of elements of the same data type that are stored in a continuous block of memory. Once an array is created, its size can not be changed.

But what if we want to have an array that should changed its size dynamically?

For that, C++ has vectors.

std::vector is a dynamic array that can grow or shrink in size as needed. It is a container class in the C++ Standard Template Library (STL) that provides a convenient way to manage arrays of varying sizes.

One of the key differences between std::vector and arrays is that std::vector manages its own memory allocation and deallocation. When the size of a std::vector changes, it automatically reallocates memory as needed, whereas with an array, you would have to manage the memory manually by allocating or deallocating it yourself.

Additionally, std::vector provides a number of member functions that make it easy to manipulate the elements stored in the vector, such as adding or removing elements, accessing specific elements, and iterating over the vector. With an array, you would have to implement these operations manually.

So to sum up, std::vector provides a flexible and convenient way to work with dynamic arrays in C++, whereas arrays are fixed-size collections of elements that must be managed manually.

Strings in C++ language

In C++, a string is a sequence of characters stored in a contiguous block of memory. Strings can be represented using two different types:

  • C-style strings: C-style strings are arrays of characters terminated with a null character ('\0'). They are created by declaring an array of characters and initializing it with a sequence of characters, followed by a null character. For example:

    Strings and Arrays
    CPP
    1 char myString[] = "Hello, world!";
    2
    Wrapped for easier reading. Turn wrap off to inspect exact line lengths.
  • std::string: std::string is a class that represents a string of characters. It is part of the C++ Standard Library and provides a convenient way to manipulate strings. To use std::string, you need to include the <string> header file. For example:

    Strings and Arrays
    CPP
    1 #include <string>
    2
    3 std::string myString = "Hello, world!";
    4
    Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

The main advantage of using std::string over C-style strings is that std::string manages its own memory allocation and deallocation, so you don't have to worry about the size of the string or allocating memory yourself. std::string also provides a wide range of member functions that make it easy to manipulate strings, such as appending or erasing characters, finding substrings, and comparing strings.

In addition, std::string supports a wide range of string operations, such as concatenation, conversion to and from other data types, and input/output.

The example

Now when you've learned all that theory about arrays and strings, let's get to actual example.

In order to demonstrate the work with arrays and strings, we will use several arrays of different dimentions, initialize them with strings and then show these strings on the sides of WOWCube device with a bit of funky animations.

First, let's declare the arrays:

Strings and Arrays
CPP
1//array of characters
2char arrWOWCUBE[8];
3
4//vectors of strings
5std::vector<std::string> arrWOWCUBE2;
6std::vector<std::string> arrTWISTY;
7
8//float parameters used to calculate vertical offsets of each letter
9float fParam[6];
10//array of previous letter positions
11int prevPos[6][2];
12
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

and initialize them:

Strings and Arrays
CPP
1StringsAndArrays::StringsAndArrays():
2 firstFrame(0),i1(0),i2(0),
3 arrWOWCUBE{'W','O','W','C','U','B','E',' '},
4 arrWOWCUBE2{"WOWCUBE","IS","COOL"},
5 arrTWISTY{"T","W","I","S","T","Y"},
6 fParam{0 ,20 ,10 ,-10,-20,-10},
7 prevPos{0,0,0,0,0,0,0,0,0,0,0,0}
8
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

Pay attention!

Different ways to declare arrays in the code above are used purely for the demonstration purposes. We recommend to choose and use one particular style of string variable declarations in your game cubeapps.

So what exactly is declared here?

  • arrWOWCUBE declares an array of characters that form the word `WOWCUBE'
  • arrWOWCUBE2 declares a vector of strings that contains 3 strings
  • arrTWISTY also declares a vector of strings
  • fParam declares an array of floating point values
  • prefPos declares a two-dimentional array of integers that would be used later for storing some temporary values

Second, we need to do some extra initialization. As always, variables are initialized in InitializeResources(). We initialize two timers for animation effects.

Then we modify the on_Timer callback to define the application logic of what should be happening on timer tick.

Strings and Arrays
CPP
1void StringsAndArrays::on_Timer(uint8_t timerID)
2{
3 switch(timerID)
4 {
5 case Timers::myTimer:
6 {
7 this->buff2+=this->arrWOWCUBE[i1];
8
9 i1++;
10 if(i1>7)
11 {
12 i1=0;
13 this->buff2 = " ";
14 }
15 }
16 break;
17 case Timers::myTimer2:
18 {
19 this->i2++;
20 if(this->i2>3) this->i2 = 0;
21 }
22 break;
23 default:
24 break;
25 }
26}
27
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

The function receives timerID identifier of a timer as an input parameter. We have two timers now, and we need to know which one produced a tick, right?

We have two timers that tick with different frequencies - one triggers every 100 milliseconds (10 times a second), another one produces a tick once a second.

So when the first timer ticks, on_Timer(0) is called. And when the second timer ticks, functions parameter changed to 1 and on_Timer(1) gets executed.

So let's see what happens when each timer ticks:

Timer 0

  • Take an i1 index from arrWOWCUBE array and copy it into a string buffer buff2
  • Increment i1 by 1
  • If i1 value gets greater than 7, reset it

Timer 1

  • Increment i2 by 1
  • If i2 gets greater than 3, reset it

This will result in constant change of array index parameters that we use for composing strings we render on screen.

Finally, we would want to render those strings (with a bit of animation, as promised).

Strings and Arrays
CPP
1void StringsAndArrays::on_Render(std::array<Cubios::Screen, 3>& screens)
2{
3 for(auto it = screens.begin(); it != screens.end(); ++it)
4 {
5 Cubios::GFX_setRenderTarget(it->ID());
6 Cubios::GFX_clear(Colors::black);
7
8 switch(it->ID())
9 {
10 case 0:
11 Cubios::GFX_drawText(120,120, TEXT_SIZE, 0, Cubios::text_align_t::TEXT_ALIGN_CENTER, Colors::teal, buff2.c_str());
12 break;
13 case 1:
14 if(i2<3)
15 {
16 if(i2>=0) GFX_drawText(120,120-50, TEXT_SIZE+2, 0, Cubios::text_align_t::TEXT_ALIGN_CENTER, MyColors::blue1, this->arrWOWCUBE2[0].c_str());
17 if(i2>=1) GFX_drawText(120,120, TEXT_SIZE+2, 0, Cubios::text_align_t::TEXT_ALIGN_CENTER, MyColors::blue2, this->arrWOWCUBE2[1].c_str());
18 if(i2>=2) GFX_drawText(120,120+50, TEXT_SIZE+2, 0, Cubios::text_align_t::TEXT_ALIGN_CENTER, MyColors::blue3, this->arrWOWCUBE2[2].c_str());
19 }
20 break;
21 case 2:
22 {
23 int x = 0;
24 float offset = 0;
25
26 for(size_t i=0;i<arrTWISTY.size();i++)
27 {
28 offset = sinf(this->fParam[i])*30;
29
30 this->fParam[i]+=0.15f;
31
32 if(firstFrame==0)
33 {
34 firstFrame = 1;
35 }
36 else
37 {
38 if(firstFrame==1)
39 {
40 firstFrame = 2;
41 GFX_drawText(10+x,DISPLAY_HEIGHT/2+prevPos[i][0]+10, TEXT_SIZE, 0, Cubios::text_align_t::TEXT_ALIGN_LEFT_CORNER, MyColors::pink2, this->arrTWISTY[i].c_str());
42 }
43 else
44 {
45 GFX_drawText(10+x,DISPLAY_HEIGHT/2+prevPos[i][1]+20, TEXT_SIZE, 0, Cubios::text_align_t::TEXT_ALIGN_LEFT_CORNER, MyColors::pink3, this->arrTWISTY[i].c_str());
46 GFX_drawText(10+x,DISPLAY_HEIGHT/2+prevPos[i][0]+10, TEXT_SIZE, 0, Cubios::text_align_t::TEXT_ALIGN_LEFT_CORNER, MyColors::pink2, this->arrTWISTY[i].c_str());
47 }
48 }
49
50 prevPos[i][1] = prevPos[i][0];
51 prevPos[i][0] = (int)(offset);
52
53 GFX_drawText(10+x,DISPLAY_HEIGHT/2+prevPos[i][0], TEXT_SIZE, 0, Cubios::text_align_t::TEXT_ALIGN_LEFT_CORNER, MyColors::pink1, this->arrTWISTY[i].c_str());
54 x+=40;
55 }
56 }
57 break;
58 }
59
60 Cubios::GFX_render();
61 }
62}
63
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

What we have here?

  • First screen displays the string buffer buff2 that is dynamically changed every 100 milliseconds on timer 0.
  • Second screen displays three words from arrWOWCUBE2 array selected by index that gets incremented on timer 1 each second.
  • Third screen... well, things are getting a little bit tricky here...

Third screen shows the word TWISTY built out of characters stored in arrTWISTY array.

If we would have wanted just to print that word on a straight line, we could just take an index of that array and print all characters one by one, right?

But that would be too easy and too boring. So instead, each letter in the word is animated, it sways up and down leaving a ghostly trace.

Behind every computer animation stands Math.

And our example is not an exclusion - in order to animate word letters we must apply some trigonometry. Cause if we want the letters to sway, we have to find the way to change their coordinates in an endless cyclical manner. And hopefully, make it look neat as well...

So, to generate per-letter vertical offsets, a sinf trigonometrical function is used:

Strings and Arrays
CPP
1offset = sinf(this->fParam[i])*30;
2fParam[i]+=0.015;
3
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.

The sinf function in C++ is a math function that calculates the sine of a given angle in radians, where the input value is a single-precision floating-point number. The function is defined in the <cmath> header file.

fParam[i] contains a floating point value of an angle that gets passed to the sine function on every tick and gets incremented by a small value. The offset parameter receives a value of a sine of an angle, then used for rendering letters at dynamic positions.

And finally, three copies of each letter are getting rendered for creation of a ghost trail effect.

Context Rail

Project files

StringsAndArrays.cpp
project/src/StringsAndArrays.cpp
StringsAndArrays.h
project/src/StringsAndArrays.h
wowcubeapp-build.json
project/wowcubeapp-build.json
Jump Grid

On This Page

ArraysArrays in C++ languageVectors in C++ languageStrings in C++ languageThe exampleTimer 0Timer 1
Context Rail

Related nodes

info.json
Examples / SDK 6.3 / C++ / basics / Strings and Arrays
StringsAndArrays.cpp
Examples / SDK 6.3 / C++ / basics / Strings and Arrays / project / src
StringsAndArrays.h
Examples / SDK 6.3 / C++ / basics / Strings and Arrays / project / src
wowcubeapp-build.json
Examples / SDK 6.3 / C++ / basics / Strings and Arrays / project
Previous Node
wowcubeapp-build.json
Examples / SDK 6.3 / C++ / basics / Working with Emulator / project
Next Node
info.json
Examples / SDK 6.3 / C++ / basics / Strings and Arrays