By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,696 Members | 2,213 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,696 IT Pros & Developers. It's quick & easy.

Dynamic Arrays

P: n/a
Hi Everyone,

I apologise if this is covered in the FAQ, I did look, but nothing
actually stood out to me as being relative to my subject.

I want to create a 2 dimensional array, a 'array of strings'. I already
know that no individual string will be longer than 50 characters. I just
don't know before run time how many elements of the array will be needed.

I have heard it is possible to dynamically allocate memory for a 2
dimensional array as long as the size of the 2nd element is shown. Is
this correct? And if so could someone post a simple example for me, to
base my own code off.

Thanks

--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
"Materialised" <Ma**********@privacy.net> wrote in message
news:c6************@ID-220437.news.uni-berlin.de...
I want to create a 2 dimensional array, a 'array of strings'. I already
know that no individual string will be longer than 50 characters. I just
don't know before run time how many elements of the array will be needed.

I have heard it is possible to dynamically allocate memory for a 2
dimensional array as long as the size of the 2nd element is shown. Is
this correct? And if so could someone post a simple example for me, to
base my own code off.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char (*arr)[50] = malloc(10 * sizeof *arr);
if (arr)
{
int i;
for (i = 0; i < 10; i++)
{
sprintf(arr[i] "%d", i);
puts(arr[i]);
}
free(arr);
}
}
Nov 14 '05 #2

P: n/a

"Materialised" <Ma**********@privacy.net> wrote in message
news:c6************@ID-220437.news.uni-berlin.de...
Hi Everyone,

I apologise if this is covered in the FAQ, I did look, but nothing
actually stood out to me as being relative to my subject.

I want to create a 2 dimensional array, a 'array of strings'. I already
know that no individual string will be longer than 50 characters. I just
don't know before run time how many elements of the array will be needed.

I have heard it is possible to dynamically allocate memory for a 2
dimensional array as long as the size of the 2nd element is shown. Is
this correct? And if so could someone post a simple example for me, to
base my own code off.


There are several published. I did a googles search in googles for
"array of strings" and came up with several examples. Here is one
posted about one year ago in comp.lang.c

C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct NAME{
char **name;
size_t count;
}NAME;

char *addNAME(NAME *p,const char *name);
void freeNAME(NAME *p);

int main(void)
{
NAME president = {0}; /* initalized zero neccessary for start*/
size_t i;

addNAME(&president,"George Washington");
addNAME(&president,"Abe Lincoln");
puts("Presidents in the array are");
for(i = 0; i < president.count;i++)
printf("\t%s\n",president.name[i]);
freeNAME(&president);
printf("\nAfter freeing the array\n"
"There are %u names in the array\n",president.count);
return 0;
}

char *addNAME(NAME *p, const char *name)
{
char **tmp;
size_t i;

if(!p || !name) return NULL;
i = p->count;
if((tmp = realloc(p->name,(i+1)*sizeof(*p->name))) == NULL)
return NULL;
if((tmp[i] = malloc(strlen(name)+1)) == NULL)
return NULL;
strcpy(tmp[i],name);
p->count++;
p->name = tmp;
return p->name[i];
}

void freeNAME(NAME *p)
{
size_t i;

if(!p) return;
for(i = 0;i < p->count;i++)
free(p->name[i]);
free(p->name);
p->name = NULL;
p->count = 0;
}

Thapani.
Nov 14 '05 #3

P: n/a
In <c6************@ID-220437.news.uni-berlin.de> Materialised <Ma**********@privacy.net> writes:
I apologise if this is covered in the FAQ, I did look, but nothing
actually stood out to me as being relative to my subject.

I want to create a 2 dimensional array, a 'array of strings'. I already
know that no individual string will be longer than 50 characters. I just
don't know before run time how many elements of the array will be needed.

I have heard it is possible to dynamically allocate memory for a 2
dimensional array as long as the size of the 2nd element is shown. Is
this correct?
Yes, you can use a pointer to arrays of that size.
And if so could someone post a simple example for me, to
base my own code off.


You can find the cryptical syntax for declaring a pointer to array in
the FAQ. I'll show the readable approach.

#include <stdlib.h>
#include <string.h>

#define SIZE (50 + 1)
typedef char array_t[SIZE];

int main(int argc, char **argv)
{
array_t *p;
int i;

if (argc == 0) return 0;
p = calloc(argc, sizeof *p); /* or sizeof(array_t) */
if (p == NULL) return EXIT_FAILURE;
for (i = 0; i < argc; i++) strncpy(p[i], argv[i], SIZE - 1);
/* ... */
return 0;
}

If you no longer need the 2-dimensional array at some point in your
program, you can free it with a plain free(p) call. And you can access
individual characters in the array using the p[i][j] syntax (*before*
calling free).

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #4

