[Tutorial] Beginner's Guide: Single/Two/Multi-dimensional Arrays
#1

Beginner's Guide
Single & Multi-dimensional Arrays

(I'm a little free today so I thought about making a tutorial..)

In this tutorial, we'll cover only the basic information and understandings about how arrays work.
Knowledge about "Arrays" is necessary for any scripter. So, let's get started.

Requirements:
a) Some basic ideas about scripting/pawn.
b) Patience & Understanding ability.

Contents:
0. Definition of Array
1. Single Dimensional
2. Two Dimensional (Will post soon)
3. Three Dimensional (Will post soon)

Definition
Array is a structure of data that contains same or different values as a collection, each of them has a unique ID relating to their position in the structure. Easy, right? No, not really for a beginner, just read what's written below, you'll understand better.

1. Single Dimensional
Let's start with an example:
pawn Code:
new MyArray[10];
This will create a structure of 10 elements that looks like this:


Since this is only a "Chain", you can call it "Single Dimensional" or "String".

If we were to give IDs to each of the the elements, the whole chain would be [0] and each of the boxes would be [0]..[9]



Remember, first element will always start with ID "0" not "1"! If you count from 0 to 9, you'll see that there are 10 numbers. So, 0-9 = 10 slots.


As you can see the boxes are empty, but an element cannot be empty, so actually, these are filled with "NULL" characters.
This helps the compiler to understand where the strings end or else it wouldn't be able to to check the length of the string and terminate it.
Now, this is what it looks like:



Note that '\0' is a character constant called NULL.

Now, Let's see how it looks like if we have a word in it:

pawn Code:
new MyArray[10] = "Computers";


Now you see a '\0' at the end. It tells the compiler that the string ends there.

If you would've done:
pawn Code:
new MyArray[10] = "Computerss";
You'll come across:
Code:
error 018: initialization data exceeds declared size
Because there is no space for a NULL character!

You can also do:
pawn Code:
new MyArray[10] = {'C', 'o', 'm', 'p', 'u', 't', 'e', 'r', 's'};
//It's same as new MyArray[10] = "Computers";
To utilize the array:

pawn Code:
new MyArray[10] = "Computers";

printf("%s" /* identifier %s is for strings */, MyArray);

//or:
   
    printf
    (
        "%c%c%c%c%c%c%c%c%c%c", //If you didn't know, identifier '%c' is for characters.
        MyArray[0],
        MyArray[1],
        MyArray[2],
        MyArray[3],
        MyArray[4],
        MyArray[5],
        MyArray[6],
        MyArray[7],
        MyArray[8],
        MyArray[9]
    );

//Both will output:
Computers
pawn Code:
//If you do:
printf("%i" /* %i is for integers (numbers) */, MyArray[0]);

//it will output:
67

Because 67 is the ASCII number for the letter C.
So, for a simple use:
pawn Code:
new message[] = "Hello guys! I'm reading the tutorial here!";
format(message, sizeof message, "She said: %s", message);
print(message);

//Will give you:
She said: Hello guys! I'm reading the tutorial here!
Note: If you declare a string with no size, the precompiler will automatically set the size according to what you have initialized it with.
Example:

pawn Code:
new something[] = "YAY!";
//it becomes:
new something[5] = "YAY!";

2. Two Dimensional
Now, you know a lot more about 'Strings'. A 2D Array is actually String of Strings.

When you declare a new 2D Array:

pawn Code:
new MyArray_2D[7][8];
It looks like:



A 2D Array with content inside:



Some more explanation:

pawn Code:
new MyArray_2D [] [] =
    {
        "One",
        "Two",
        "Three"
    };
   
    printf("%s", MyArray_2D);
//will give you some weird symbols because MyArray_2D is a 2D Array,
//you are supposed to index it with an ID [i].

//So, do it this way:
printf("%s", MyArray_2D[0]);
//gives: "One" because at first index 0, you have a string "One"

printf("%s", MyArray_2D[0][0]);
//Also gives: "One" because in the printf function, you specified it as a "String" using %s,
//it will print characters until it reaches a NULL index.

printf("%c", MyArray_2D[0][0]);
//Gives: "O" because at the position 0, 0 in MyArray_2D, "O" is a character.

printf("%s", MyArray_2D[1]);
//Gives: "Two" and similarly,  MyArray_2D[2] will print "Three"
Some simple examples:
pawn Code:
new NewsHeadlines [4] [128] =
    {
                //[0] ............................................................ [i]
        /* [0] */ "The server was attacked by a group of rougue members this evening!",
        /* [1] */ "A competition held by an admin caused the server to crash!",
        /* [2] */ "Server crashed due to a bad filterscript this evening.",
        /* [3] */ "I have no other news in my head."
    };
   
    SendClientMessageToAll(-1, NewsHeadlines [ random(sizeof NewsHeadlines) ] );
