Archive

Posts Tagged ‘array’

Dinamically allocate memory for a bi-dimensional array in C

January 7, 2014 No comments

One of the biggest faults of an array is that we have to define it’s size in coding time. Sometimes it’s the easiest thing to do and it’s ok, we may waste some bytes (As in a little string when we create a 100 bytes array); sometimes we choose the right size (for example when creating an array with the names of the months). But many times we have no idea what the size it must have, if it is very small we probably will fail short and if it is very large, we will wast a lot of memory.

But one of the tools C has is the dinamic memory allocation (malloc function and derivates), but it can allocate memory for an structure, or an unidimensional array, if we want to allocate memory for a two-dimensional, three-dimensional array or so, we must allocate memory for each of the arrays composing the multi-dimensional array,

To have a dynamic array, we must have a double pointer, so it can be declared as:

1
int **myArray;

To allocate memory for that variable, first we must allocate all rows, and then, inside each row, we must allocate the columns. For example for a 3×3 array, we must:

  • Allocate 3 rows
  • Allocate 3 columns for 1st row
  • Allocate 3 columns for 2nd row
  • Allocate 3 columns for 3rd row

The next example is using calloc() function to allocate memory (we can do it with malloc with no difficulties:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdlib.h>
#include <stdio.h>

void** calloc2d (int rows, int cols, int elemSize)
{
  void **variable;
  int i;

  variable=(void**)calloc(rows, sizeof(void*));
 
  for (i=0; i<rows; i++)
    {
      variable[i]=calloc(cols, elemSize);
    }
  return variable;
}

void free2d (void **var, int rows)
{
  int i;
  for (i=0; i<rows; i++)
    free(var[i]);

  free(var);
}

void randomValues(int **v, int rows, int cols)
{
  int i,j;
  for (i=0; i<rows; i++)
    for (j=0; j<cols; j++)
      v[i][j]=rand();
}

int main(int argc, char *argv[])
{
  int rows=10000;
  int cols=20000;
  getchar();
  int ** v=(int**)calloc2d(rows, cols, sizeof(int));

  randomValues(v, rows, cols);
  getchar();

  free2d((void**)v, rows);
  getchar();
  return EXIT_SUCCESS;
}

The first function (calloc2d()) will allocate dinamically bi-dimensional arrays indicating rows and columns, free2d() will free memory allocated only indicating rows.
The function randomValues() assign random integer values to the array, to use the allocated memory, so the memory will be really used.

The program does three pauses, one before anything (press enter, to continue), another one when the memory is allocated, and the other one when everything in freed. We can use a memory analysis program, or even top to see what’s going on.

Be careful if your system is low on memory, because 10000 rows * 20000 columns * 4 (sizeof(int)) = 800000000 = 8*10^8 or 800Mb

Photo cibomahto (Flickr) CC-by

Swapping variable values in PHP [Short post]

October 11, 2013 No comments

Yesterday we talked about swapping variables in C and C++. This time, we will do it in PHP.

We can translate the C program to PHP, creating a temporary value and running the program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$a = 11;
$b = 99;

echo "Original A value: ".$a."\n";
echo "Original B value: ".$b."\n";

$tmp = $a;
$a = $b;
$b = $tmp;

echo "New A value: ".$a."\n";
echo "New B value: ".$b."\n";
?>

It will simply work, but we can take advantages of built-in PHP functions, to make it shorter (and we won’t use a temporary variable):

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$a = 11;
$b = 99;

echo "Original A value: ".$a."\n";
echo "Original B value: ".$b."\n";

list($a, $b) = array($b, $a);

echo "New A value: ".$a."\n";
echo "New B value: ".$b."\n";
?>

So first we create an array with values $b and $a and then we separate this values in variables $a and $b. The result is the same.

File sizes for humans (PHP, C, C++)

When we get a file size, we usually get it in bytes. It’s ok to have this value, but, when giving the user this information, we must convert it to another unit to make it a little more accessible. When talking about megabytes or gigabytes, everyone will make a mess. So here are some snippets to help us do that:

First in PHP:

1
2
3
4
5
6
7
8
9
function human_size ($tam) {
        $i = 0;
        $unids=array("bytes","Kb","Mb","Gb","Tb","Pb","Eb","Zb","Yb","Bb");
        while ($tam>1024) {
                $tam = $tam /1024;
                $i++;
        }
        return number_format($tam,2,",",".").$unids[$i];
}

So we can call:

1
echo human_size(12939128332323);

It will return

11.77Tb

So we can have (as users) a better value.

In C++ we can do it that way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <sstream>

using namespace std;

string human_size(long double size)
{
  static string units[10]={"bytes","Kb","Mb","Gb","Tb","Pb","Eb","Zb","Yb","Bb"};
  ostringstream out;
  int i= 0;

  while (size>1024) {
    size = size /1024;
    i++;
  }

  out.precision(3);
  out<<size<<units[i];
  return out.str();
}

int main()
{
  cout <<human_size(1232312333)<<endl;
}

This time we use ostringstream to build the output string, but the basis is the same as php, it’s only to have a copy-paste snippet :)

And finally, C language, this time, we don’t have a string type, so we have to use char arrays to make it possible, this way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

char *human_size(char *store, long double size)
{
  static char units[10][6]={"bytes","Kb","Mb","Gb","Tb","Pb","Eb","Zb","Yb","Bb"};  
  int i= 0;

  while (size>1024) {
    size = size /1024;
    i++;
  }

  sprintf(store,"%.2Lf%s",size, units[i]);

  return store;
}

int main()
{
  char cadena[30];
  printf("Size: %s\n", human_size(cadena, 1293323872));
}

I know I’m using a lot of units: “bytes”, “Kilobytes”, “Megabytes”, “GigaBytes”, “Terabytes”, “Petabytes”, “Exabytes”, “Zetabytes”, “Yottabytes” and “Brontobytes”, and numeric variables won’t store such huge numbers. :)

This post is available in Spanish here: http://totaki.com/poesiabinaria/2010/03/tamano-de-archivo-para-seres-humanos-phpc-y-c/
Photo: Kate Haskell (Flickr) CC-by

Top