P: n/a
Dan Pop wrote:
In <c6************@ID-220437.news.uni-berlin.de> Materialised <Ma**********@privacy.net> writes:

I apologise if this is covered in the FAQ, I did look, but nothing
actually stood out to me as being relative to my subject.

I want to create a 2 dimensional array, a 'array of strings'. I already
know that no individual string will be longer than 50 characters. I just
don't know before run time how many elements of the array will be needed.

I have heard it is possible to dynamically allocate memory for a 2
dimensional array as long as the size of the 2nd element is shown. Is
this correct?

Yes, you can use a pointer to arrays of that size.

And if so could someone post a simple example for me, to
base my own code off.

You can find the cryptical syntax for declaring a pointer to array in
the FAQ. I'll show the readable approach.

#include <stdlib.h>
#include <string.h>

#define SIZE (50 + 1)
typedef char array_t[SIZE];

int main(int argc, char **argv)
{
array_t *p;
int i;

if (argc == 0) return 0;
p = calloc(argc, sizeof *p); /* or sizeof(array_t) */
if (p == NULL) return EXIT_FAILURE;
for (i = 0; i < argc; i++) strncpy(p[i], argv[i], SIZE - 1);
/* ... */
return 0;
}

If you no longer need the 2-dimensional array at some point in your
program, you can free it with a plain free(p) call. And you can access
individual characters in the array using the p[i][j] syntax (*before*
calling free).

Dan

Thanks dan that clarified it for me, and thanks to the other posters as
well.

--
------
Materialised

perl -e 'printf "%silto%c%sck%ccodegurus%corg%c", "ma", 58, "mi", 64,
46, 10;'
Nov 14 '05 #5

P: n/a


Materialised wrote:
Hi Everyone,

I apologise if this is covered in the FAQ, I did look, but nothing
actually stood out to me as being relative to my subject.

I want to create a 2 dimensional array, a 'array of strings'. I already
know that no individual string will be longer than 50 characters. I just
don't know before run time how many elements of the array will be needed.

I have heard it is possible to dynamically allocate memory for a 2
dimensional array as long as the size of the 2nd element is shown.

Size of the second dimension , that is . (instead of 2nd element).
Because in C , even a 2-D array is actually implemented as a single-dim.
array and so it needs the II dimension to locate an element.
--
Rakesh Kumar
** Remove nospamplz from my email address for my real email **
Nov 14 '05 #6

P: n/a
Materialised <Ma**********@privacy.net> wrote in message news:<c6************@ID-220437.news.uni-berlin.de>...
Hi Everyone,

I apologise if this is covered in the FAQ, I did look, but nothing
actually stood out to me as being relative to my subject.

I want to create a 2 dimensional array, a 'array of strings'. I already
know that no individual string will be longer than 50 characters. I just
don't know before run time how many elements of the array will be needed.

I have heard it is possible to dynamically allocate memory for a 2
dimensional array as long as the size of the 2nd element is shown. Is
this correct? And if so could someone post a simple example for me, to
base my own code off.

Thanks


If you want to borrow free dynamic-array-of-string code, look at
FreeDOS edlin, which actually uses dynamic-array-of-dynamic-string,
which is even cooler. Anyway, here's the URL:
http://www.ibiblio.org/pub/micro/pc-...ne/edlin21.zip

and the relevant code:

/* defines.h -- standard defines */

#ifndef DEFINES_H
#define DEFINES_H

#include <stddef.h>

typedef void fvoid_t ();

typedef enum capacity
{
default_size,
reserve
} capacity;

#ifndef NPOS
#define NPOS ((size_t)(-1))
#endif

void Nomemory ();

#endif

/* END OF FILE */

/* defines.c -- implementation of functions from defines.h

AUTHOR: Gregory Pietsch

*/

#include <stdio.h>
#include <stdlib.h>
#include "defines.h"

void
Nomemory (void)
{
fputs ("No memory\n", stderr);
abort ();
}

/* END OF FILE */

/* dynarray.h - dynamic array header

*/

#include <stdlib.h>
#include <stdio.h>
#include "defines.h"

#define _VAL(y,x) y ## x
#define _NM(y,x) _VAL(y,x)

#ifdef PROTOS_ONLY

/* types */

typedef struct _NM (TS, _ARRAY_T)
{
T *_Ptr;
size_t _Len, _Res;
} _NM (TS, _ARRAY_T);