Here, "sizeof NewsHeadlines" will give 4.
Random of 4 will give 0 or 1 or 2 or 3 (0-3 = 4 numbers)

So, NewsHeadlines[0-3] will give the message on ID 0-3.

And since it's a variable, you can changed the headlines!
pawn Code:
format(NewsHeadlines[0], 128, "The headline has been changed!");
    printf("%s", NewsHeadlines[0]);

3. Three Dimensional
Alright, so the harder part, 3D arrays.
As I've told you 2D arrays are string of strings, then 3D Arrays are string of strings of strings. Confusing, eh?

Anyway, I'll show an example:

pawn Code:
new Array_3D [4] [4] [4];
It would look like:


And If we put index numbers (slot ids):


As in scripts:

pawn Code:
new Array_3D_A [3] [5] [12] =
{
    {"Pen",     "Book",     "Paper",  "Notes",  "Pencil"},
    {"Laptop",  "Computer", "Cell",   "Pad",    "Pod"},
    {"Car",     "Bike",     "Bus",    "Train",  "Muscle"}
};

for ( new index = 0; index < sizeof Array_3D_A; index++ )
    {
        printf
        (
            "Objects: %s | %s | %s | %s | %s",
            Array_3D_A[index][0],
            Array_3D_A[index][1],
            Array_3D_A[index][2],
            Array_3D_A[index][3],
            Array_3D_A[index][4]
        );
    }
Will output:
Code:
Objects: Pen | Book | Paper | Notes | Pencil
Objects: Laptop | Computer | Cell | Pad | Pod
Objects: Car | Bike | Bus | Train |
Let's see how we get the index ids:

pawn Code:
new Array_3D_A [3] [5] [12] =
{
    //       [0]        [1]         [2]       [3]       [4]
    /*[0]*/ {"Pen",     "Book",     "Paper",  "Notes",  "Pencil"},
    /*[1]*/ {"Laptop",  "Computer", "Cell",   "Pad",    "Pod"},
    /*[2]*/ {"Car",     "Bike",     "Bus",    "Train",  "Muscle"}
};
As you move down the lines, it's in increasing order of main indexes. (Above, there are 3 columns, 0-2)
As you move Left-to-Right, it's in increasing order of the second indexes. (Above, there are 5 rows, 0-4)
And as you count the characters of each string (word), your going in increasing order of the third indexes.
(Above, there are 12 elements, 0-11 where the strings are stored)


Another example:
pawn Code:
new Array_3D_B [] [] [] =
{
    {float:102.14571,   "******",       4100},
    {float:452.45245,   "*******",      4012},
    {float:124.78951,   "Memebase",     4501}
};

for ( new index = 0; index < sizeof Array_3D_B; index++ )
    {
        printf
        (
            "Data: %f | %s | %i",
            Array_3D_B[index][0],
            Array_3D_B[index][1],
            Array_3D_B[index][2]
        );
    }
Will output:

Code:
Data: 102.145713 | ****** | 4100
Data: 452.452453 | ******* | 4012
Data: 124.789512 | Memebase | 4501
Another one:
pawn Code:
new Array_3D_C [] [] [] =
{
    { {'A', 'C', 'E', '\0'}, 0xFF11FF25, float:4.154,  36},
    { {'B', 'A', 'M', '\0'}, 0xFFFFFFFF, float:6.154,  43},
    { {'Y', 'A', 'Y', '\0'}, 0x0,        float:74.154, 46}
};

for ( new index = 0; index < sizeof Array_3D_C; index++ )
    {
        printf
        (
            "Data: %s | %x | %f | %c",
            Array_3D_C[index][0],
            Array_3D_C[index][1],
            Array_3D_C[index][2],
            Array_3D_C[index][3]
        );
    }
Will output:
Code:
Data: ACE | -EE00DB | 4.153999 | $ | 
Data: BAM | -1 | 6.153999 | + | 
Data: YAY | 0 | 74.153999 | . |
---

That's all for now!
Reply
#2

* Reserved for Future use.
Reply
#3

This is very bad... I cannot give you reputation you deserve for this excellent tutorial. Very beautiful work and will help alot of people on difficult situation understanding arrays.
Reply
#4

Quote:
Originally Posted by iPLEOMAX
View Post
pawn Code:
//If you do:
printf("%c", MyArray[10]);

