campo-sirio/include/array.cpp
guy e9a34d143f Migliorata gestione sheet ricerca
git-svn-id: svn://10.65.10.50/branches/R_10_00@23179 c028cbd2-c16b-5b4b-a496-9718f37d4682
2016-02-25 11:34:01 +00:00

1009 lines
23 KiB
C++
Executable File

#include <array.h>
#include <strings.h>
void TContainer::for_each( OPERATION_FUNCTION op )
{
TObject* curr = first_item();
while(curr)
{
op(*curr);
curr = succ_item();
}
}
void TContainer::for_each_that( OPERATION_FUNCTION op, CONDITION_FUNCTION match )
{
TObject* curr = first_that( match );
while( curr )
{
op( *curr );
curr = succ_that( );
}
}
TObject* TContainer::first_that( CONDITION_FUNCTION match )
{
_last_condition = match;
if( _last_condition )
{
TObject* curr = first_item( );
while( curr && !_last_condition( *curr ) )
curr = succ_item( );
return curr;
}
else
return first_item( );
}
TObject* TContainer::last_that( CONDITION_FUNCTION match )
{
_last_condition = match;
if( _last_condition )
{
TObject* curr = last_item( );
while( curr && !_last_condition( *curr ) )
curr = pred_item( );
return curr;
}
else
return last_item( );
}
TObject* TContainer::succ_that( )
{
if( _last_condition )
{
TObject* curr = succ_item( );
while( curr && !_last_condition( *curr ) )
curr = succ_item( );
return curr;
}
else
return succ_item( );
}
TObject* TContainer::pred_that( )
{
if( _last_condition )
{
TObject* curr = pred_item( );
while( curr && !_last_condition( *curr ) )
curr = pred_item( );
return curr;
}
else
return pred_item( );
}
long TContainer::count( CONDITION_FUNCTION match )
{
long c = 0;
TObject* curr = first_item( );
while( curr )
if( match( *curr ) )
c++;
return c;
}
TObject* TArray::first_item( )
{
_scanindex = first( );
return ( _scanindex == size( ) )?NULL:_data[ _scanindex ];
};
TObject* TArray::last_item( )
{
_scanindex = last( );
return ( _scanindex == -1 )?NULL:_data[ _scanindex ];
};
TObject* TArray::succ_item( )
{
_scanindex = succ( _scanindex );
return ( _scanindex == size( ))?NULL:_data[ _scanindex ];
};
TObject* TArray::pred_item( )
{
_scanindex = pred( _scanindex );
return ( _scanindex == -1)?NULL:_data[ _scanindex ];
};
// @doc EXTERNAL
// @mfunc Modifica la dimensione dell'array.
void TArray::resize(
int arraysize) // @parm Indica la nuova dimensione che deve assumere l'array.
// @comm Alloca la memoria necessaria per contentere i dati della nuova
// dimensione inizializzando a NULL tutti i nuovi elementi aggiunti
// all'array lasciando inalterati, sia in posizione che in
// contenuto gli elementi gia' presenti.
// <nl>Nel caso si cerchi di diminuire la dimensione viene dato un
// messaggio di errore.
{
CHECK(arraysize > _size, "Can't reduce array size.");
TObject** newdata = new TObject* [arraysize];
memset(newdata, 0, arraysize*sizeof(TObject*));
if (_data != NULL)
{
memcpy(newdata, _data, _size*sizeof(TObject*));
delete _data;
}
_size = arraysize;
_data = newdata;
}
// @doc EXTERNAL
// @mfunc Rimuove uno o tutti (default) gli elementi
// @rdesc Ritorna uno dei seguenti parametri:
//
// @flag TRUE | Se l'operazione e' riuscita con successo
// @flag FALSE | Se il numero di elementi e' rimasto invariato
bool TArray::destroy(
int index, // @parm Numero dell'elemento da eliminare (default -1)
bool pack) // @parm Se true richiama la funzione <mf TArray::pack> per compattare gli elementi dell'array (default FALSE)
// @comm Permette la rimozione di uno (index > 0 ) o di tutti (default) gli
// elementi dell'array assegnandone il valore NULL.
// <nl>Nel caso il parametro pack sia TRUE permette di rendere contigui
// tutti gli elementi diversi da NULL tramite la chiamata alla funzione
// <mf TArray::pack>.
{
const int old = _items;
if (index < 0)
{
for (int i = last(); i >= 0; i--) if (_data[i] != NULL)
{
delete _data[i];
_data[i] = NULL;
}
_items = _next = 0;
}
else
{
TObject* o = remove(index, pack);
if (o) delete o;
}
return _items < old;
}
void TArray::copy(const TArray& a)
{
destroy();
if (size() < a.size())
resize(a.size());
for (int i = a.size()-1; i >= 0; i--)
{
const TObject* o = a.objptr(i);
if (o != NULL)
{
_data[i] = o->dup();
#ifdef DBG
const long vir_tab1 = *((long*)o);
const long vir_tab2 = *((long*)_data[i]);
if (vir_tab1 != vir_tab2)
NFCHECK("Duplicazione di elementi di array pericolosa");
#endif
}
}
_items = ( int )a.items();
_next = ( int )a._next;
}
TArray::TArray(int arraysize)
: _data(NULL), _size(0), _items(0), _next(0)
{
if (arraysize)
resize(arraysize);
}
TArray::TArray()
: _data(NULL), _size(0), _items(0), _next(0)
{
}
TArray::TArray(const TArray& a)
: _data(NULL), _size(0), _items(0), _next(0)
{
copy(a);
}
TArray& TArray::operator= (const TArray& a)
{
copy(a);
return *this;
}
TArray::~TArray()
{
if (ok())
{
destroy();
delete [] _data;
}
}
const char* TArray::class_name() const
{
return "Array";
}
word TArray::class_id() const
{
return CLASS_ARRAY;
}
// @doc EXTERNAL
// @mfunc Stampa un array
void TArray::print_on(
ostream& out) const // @parm indica l'output sul quale reindirizzare la stampa (funzione standard del C++)
// @comm Permette di stampare sull'output passato come parametro il contenuto
// dell'array, preceduto dal numero dell'elemetno a cui si riferisce.
// <nl>Nel caso vi siano degli elementi vuoti (valore = NULL) viene
// stampato il valore (null).
{
for (int i = 0; i < size(); i++)
{
out.width(4);
out << i << ' ';
out.width();
if (_data[i] != NULL) out << *_data[i];
else out << "(null)";
out << endl;
}
}
// @doc EXTERNAL
// @mfunc Controlla se si tratta di un oggetto valido
//
// @rdesc Ritorna uno dei seguenti parametri:
// @flag TRUE | Se l'array contiene degli elementi
// @flag FALSE | Se l'array e' vuoto
bool TArray::ok() const
// @comm Controlla se la dimensione dell'array e' uguale a 0 e se esistono
// degli elementi diversi da NULL
{
return(size() != 0 && (_data != NULL));
}
#ifdef DBG
TObject& TArray::operator[] (int index) const
{
TObject* o = objptr(index);
if (o == NULL)
{
NFCHECK("Can't access NULL array item %d of %d", index, _size);
const int f = last();
if (f >= 0)
{
o = objptr(f)->dup();
((TArray*)this)->add(o, index);
}
CHECK(o, "Unrecoverable array access error");
}
return *o;
}
#endif
// @doc EXTERNAL
// @mfunc Aggiunge un oggetto ad un array.
//
// @rdesc La funzione ritorna la posizione nella quale e' stato aggiunto
// l'oggetto.
int TArray::add(
TObject *object, // @parm Oggetto da aggiungere nell'array
int index) // @parm Posizione in cui aggiungere l'oggetto
// @parm TObject | &object | Oggetto da aggiungere nell'array. L'oggetto viene duplicato
// @syntax add(TObject* object,int index);
// @syntax add(TObject& object,int index);
//
// @comm Nel caso venga passata una posizione minore di 0 l'elemento viene aggiunto
// in coda all'array, diversamente viene l'elemento presente viene
// sostitito con l'oggetto passato nei prametri.
// <nl>Se e' stato passato un indice minore della dimensione dell'array,
// viene aumentata automaticamente la dimensione dell'array stesso tramite
// la chiamata alla funzione <mf TArray::resize>.
// <nl><nl>ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve
// essere definita la funzione <mf TObject::dup>.
//
// @xref <mf TArray::insert>
{
if (index < 0)
for (index = _next; index < size() && _data[index]; index++);
if (index >= size())
{
long newsize = 3L * index / 2 + 1;
if (newsize > INT_MAX)
newsize = INT_MAX;
resize((int)newsize);
}
if (object != _data[index]) // Evita ricopiatura su se stesso
{
if (_data[index] != NULL)
{
delete _data[index];
_items--;
}
_data[index] = object;
if (object != NULL)
{
_items++;
_next = index+1;
}
else
{
if (index < _next)
_next = index;
}
}
return index;
}
// @doc EXTERNAL
// @mfunc Inserisce un elemento dell'array nella posizione index
//
// @rdesc La funzione ritorna la posizione nella quale e' stato inserito l'oggetto.
int TArray::insert(
TObject *object, // @parm Oggetto da inserire nell'array
int index, // @parm Posizione in cui inserire l'oggetto (puo' essere -1)
bool force) // @parm Forza l'inserimento anche se la posizione e' vuota
// @parm TObject | &object | Oggetto da inserire nell'array. L'oggetto viene duplicato
// @syntax insert(TObject* object, int index);
// @syntax insert(TObject& object, int index);
//
// @comm Nel caso l'elemento della posizione passata sia diverso da NULL vengono
// spostati di una posizione tutti gli elementi presenti nell'array.
// La dimensione dell'array viene automaticamente aumentata nel caso
// la stessa non sia sufficiente a contenere il nuovo oggetto.
// <nl><nl>ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve
// essere definita la funzione <mf TObject::dup>.
//
// @xref <mf TArray::add>
{
const int s = size();
if ((index >= 0 && index < s) && (force || objptr(index)))
{
if (_data[s - 1]) // Se l'ultimo non e' vuoto ...
add(NULL, s); // ... aggiungi un elemento in fondo
for (int i = size()-1; i > index; i--) // size va aggiornato perche potrebbe essere cambiato
_data[i] = _data[i - 1];
_data[index] = NULL;
}
return add(object, index);
}
int TArray::add(const TObject& object, int index)
{
TObject* objptr = object.dup();
return add(objptr, index);
}
int TArray::insert(const TObject& object, int index, bool force)
{
TObject* objptr = object.dup();
return insert(objptr, index, force);
}
// @doc EXTERNAL
// @mfunc Elimina l'elemento nella posizione index dell'array
//
// @rdesc Ritorna l'elemento dell'array eliminato senza farne la delete
TObject* TArray::remove(
int index, // @parm Indica la posizione dell'elemento da eliminare
bool dopack) // @parm Indica se si vuole richiamare la funzione
// <mf TArray::pack> (default FALSE) per spostare gli elementi successivi dell'array
{
CHECKD(index >= 0, "Can't remove array item ", index);
TObject* o = objptr(index);
if (o)
{
_data[index] = NULL;
_items--;
if (index < _next)
_next = index;
}
if (dopack && index < size())
{
const int last = size()-1;
for (int i = index ; i < last; i++)
_data[i] = _data[i+1];
_data[last] = NULL;
}
return o;
}
TObject* TArray::remove_item(bool pack )
{
return remove(_scanindex,pack);
}
void TArray::swap(int i1, int i2)
{
TObject* o1 = remove(i1, FALSE);
TObject* o2 = remove(i2, FALSE);
if (o1) add(o1, i2);
if (o2) add(o2, i1);
}
// @doc EXTERNAL
// @mfunc Cerca il prossimo oggetto dell'array
//
// @rdesc Ritorna l'indice del prossimo elemento trovato o size() se non esiste
int TArray::succ(int i) const
{
CHECKD(i >= -1, "Bad array index ", i);
for (i++; i < size(); i++)
if (_data[i]) break;
return i;
}
// @doc EXTERNAL
// @mfunc Cerca il precedente oggetto dell'array
//
// @rdesc Ritorna l'indice dell'elemento precedente o -1 se non esiste
int TArray::pred(int i) const
{
CHECKD(i <= size(), "Bad array index ", i);
for (i--; i >= 0; i--)
if (_data[i]) break;
return i;
}
// @doc EXTERNAL
// @mfunc Cerca il primo oggetto dell'array
//
// @rdesc Ritorna l'indice del primo elemento trovato o size() se l'array e' vuoto
int TArray::first() const
{
return succ(-1);
}
// @doc EXTERNAL
// @mfunc Cerca l'ultimo oggetto dell'array
//
// @rdesc Ritorna l'indice dell'ultimo elemento trovato o -1 se l'array e' vuoto
int TArray::last() const
{
return pred(size());
}
// @doc EXTERNAL
// @mfunc Rende contigui tutti gli elementi non nulli
void TArray::pack()
// @comm Riordina gli elementi dell'array facendo che tra di loro non ve ne
// siano con valore uguale a NULL.
{
int next = 0;
for (int i = 0; i < size(); i++)
{
if (_data[i] != NULL)
{
if (next < i)
{
_data[next] = _data[i];
_data[i] = NULL;
}
next++;
}
}
_next = next;
}
// @doc INTERNAL
// @func Funzione per permettere il confonto tra 2 oggetti.
//
// @rdesc Ritorna i seguenti valori
//
// @flag <gt>0 | se <p this> <gt> <p s>
// @flag 0 | se <p this> == <p s>
// @flag <lt>0 | se <p this> <lt> <p s>
// @flag UNDEFINED | se l'ordine non e' definito
static int sortable_compare(
const TObject** o1, // @parm Primo oggetto da confrontare
const TObject** o2) // @parm Secondo oggetto da confrontare
// @comm E' utilizzata dalla funzione <mf TArray::sort> come default per
// stabilire il criteri di ordinamento degli oggetti passati.
{
if (o1 == o2)
return 0; // qsort a volte confronta un oggetto con se stesso: per cui ne approfitto!
const TSortable* s1 = (const TSortable*)*o1;
const TSortable* s2 = (const TSortable*)*o2;
return s1->compare(*s2);
}
// @doc EXTERNAL
// @mfunc Ordina i TObject secondo il criterio definito in <t COMPARE_FUNCTION>
void TArray::sort(
COMPARE_FUNCTION compare) // @parm Funzione indicante il criterio di ordinamento (default TSortable)
// @comm Nel caso non venga passata nessuna funzione che permetta di confrontare
// i due oggetti viene utilizzato il criterio <c TSortable>
{
typedef int (*qsortfunc)(const void*, const void*);
if (compare == NULL) compare = sortable_compare;
pack();
qsort(_data, last()+1, sizeof(TObject*), (qsortfunc)compare);
}
static COMPARE_FUNCTION_EX _cmp_func = NULL;
static void* _cmp_jolly = NULL;
static int compare_ex(const void* p1, const void* p2)
{
if (p1 == p2)
return 0;
const TSortable& o1 = **(const TSortable**)p1;
const TSortable& o2 = **(const TSortable**)p2;
return _cmp_func(o1, o2, _cmp_jolly);
}
void TArray::sort(
COMPARE_FUNCTION_EX compare, // @parm Funzione indicante il criterio di ordinamento (default TSortable)
void* jolly)
// @comm Nel caso non venga passata nessuna funzione che permetta di conforntare
// i due oggetti viene utilizzato il criterio <c TSortable>
{
_cmp_func = compare;
_cmp_jolly = jolly ? jolly : this;
pack();
qsort(_data, last()+1, sizeof(TObject*), compare_ex);
}
bool TArray::is_kind_of(word id) const
{ return class_id() == CLASS_ARRAY || TContainer::is_kind_of(id); }
TArray& objptr2array(TObject* obj)
{
CHECK(obj && obj->is_kind_of(CLASS_ARRAY), "Invalid array pointer");
return static_cast<TArray&>(*obj);
}
///////////////////////////////////////////////////////////
// TString_array
///////////////////////////////////////////////////////////
int TString_array::add(const char* s, int n)
{
if (objptr(n) == NULL)
n = TArray::add(new TToken_string(s), n);
else
row(n) = s;
return n;
}
int TString_array::add(TToken_string* s, int n)
{ return TArray::add(s, n); }
int TString_array::add(const TToken_string& s, int n)
{
if (objptr(n) == NULL)
n = TArray::add(s, n);
else
row(n) = s;
return n;
}
const TString_array& TString_array::operator=(const TString_array& a)
{
destroy();
FOR_EACH_ARRAY_ROW_BACK(a, i, riga)
add(*riga, i);
return *this;
}
// @doc EXTERNAL
// @mfunc Cerca una stringa nell'array
//
// @rdesc Ritorna la posizione nell'array in cui si trova la stringa (-1 se non
// e' stata trovata)
int TString_array::find(
const char* s, // @parm Stringa da cercare
int from) const // @parm Posizione dalla quale cercare la stringa
{
int found = -1;
for (int i = from; i < items(); i++)
if (row(i).compare(s, -1, true) == 0)
{
found = i;
break;
}
return found;
}
HIDDEN int ascending_string(const TObject** o1, const TObject** o2)
{
const TString* s1 = (const TString*)*o1;
const TString* s2 = (const TString*)*o2;
return strcmp(*s1, *s2);
}
HIDDEN int descending_string(const TObject** o1, const TObject** o2)
{
return -ascending_string(o1, o2);
}
void TString_array::sort(bool ascending)
{
TArray::sort(ascending ? ascending_string : descending_string);
}
///////////////////////////////////////////////////////////
// TPointer_array
///////////////////////////////////////////////////////////
// @doc EXTERNAL
// @mfunc Rimuove uno o tutti (default) gli elementi
// @rdesc Ritorna uno dei seguenti parametri:
//
// @flag TRUE | Se l'operazione e' riuscita con successo
// @flag FALSE | Se il numero di elementi e' rimasto invariato
bool TPointer_array::destroy(
int index, // @parm Numero dell'elemento da eliminare (default -1)
bool pack) // @parm Se true richiama la funzione <mf TArray::pack> per compattare gli elementi dell'array (default FALSE)
// @comm Permette la rimozione di uno (index > 0 ) o di tutti (default) gli
// elementi dell'array assegnandone il valore NULL.
// <nl>Nel caso il parametro pack sia TRUE permette di rendere contigui
// tutti gli elementi diversi da NULL tramite la chiamata alla funzione
// <mf TArray::pack>.
{
if (data())
{
if (index < 0)
memset(data(), 0, size() * sizeof(TObject*));
else
remove(index);
}
return TArray::destroy(index, pack);
}
void TPointer_array::copy(const TArray& a)
{
destroy();
if (size() < a.size())
resize(a.size());
// for (int i = a.size()-1; i >= 0; i--)
// add(a.objptr(i), i);
memcpy(data(), a.data(), a.size() * sizeof(TObject*));
_items = a._items;
_next = a._next;
}
int TPointer_array::add(TObject* object, int index)
{
if (index >= 0)
remove(index);
return TArray::add(object, index);
}
int TPointer_array::add(const TObject& object, int index)
{
return add(&(TObject&)object, index);
}
int TPointer_array::insert(const TObject& object, int index, bool force)
{
return TArray::insert(&(TObject&)object, index, force);
}
int TPointer_array::find_long(long value) const
{
int i = 0;
for (i = last(); i >= 0 && get_long(i) != value; i = pred(i));
return i;
}
///////////////////////////////////////////////////////////
// TBit_array
///////////////////////////////////////////////////////////
TBit_array::TBit_array(long size)
: _size(0), _bit(NULL)
{
if (size)
resize(index(size));
}
// @doc EXTERNAL
// @mfunc Copia l'array passato come parametro
void TBit_array::copy(
const TBit_array& ba) // @parm Array da copiare
// @comm Copia il contenuto dell'array passato come parametro.
{
if (_bit)
{
delete _bit;
_bit = NULL;
_size = 0;
}
resize(ba._size-1);
memcpy(_bit, ba._bit, _size);
}
TBit_array::TBit_array(const TBit_array& ba) : _size(0), _bit(NULL)
{ copy(ba); }
TBit_array& TBit_array::operator=(const TBit_array& ba)
{
copy(ba);
return *this;
}
TBit_array::~TBit_array()
{
if (_bit)
delete _bit;
}
// Certified 100%
void TBit_array::set()
{
if (_bit)
memset(_bit, 0xFF, _size);
}
// Certified 100%
void TBit_array::reset()
{
if (_bit)
memset(_bit, 0x0, _size);
}
// Certified 99%
// @doc EXTERNAL
//
// @mfunc Modifica la dimensione dell'array.
void TBit_array::resize(
word size) // @parm Indica la nuova dimensione che deve assumere l'array.
// @comm Alloca la memoria necessaria per contentere i dati della nuova
// dimensione inizializzando a NULL tutti i nuovi elementi aggiunti
// all'array lasciando inalterati, sia in posizione che in
// contenuto gli elementi gia' presenti.
{
word oldsize = _size;
byte* oldbit = _bit;
_size = size+1;
_bit = new byte[_size];
reset();
if (oldsize)
{
memcpy(_bit, oldbit, oldsize);
delete oldbit;
}
}
bool TBit_array::operator[] (long n) const
{
const word i = index(n);
if (i >= _size) return FALSE;
return (_bit[i] & mask(n)) != 0;
}
// Certified 99%
TBit_array& TBit_array::operator|= (const TBit_array& ba)
{
if (_size < ba._size)
resize(ba._size);
for (word i = 0; i < _size; i++)
_bit[i] |= ba._bit[i];
return *this;
}
// Certified 99%
void TBit_array::set(long n)
{
CHECKD(n >= 0, "Can't set a negative bit ", n);
const word i = index(n);
if (i >= _size)
resize(i);
_bit[i] |= mask(n);
}
// Certified 99%
void TBit_array::reset(long n)
{
const word i = index(n);
if (i < _size)
_bit[i] &= ~mask(n);
}
// Certified 99%
void TBit_array::neg(long n)
{
const word i = index(n);
if (i >= _size) resize(i);
_bit[i] ^= mask(n);
}
// Certified 90%
// @doc EXTERNAL
// @mfunc Ritorna il numero di 1 presenti nell'array
//
// @rdesc Numero di 1 trovati.
long TBit_array::ones() const
// @comm Passa tutto l'array di bit e conta quanti degli elementi presenti sono
// settati ad 1.
//
// @xref <mf TBit_array::last_one> <mf TBit_array::first_one>
{
long one = 0;
for (word i = 0; i < _size; i++)
{
const byte b = _bit[i];
if (b)
{
for (byte m = 1; m; m <<= 1)
if (b & m) one++;
}
}
return one;
}
// Certified 90%
// @doc EXTERNAL
// @mfunc Ritorna la posizione dell'ultimo 1 nell'array
//
// @rdesc Ritorna i seguenti valori:
// @flag >0 | Posizione nella quale si trova l'ultimo 1
// @flag -1 | Se non sono presenti bit settati ad 1
long TBit_array::last_one() const
// @comm Cerca all'interno dell'array di bit la posizione dell'ultimo bit
// settato ad 1
//
// @xref <mf TBit_array::first_one> <mf TBit_array::ones>
{
for (word i = _size; i--;)
{
const byte b = _bit[i];
if (b)
{
for (byte j = 8; j--;)
if ((1<<j) & b) return (long(i)<<3) + j;
}
}
return -1;
}
// Certified 90%
// @doc EXTERNAL
// @mfunc Ritorna la posizione del primo 1 nell'array
//
// @rdesc Ritorna i seguenti valori:
//
// @flag >0 | Posizione nella quale si trova il primo 1
// @flag -1 | Se non sono presenti bit settati ad 1
long TBit_array::first_one() const
// @comm Cerca all'interno dell'array di bit la posizione del primo bit
// settato ad 1
//
// @xref <mf TBit_array::last_one> <mf TBit_array::ones>
{
for (word i = 0; i < _size; i++)
{
const byte b = _bit[i];
if (b)
{
for (byte j = 0; j < 8; j++)
if ((1<<j) & b) return (long(i)<<3)+j;
}
}
return -1;
}
bool TBit_array::some_one() const
{
for (word i = 0; i < _size; i++)
if (_bit[i]) return true;
return false;
}
// @doc EXTERNAL
// @mfunc Controlla se si tratta di un oggetto valido
//
// @rdesc Ritorna uno dei seguenti parametri:
//
// @flag TRUE | Se l'array contiene degli elementi
// @flag FALSE | Se l'array e' vuoto
bool TBit_array::ok() const
// @comm Controlla se la dimensione dell'array e' maggiore di 0 e se esistono
// degli elementi diversi da NULL
{
return _bit != NULL && _size > 0;
}
void TBit_array::set(const char* numbers)
{
TToken_string s(numbers, ' ');
s.trim(); s.strip_double_spaces();
FOR_EACH_TOKEN(s, n) if (isdigit(*n))
set(atol(n));
}
void TBit_array::reset(const char* numbers)
{
TToken_string s(numbers, ' ');
s.trim(); s.strip_double_spaces();
FOR_EACH_TOKEN(s, n) if (isdigit(*n))
reset(atol(n));
}
// @doc EXTERNAL
//
// @mfunc Stampa un array
void TBit_array::print_on(
ostream& out) const // @parm Indica l'output sul quale reindirizzare la stampa (funzione standard del C++)
// @comm Stampa tutti gli indici degli elementi diversi da 0
{
const long last = _size<<3;
for (long i = 1; i < last; i++)
if (operator[](i)) out << ' ' << i;
}