_NM (TS, _ARRAY_T) * _NM (TS, _create) (void);
void
_NM (TS, _destroy) (_NM (TS, _ARRAY_T) *);
void
_NM (TS, _ctor) (_NM (TS, _ARRAY_T) *);
void
_NM (TS, _ctor_with_size) (_NM (TS, _ARRAY_T) *, size_t,
capacity);
void
_NM (TS, _copy_ctor) (_NM (TS, _ARRAY_T) *, _NM (TS, _ARRAY_T)
*);
void
_NM (TS, _ctor_from_ptr) (_NM (TS, _ARRAY_T) *, T *, size_t);
void
_NM (TS, _dtor) (_NM (TS, _ARRAY_T) *);
_NM (TS, _ARRAY_T) * _NM (TS, _append) (_NM (TS, _ARRAY_T) *, T *,
size_t,
size_t);
_NM (TS, _ARRAY_T) * _NM (TS, _assign) (_NM (TS, _ARRAY_T) *, T *,
size_t,
size_t);
_NM (TS, _ARRAY_T) * _NM (TS, _insert) (_NM (TS, _ARRAY_T) *, size_t,
T *,
size_t, size_t);
_NM (TS, _ARRAY_T) * _NM (TS, _remove) (_NM (TS, _ARRAY_T) *, size_t,
size_t);
_NM (TS, _ARRAY_T) * _NM (TS, _subarray) (_NM (TS, _ARRAY_T) *,
_NM (TS, _ARRAY_T) *,
size_t,
size_t);
void
_NM (TS, _swap) (_NM (TS, _ARRAY_T) *, _NM (TS, _ARRAY_T) *);
T *
_NM (TS, _get_at) (_NM (TS, _ARRAY_T) *, size_t);
void
_NM (TS, _put_at) (_NM (TS, _ARRAY_T) *, size_t, T *);
T *
_NM (TS, _base) (_NM (TS, _ARRAY_T) *);
size_t
_NM (TS, _length) (_NM (TS, _ARRAY_T) *);
void
_NM (TS, _resize) (_NM (TS, _ARRAY_T) *, size_t, T *);
size_t
_NM (TS, _reserve) (_NM (TS, _ARRAY_T) *);
void
_NM (TS, _set_reserve) (_NM (TS, _ARRAY_T) *, size_t);

#else

#ifndef Tctor
#define Tctor(x)
#endif
#ifndef Tdtor
#define Tdtor(x)
#endif
#ifndef Tassign
#define Tassign(x,y) (*(x) = *(y))
#endif

/* functions */

static void _NM (TS, _Xinv) (void)
{
fputs ("Invalid dynamic array argument\n", stderr);
abort ();
}

static void _NM (TS, _Xlen) (void)
{
fputs ("Length error: dynamic array too long\n", stderr);
abort ();
}

static void _NM (TS, _Xran) (void)
{
fputs ("Out of range: invalid dynamic array position\n", stderr);
abort ();
}

static void _NM (TS, _Tidy) (_NM (TS, _ARRAY_T) * this, int
_Constructed)
{
size_t i;

if (_Constructed && this->_Ptr != 0)
{
for (i = 0; i < this->_Len; i++)
Tdtor (this->_Ptr + i);
free (this->_Ptr);
}
this->_Len = 0;
this->_Ptr = 0;
this->_Res = 0;
}

static void _NM (TS, _Grow) (_NM (TS, _ARRAY_T) * this, size_t _N, T *
_S,
int _Trim)
{
size_t _Os = this->_Ptr == 0 ? 0 : this->_Res;
size_t _I, _M, _R;
T *_Np;

if (_N == 0)
{
if (_Trim)
_NM (TS, _Tidy) (this, 1);
}
else if (_N == _Os || _N < _Os && !_Trim);
else
{
_M = this->_Ptr == 0 && _N < this->_Res ? this->_Res : _N;
_Np = calloc (_M, sizeof (T));
if (_Np == 0)
Nomemory (); /* no memory */
for (_I = 0; _I < _M; _I++)
Tctor (_Np + _I);
_R = _M;
_M = _N < this->_Len ? _N : this->_Len;
for (_I = 0; _I < _M; ++_I)
Tassign (_Np + _I, this->_Ptr + _I);
if (_S != 0)
for (; _I < this->_Res; ++_I)
Tassign (_Np + _I, _S);
_NM (TS, _Tidy) (this, 1);
this->_Ptr = _Np;
this->_Res = _R;
}
this->_Len = _N;
}

_NM (TS, _ARRAY_T) * _NM (TS, _create) (void)
{
_NM (TS, _ARRAY_T) * x = malloc (sizeof (_NM (TS, _ARRAY_T)));

if (x == 0)
Nomemory ();
_NM (TS, _Tidy) (x, 0);
return x;
}

void _NM (TS, _destroy) (_NM (TS, _ARRAY_T) * x)
{
_NM (TS, _Tidy) (x, 1);
free (x);
}