//will ouput:
(null) because the last character is '\0'
I'm quite sure that this is an OOB (Out-Of-Bounds) error; the 10th element doesn't exist. Other than that, very good.
Reply
#5

@T0pAz
No problem bro, it's all for the sake of community.

@Vince
Yes, thank you for pointing that out. Edited now.
Reply
#6

Quote:
Originally Posted by Y_Less
View Post
I'd suggest you do something on enum arrays, and how they're not what people think.
That's something I'd glad to know, how come enum arrays are not what people think?
Reply
#7

Quote:
Originally Posted by Y_Less
View Post
I'd suggest you do something on enum arrays, and how they're not what people think.
Quote:
Originally Posted by [XST]O_x
View Post
That's something I'd glad to know, how come enum arrays are not what people think?
Alright then, I'll also do that
Reply
#8

Part 1:
1) hi 10
2) h 10
F) hi 10
3)-5) I have no idea. (I'd be really glad for an explanation though)

Part 2:
6) h, and I believe 1? Or 10, not quite sure.
F) h, 1

Part 3:
7)hi
F)hi, 10
Reply
#9

Quote:
Originally Posted by Y_Less
View Post
Do you know what this code prints?

pawn Code:
#include <a_samp>

enum E_EG
{
    E_EG_NUM,
    E_EG_STR[10],
}

main()
{
    // Part 1.
    new eg[E_EG] = {42, "hi"};
    printf("1) %s %d", eg[E_EG_STR], sizeof (eg[E_EG_STR]));
    printf("2) %s %d", eg[E_EG_STR][0], sizeof (eg[E_EG_STR]));
    func(eg[E_EG_STR]);
    printf("3) %d", eg[E_EG:2]);
    printf("4) %d", eg[E_EG_STR + E_EG:1]);
    printf("5) %d", _:E_EG_STR);
    // Part 2.
    new eg2[10] = "hi";
    printf("6) %s %d", eg2[0], sizeof (eg2[]));
    func(eg2[0]);
    // Part 3.
    new eg3[10][E_EG];
    printf("7) %s", eg3[0][E_EG_STR]);
    func(eg3[5][E_EG_STR]);
}

func(data[], size = sizeof (data))
{
    printf("F) %s %d", data, size);
}
Sorry about ME answering your question, but wouldn't it return the ascii value of "i" (the second character in the string)? I'm just curious about that since I'm not very good at this.

EDIT: Oh, I see you've edited it. Let me see again.

pawn Code:
#include <a_samp>

enum E_EG
{
    E_EG_NUM,
    E_EG_STR[10] // There was an unneeded comma here, so I removed it
}

main()
{
    // Part 1.
    new eg[E_EG] = {42, "hi"}; // Assigns 42 to the E_EG_NUM var and "hi" to the E_EG_STR var
    printf("1) %s %d", eg[E_EG_STR], sizeof (eg[E_EG_STR])); // Prints the string itself, and the size of the string
    printf("2) %s %d", eg[E_EG_STR][0], sizeof (eg[E_EG_STR])); // Prints the string, starting from position 0 and the size
    func(eg[E_EG_STR]); // Prints the string, and the current size of the string
    printf("3) %d", eg[E_EG:2]); // Prints the ascii value of the second character
    printf("4) %d", eg[E_EG_STR + E_EG:1]); // Prints the same as above
    printf("5) %d", _:E_EG_STR); // No idea what this is though
    // Part 2.
    new eg2[10] = "hi"; // Creates a new char and assigns the value "hi" to it
    printf("6) %s %d", eg2[0], sizeof (eg2[])); // Does exactly what 2) does, but it gets the current size of the variable
    func(eg2[0]); // Does exactly what the previous F) does, but assigns the string to be gotten from a chosen position
    // Part 3.
    new eg3[10][E_EG]; // No idea what this does
    printf("7) %s", eg3[0][E_EG_STR]); // No idea what this does
    func(eg3[0][E_EG_STR]); // No idea what this does
}

func(data[], size = sizeof (data))
{
    printf("F) %s %d", data, size);
}
Reply
#10

Quote:
Originally Posted by Y_Less
View Post
That's not very clear actually, the main point is the difference between:

pawn Code:
printf("%d", sizeof (arr[0]));
pawn Code:
printf("%d", sizeof (eArr[E_EG_STR]));
pawn Code:
func(eArr[E_EG_STR]);
// ...
func(arr[], size = sizeof (arr) printf("%d", size);
One of which won't even compile, the other two will give different results for essentially the same thing.
Well, the function itself won't compile because there's a bracket missing, but anyway, this is really interesting to be honest. There definately should be a tut on it.
Reply


Forum Jump:


Users browsing this thread: 7 Guest(s)