void _NM (TS, _ctor) (_NM (TS, _ARRAY_T) * this)
{
_NM (TS, _Tidy) (this, 0);
}

void _NM (TS, _ctor_with_size) (_NM (TS, _ARRAY_T) * this, size_t n,
capacity c)
{
_NM (TS, _Tidy) (this, 0);
this->_Res = n;
if (c == default_size)
_NM (TS, _Grow) (this, n, 0, 0);
}

void _NM (TS, _copy_ctor) (_NM (TS, _ARRAY_T) * this, _NM (TS,
_ARRAY_T) * x)
{
size_t i;

_NM (TS, _Tidy) (this, 0);
_NM (TS, _Grow) (this, _NM (TS, _length) (x), 0, 0);
for (i = 0; i < this->_Len; i++)
Tassign (this->_Ptr + i, x->_Ptr + i);
}

void _NM (TS, _ctor_from_ptr) (_NM (TS, _ARRAY_T) * this, T * s,
size_t n)
{
if (s == 0)
_NM (TS, _Xinv) ();
_NM (TS, _Tidy) (this, 0);
_NM (TS, _assign) (this, s, n, 1);
}

void _NM (TS, _dtor) (_NM (TS, _ARRAY_T) * this)
{
_NM (TS, _Tidy) (this, 1);
}

_NM (TS, _ARRAY_T) * _NM (TS, _append) (_NM (TS, _ARRAY_T) * this, T *
_S,
size_t _N, size_t _D)
{
size_t _I;

if (NPOS - this->_Len <= _N)
_NM (TS, _Xlen) ();
_I = this->_Len;
for (_NM (TS, _Grow) (this, _N += _I, 0, 0); _I < _N; ++_I, _S +=
_D)
Tassign (this->_Ptr + _I, _S);
return this;
}

_NM (TS, _ARRAY_T) * _NM (TS, _assign) (_NM (TS, _ARRAY_T) * this, T *
_S,
size_t _N, size_t _D)
{
size_t _I;

_NM (TS, _Grow) (this, _N, 0, 1);
for (_I = 0; _I < _N; ++_I, _S += _D)
Tassign (this->_Ptr + _I, _S);
return this;
}

_NM (TS, _ARRAY_T) * _NM (TS, _insert) (_NM (TS, _ARRAY_T) * this,
size_t _P,
T * _S, size_t _N, size_t _D)
{
size_t _I;

if (this->_Len < _P)
_NM (TS, _Xran) ();
if (NPOS - this->_Len <= _N)
_NM (TS, _Xlen) ();
if (0 < _N)
{
_I = this->_Len - _P;
for (_NM (TS, _Grow) (this, _N + this->_Len, 0, 0); 0 < _I;)
{
--_I;
Tassign (this->_Ptr + (_P + _N + _I), this->_Ptr + (_P +
_I));
}
for (_I = 0; _I < _N; ++_I, _S += _D)
Tassign (this->_Ptr + (_P + _I), _S);
}
return this;
}

_NM (TS, _ARRAY_T) * _NM (TS, _remove) (_NM (TS, _ARRAY_T) * this,
size_t _P,
size_t _N)
{
size_t _M, _I;

if (this->_Len < _P)
_NM (TS, _Xran) ();
if (this->_Len - _P < _N)
_N = this->_Len - _P;
if (0 < _N)
{
_M = this->_Len - _P - _N;
for (_I = 0; _I < _M; ++_I)
Tassign (this->_Ptr + (_P + _I), this->_Ptr + (_P + _I + _N));
_NM (TS, _Grow) (this, this->_Len - _N, 0, 0);
}
return this;
}

_NM (TS, _ARRAY_T) * _NM (TS, _subarray) (_NM (TS, _ARRAY_T) * this,
_NM (TS, _ARRAY_T) * _X,
size_t _P,
size_t _N)
{
if (this->_Len < _P)
_NM (TS, _Xran) ();
if (this->_Len - _P < _N)
_N = this->_Len - _P;
return this == _X ? (_NM (TS, _remove) (this, _P + _N, NPOS),
_NM (TS, _remove) (this, 0, _P))
: _NM (TS, _assign) (_X, this->_Ptr + _P, _N, 1);
}

void _NM (TS, _swap) (_NM (TS, _ARRAY_T) * this, _NM (TS, _ARRAY_T) *
_X)
{
T *_Tp;
size_t _T;

_Tp = this->_Ptr;
this->_Ptr = _X->_Ptr;
_X->_Ptr = _Tp;
_T = this->_Len;
this->_Len = _X->_Len;
_X->_Len = _T;
_T = this->_Res;
this->_Res = _X->_Res;
_X->_Res = _T;
}

T *_NM (TS, _get_at) (_NM (TS, _ARRAY_T) * this, size_t _I)
{
if (this->_Len <= _I)
_NM (TS, _Xran) ();
return this->_Ptr + _I;
}

void _NM (TS, _put_at) (_NM (TS, _ARRAY_T) * this, size_t _I, T * _X)
{
if (this->_Len < _I)
_NM (TS, _Xran) ();
else if (this->_Len == _I)
_NM (TS, _append) (this, _X, 1, 1);
else
Tassign (this->_Ptr + _I, _X);
}

T *_NM (TS, _base) (_NM (TS, _ARRAY_T) * this)
{
return this->_Len != 0 ? this->_Ptr : 0;
}

size_t _NM (TS, _length) (_NM (TS, _ARRAY_T) * this)
{
return this->_Len;
}

void _NM (TS, _resize) (_NM (TS, _ARRAY_T) * this, size_t _N, T * _X)
{
_NM (TS, _Grow) (this, _N, _X, 1);
}

size_t _NM (TS, _reserve) (_NM (TS, _ARRAY_T) * this)
{
return this->_Res;
}

void _NM (TS, _set_reserve) (_NM (TS, _ARRAY_T) * this, size_t _R)
{
if (this->_Ptr == 0)
this->_Res = _R;
}

#endif

#undef _NM
#undef _VAL

/* END OF FILE */

/* dynamic string function header

AUTHOR: Gregory Pietsch
*/

#ifndef DYNSTR_H
#define DYNSTR_H

#include "defines.h"

typedef struct STRING_T
{
char *ptr;
size_t len, res;
} STRING_T;

/* exported functions */

void DSctor (STRING_T * this);
void DSctor_with_size (STRING_T * this, size_t n, capacity c);
void DSdtor (STRING_T * this);
STRING_T *DScreate (void);
void DSdestroy (STRING_T * this);
STRING_T *DSappendchar (STRING_T * this, int c, size_t nr);
STRING_T *DSappendcstr (STRING_T * this, char *s, size_t ns);
STRING_T *DSappend (STRING_T * this, STRING_T * str, size_t pos,
size_t ns);
STRING_T *DSassignchar (STRING_T * this, int c, size_t n);
STRING_T *DSassigncstr (STRING_T * this, char *s, size_t n);
STRING_T *DSassign (STRING_T * this, STRING_T * str, size_t pos,
size_t ns);
STRING_T *DSinsertchar (STRING_T * this, size_t p0, int c, size_t nr);
STRING_T *DSinsertcstr (STRING_T * this, size_t p0, char *s, size_t
ns);
STRING_T *DSinsert (STRING_T * this, size_t p0, STRING_T * str, size_t
pos,
size_t ns);
STRING_T *DSremove (STRING_T * this, size_t p0, size_t nr);
STRING_T *DSreplacechar (STRING_T * this, size_t p0, size_t n0, int c,
size_t nr);
STRING_T *DSreplacecstr (STRING_T * this, size_t p0, size_t n0, char
*s,
size_t ns);
STRING_T *DSreplace (STRING_T * this, size_t p0, size_t n0, STRING_T *
str,
size_t pos, size_t ns);
int DSget_at (STRING_T * this, size_t p0);
void DSput_at (STRING_T * this, size_t p0, int c);
size_t DScopy (STRING_T * this, char *s, size_t n, size_t p0);
size_t DSfind (STRING_T * this, char *s, size_t p0, size_t n);
size_t DSrfind (STRING_T * this, char *s, size_t p0, size_t n);
size_t DSfind_first_of (STRING_T * this, char *s, size_t p0, size_t
n);
size_t DSfind_last_of (STRING_T * this, char *s, size_t p0, size_t n);
size_t DSfind_first_not_of (STRING_T * this, char *s, size_t p0,
size_t n);
size_t DSfind_last_not_of (STRING_T * this, char *s, size_t p0, size_t
n);
int DScomparechar (STRING_T * this, int c, size_t p0, size_t ns);
int DScomparecstr (STRING_T * this, char *s, size_t p0, size_t ns);
int DScompare (STRING_T * this, STRING_T * str, size_t p0, size_t ns);
char *DScstr (STRING_T * this);
size_t DSlength (STRING_T * this);
void DSresize (STRING_T * this, size_t n, int c);
size_t DSreserve (STRING_T * this);
void DSset_reserve (STRING_T * this, size_t n);
STRING_T *DSsubstr (STRING_T * this, size_t p, size_t n);

#define T STRING_T
#define TS DAS
#define Tassign(x,y) DSassign(x,y,0,NPOS)
#define Tctor(x) DSctor(x)
#define Tdtor(x) DSdtor(x)
#define PROTOS_ONLY
#include "dynarray.h"
#undef T
#undef TS
#undef Tassign
#undef Tctor
#undef Tdtor
#undef PROTOS_ONLY
#endif

/* END OF FILE */

/* dynstr.c -- dynamic string functions

AUTHOR: Gregory Pietsch

*/

/* includes */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "defines.h"
#include "dynstr.h"

/* macros */

#define MIN_SIZE 31

/* typedefs */

/* functions */

static void
DStidy (STRING_T * this, int constructed)
{
if (constructed && this->ptr)
free (this->ptr);
this->ptr = 0;
this->len = 0;
this->res = 0;
}

static int
DSgrow (STRING_T * this, size_t n, int trim)
{
size_t osize = this->ptr == 0 ? 0 : this->res;
size_t size;
char *s;

if (n == 0)
{
if (trim && MIN_SIZE < osize)
DStidy (this, 1);
else if (this->ptr)
this->ptr[this->len = 0] = '\0';
return 0;
}
else if (n == osize || n < osize && !trim)
return 1;
else
{
size = this->ptr == 0 && n < this->res ? this->res : n;
if ((size |= MIN_SIZE) == NPOS)
--size;
if ((s = (char *) realloc (this->ptr, size + 1)) == 0
&& (s = (char *) realloc (this->ptr, (size = n) + 1)) == 0)
Nomemory ();
this->ptr = s;
this->res = size;
return 1;
}
}

static void
DSxlen (void)
{
fputs ("string too long\n", stderr);
abort ();
}

static void
DSxran (void)
{
fputs ("invalid string position\n", stderr);
abort ();
}

/* exported functions */

void
DSctor (STRING_T * this)
{
DStidy (this, 0);
}

void
DSctor_with_size (STRING_T * this, size_t n, capacity c)
{
DStidy (this, 0);
this->res = n;
if (c == default_size)
DSassignchar (this, '\0', n);
}

void
DSdtor (STRING_T * this)
{
DStidy (this, 1);
}

STRING_T *
DScreate (void)
{
STRING_T *this = malloc (sizeof (STRING_T));

if (this == 0)
Nomemory ();
DSctor (this);
return this;
}

void
DSdestroy (STRING_T * this)
{
DSdtor (this);
free (this);
}

STRING_T *
DSappendchar (STRING_T * this, int c, size_t nr)
{
size_t n;

if (NPOS - this->len <= nr)
DSxlen ();
if (0 < nr && DSgrow (this, n = this->len + nr, 0))
{
memset (this->ptr + this->len, c, nr);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSappendcstr (STRING_T * this, char *s, size_t ns)
{
size_t n;

if (ns == NPOS)
ns = strlen (s);
if (NPOS - this->len <= ns)
DSxlen ();
if (0 < ns && DSgrow (this, n = this->len + ns, 0))
{
memcpy (this->ptr + this->len, s, ns);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSappend (STRING_T * this, STRING_T * str, size_t pos, size_t ns)
{
size_t n;

if (DSlength (str) < pos)
DSxran ();
n = DSlength (str) - pos;
if (n < ns)
ns = n;
if (NPOS - this->len <= ns)
DSxlen ();
if (0 < ns && DSgrow (this, n = this->len + ns, 0))
{
memcpy (this->ptr + this->len, DScstr (str) + pos, ns);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSassignchar (STRING_T * this, int c, size_t n)
{
if (n == NPOS)
DSxlen ();
if (DSgrow (this, n, 1))
{
memset (this->ptr, c, n);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSassigncstr (STRING_T * this, char *s, size_t n)
{
if (n == NPOS)
n = strlen (s);
if (DSgrow (this, n, 1))
{
memcpy (this->ptr, s, n);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSassign (STRING_T * this, STRING_T * str, size_t pos, size_t ns)
{
size_t n;

if (DSlength (str) < pos)
DSxran ();
n = DSlength (str) - pos;
if (ns < n)
n = ns;
if (this == str)
{
DSremove (this, pos + n, NPOS);
DSremove (this, 0, pos);
}
else if (DSgrow (this, n, 1))
{
memcpy (this->ptr, DScstr (str) + pos, n);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSinsertchar (STRING_T * this, size_t p0, int c, size_t nr)
{
size_t n;

if (this->len < p0)
DSxran ();
if (NPOS - this->len <= nr)
DSxlen ();
if (0 < nr && DSgrow (this, n = this->len + nr, 0))
{
memmove (this->ptr + (p0 + nr), this->ptr + p0, this->len - p0);
memset (this->ptr + p0, c, nr);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSinsertcstr (STRING_T * this, size_t p0, char *s, size_t ns)
{
size_t n;

if (this->len < p0)
DSxran ();
if (ns == NPOS)
ns = strlen (s);
if (NPOS - this->len <= ns)
DSxlen ();
if (0 < ns && DSgrow (this, n = this->len + ns, 0))
{
memmove (this->ptr + (p0 + ns), this->ptr + p0, this->len - p0);
memcpy (this->ptr + p0, s, ns);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSinsert (STRING_T * this, size_t p0, STRING_T * str, size_t pos,
size_t ns)
{
size_t n;

if (this->len < p0 || DSlength (str) < pos)
DSxran ();
n = DSlength (str) - pos;
if (n < ns)
ns = n;
if (NPOS - this->len <= ns)
DSxlen ();
if (0 < ns && DSgrow (this, n = this->len + ns, 0))
{
memmove (this->ptr + (p0 + ns), this->ptr + p0, this->len - p0);
memcpy (this->ptr + p0, DScstr (str) + pos, ns);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSremove (STRING_T * this, size_t p0, size_t nr)
{
size_t n;

if (this->len < p0)
DSxran ();
if (this->len - p0 < nr)
nr = this->len - p0;
if (0 < nr)
{
memmove (this->ptr + p0, this->ptr + (p0 + nr), this->len - p0 -
nr);
n = this->len - nr;
if (DSgrow (this, n, 0))
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSreplacechar (STRING_T * this, size_t p0, size_t n0, int c, size_t
nr)
{
size_t n, nm;

if (this->len < p0)
DSxran ();
if (this->len - p0 < n0)
n0 = this->len - p0;
if (NPOS - nr <= this->len - n0)
DSxlen ();
nm = this->len - n0 - p0;
if (nr < n0)
memmove (this->ptr + (p0 + nr), this->ptr + (p0 + n0), nm);
if ((0 < nr || 0 < n0) && DSgrow (this, n = this->len + nr - n0, 0))
{
if (n0 < nr)
memmove (this->ptr + (p0 + nr), this->ptr + (p0 + n0), nm);
memset (this->ptr + p0, c, nr);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSreplacecstr (STRING_T * this, size_t p0, size_t n0, char *s, size_t
ns)
{
size_t n, nm;

if (this->len < p0)
DSxran ();
if (ns == NPOS)
ns = strlen (s);
if (NPOS - ns <= this->len - n0)
DSxlen ();
nm = this->len - n0 - p0;
if (ns < n0)
memmove (this->ptr + (p0 + ns), this->ptr + (p0 + n0), nm);
if ((0 < ns || 0 < n0) && DSgrow (this, n = this->len + ns - n0, 0))
{
if (n0 < ns)
memmove (this->ptr + (p0 + ns), this->ptr + (p0 + n0), nm);
memcpy (this->ptr + p0, s, ns);
this->ptr[this->len = n] = '\0';
}
return this;
}

STRING_T *
DSreplace (STRING_T * this, size_t p0, size_t n0, STRING_T * str,
size_t pos, size_t ns)
{
size_t n, nm;

if (this->len < p0 || DSlength (str) < pos)
DSxran ();
n = DSlength (str) - pos;
if (n < ns)
ns = n;
if (NPOS - ns <= this->len - n0)
DSxlen ();
nm = this->len - n0 - p0;
if (ns < n0)
memmove (this->ptr + (p0 + ns), this->ptr + (p0 + n0), nm);
if ((0 < ns || 0 < n0) && DSgrow (this, n = this->len + ns - n0, 0))
{
if (n0 < ns)
memmove (this->ptr + (p0 + ns), this->ptr + (p0 + n0), nm);
memcpy (this->ptr + p0, DScstr (str) + pos, ns);
this->ptr[this->len = n] = '\0';
}
return this;
}

int
DSget_at (STRING_T * this, size_t p0)
{
if (this->len <= p0)
DSxran ();
return this->ptr[p0];
}

void
DSput_at (STRING_T * this, size_t p0, int c)
{
if (this->len < p0)
DSxran ();
else if (this->len == p0)
DSappendchar (this, c, 1);
else
this->ptr[p0] = c;
}

size_t
DScopy (STRING_T * this, char *s, size_t n, size_t p0)
{
if (this->len < p0)
DSxran ();
if (this->len - p0 < n)
n = this->len - p0;
memcpy (s, this->ptr + p0, n);
return n;
}

size_t
DSfind (STRING_T * this, char *s, size_t p0, size_t n)
{
size_t nmax;
char *t, *u;

if (n == 0 || n == NPOS && (n = strlen (s)) == 0)
return 0;
if (p0 < this->len && n <= (nmax = this->len - p0))
{
for (nmax -= n - 1, u = this->ptr + p0;
(t = (char *) memchr (u, *s, nmax)) != 0;
nmax -= t - u + 1, u = t + 1)
if (memcmp (t, s, n) == 0)
return t - this->ptr;
}
return NPOS;
}

size_t
DSrfind (STRING_T * this, char *s, size_t p0, size_t n)
{
char *t;

if (n == 0 || n == NPOS && (n = strlen (s)) == 0)
return 0;
if (n <= this->len)
for (t = this->ptr + (p0 < this->len - n ? p0 : this->len - n);;
--t)
if (*t == *s && memcmp (t, s, n) == 0)
return t - this->ptr;
else if (t == this->ptr)
break;
return NPOS;
}

size_t
DSfind_first_of (STRING_T * this, char *s, size_t p0, size_t n)
{
char *t, *u;

if (n == 0 || n == NPOS && (n = strlen (s)) == 0)
return 0;
if (p0 < this->len)
{
u = this->ptr + this->len;
for (t = this->ptr + p0; t < u; t++)
if (memchr (s, *t, n) != 0)
return t - this->ptr;
}
return NPOS;
}

size_t
DSfind_last_of (STRING_T * this, char *s, size_t p0, size_t n)
{
char *t;

if (n == 0 || n == NPOS && (n = strlen (s)) == 0)
return 0;
if (0 < this->len)
for (t = this->ptr + (p0 < this->len ? p0 : this->len - 1);; t--)
if (memchr (s, *t, n) != 0)
return t - this->ptr;
else if (t == this->ptr)
break;
return NPOS;
}

size_t
DSfind_first_not_of (STRING_T * this, char *s, size_t p0, size_t n)
{
char *t, *u;

if (n == 0 || n == NPOS && (n = strlen (s)) == 0)
return 0;
if (p0 < this->len)
{
u = this->ptr + this->len;
for (t = this->ptr + p0; t < u; t++)
if (memchr (s, *t, n) == 0)
return t - this->ptr;
}
return NPOS;
}

size_t
DSfind_last_not_of (STRING_T * this, char *s, size_t p0, size_t n)
{
char *t;

if (n == 0 || n == NPOS && (n = strlen (s)) == 0)
return 0;
if (0 < this->len)
for (t = this->ptr + (p0 < this->len ? p0 : this->len - 1);; t--)
if (memchr (s, *t, n) == 0)
return t - this->ptr;
else if (t == this->ptr)
break;
return NPOS;
}

int
DScomparechar (STRING_T * this, int c, size_t p0, size_t ns)
{
size_t n;
char *s, *t;

if (this->len < p0)
DSxran ();
n = this->len - p0;
for (s = this->ptr + p0, t = s + (n < ns ? n : ns); s < t; s++)
if (*s != c)
return (*(unsigned char *) s < (unsigned char) c ? -1 : 1);
return (n < ns ? -1 : n > ns);
}

int
DScomparecstr (STRING_T * this, char *s, size_t p0, size_t ns)
{
size_t n;
int ans;

if (this->len < p0)
DSxran ();
n = this->len - p0;
if (ns == NPOS)
ns = strlen (s);
ans = memcmp (this->ptr + p0, s, n < ns ? n : ns);
return ans ? ans : n < ns ? -1 : n > ns;
}

int
DScompare (STRING_T * this, STRING_T * str, size_t p0, size_t ns)
{
size_t n;
int ans;

if (this->len < p0)
DSxran ();
n = this->len - p0;
if (DSlength (str) < ns)
ns = DSlength (str);
ans = memcmp (this->ptr + p0, DScstr (str), n < ns ? n : ns);
return ans ? ans : n < ns ? -1 : n > ns;
}

char *
DScstr (STRING_T * this)
{
return this->ptr ? this->ptr : "";
}

size_t
DSlength (STRING_T * this)
{
return this->len;
}

void
DSresize (STRING_T * this, size_t n, int c)
{
if (n < this->len)
DSremove (this, n, NPOS);
else
DSappendchar (this, c, n - this->len);
}

size_t
DSreserve (STRING_T * this)
{
return this->res;
}

void
DSset_reserve (STRING_T * this, size_t n)
{
if (this->ptr == 0)
this->res = n;
}

STRING_T *
DSsubstr (STRING_T * this, size_t p, size_t n)
{
STRING_T *s = DScreate ();

DSassign (s, this, p, n);
return s;
}

#define T STRING_T
#define TS DAS
#define Tassign(x,y) DSassign(x,y,0,NPOS)
#define Tctor(x) DSctor(x)
#define Tdtor(x) DSdtor(x)
#undef PROTOS_ONLY
#include "dynarray.h"
#undef T
#undef TS
#undef Tassign
#undef Tctor
#undef Tdtor

/* END OF FILE */

Gregory Pietsch
Nov 14 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.