char **pStrings = 0; // массив строк (обратите внимание на две звездочки **)
int str_count = 0; // количество элементов в массиве
void AddString (const char *str)
{
char **newStrings = new char* [str_count+1];
memcpy (newStrings, pStrings, sizeof(char*)*str_count);
delete [] pStrings;
pStrings = newStrings;
pStrings[str_count] = new char [strlen (str)+1];
strcpy (pStrings[str_count], str);
str_count++;
}
Массив строк (char*)
Сабж. Как мне объявить массив строк? А потом работать с ними. помогите. поскольку я что-то совсем не соображу...
Цитата:
char [n][m];
где n к-ство строк, а m к-ство символов в строке...
Ты бы определился, тебе массив статических или динамических строк нужен-то... и сишный или цппшный? И не динамическим ли должен быть сам массив? Определяйся, подскажу.
Код:
string *pStrings=new string[n];
или:
Код:
char *p[]={"Hello","People"};
Мне нужен для начала статический массив строк (лучше конечно динамический). причем чтобы каждый элемент массива - это строка с динамическим размером. Чтобы было как в CStringArray - только используя чистый сишник.
Ещё одно уточнение - тебе нужен именно массив или список сгодится?
Вариант для массива такой -
Код:
и т. п.
Такой подход будет ОЧЕНЬ МЕДЛЕННО добавлять и удалять строки, т. к. при каждом добавлении весь массив нужно копировать, при удалении тоже, зато доступ будет произвольный - чтобы получить n-ю строку, нужно просто написать pStrings[n].
Если быстродействие при добавлении/удалении элементов критично, лучше использовать список. Но тогда будет последовательный доступ - чтобы получить n-ю строку, нужно обойти все начиная с первой.
А вообще повторяюсь еще раз: лучше один раз написать индексированную коллекцию и юзать ее вдоль и поперек :)
Код:
char *str = new char[10];
str = "text";
str = "text";
Вторая строка приводит к "утере" памяти, выделенной в первой строке.
Надо писать strcpy (str, "text");
Код:
const int SIZE = 3;
const int MAX_SIZE = 32;
char **strings = new char* [SIZE];
for(int i=0; i<SIZE; i++)
strings = new char[MAX_SIZE];
strcpy(strings[0], "alfa");
strcpy(strings[1], "beta");
strcpy(strings[2], "gamma");
char *st = new char[sizeof("theta")+1];
strcpy(st, "theta");
if(strlen(st)<MAX_SIZE)
strcpy(strings[0], st);
else
throw exception("Длина строки превышает макс.размер");
// ...
// ...
for(i=0; i<SIZE; i++)
delete[] strings;
delete[] strings;
const int MAX_SIZE = 32;
char **strings = new char* [SIZE];
for(int i=0; i<SIZE; i++)
strings = new char[MAX_SIZE];
strcpy(strings[0], "alfa");
strcpy(strings[1], "beta");
strcpy(strings[2], "gamma");
char *st = new char[sizeof("theta")+1];
strcpy(st, "theta");
if(strlen(st)<MAX_SIZE)
strcpy(strings[0], st);
else
throw exception("Длина строки превышает макс.размер");
// ...
// ...
for(i=0; i<SIZE; i++)
delete[] strings;
delete[] strings;
s = realloc( s, blocksize );
чтобы твоя строка приняла размер blocksize, вот тебе и динамический размер строки, а все остальное сказано уже выше
Это, во-первых, проще всего.
Во-вторых, работает быстрее )))
Спасибо всем за ответы.
З.Ы. мне кстати идея (но это не чисто его идея, тут подобное уже ранее высказывалось, но все-таки) _north_ очень понравилась! Но я буду использовать все-таки списки )
Если минимальным элементом списка будет один символ, то это не самая хорошая идея
А как тогда лучше?
Код:
typedef struct {
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
UINT iPrevFree;
bool bAlloc;
bool bFree;
} ANSI_STRING, *PANSI_STRING;
typedef struct
{
int iNum;
int iFree;
ANSI_STRING as[1];
}STRINGARRAY,*PSTRINGARRAY;
PSTRINGARRAY init(int);
UINT add(PSTRINGARRAY,char*);
void remove(PSTRINGARRAY,UINT);
char * get(PSTRINGARRAY,UINT);
PSTRINGARRAY init(int iNum)
{
PSTRINGARRAY p=(PSTRINGARRAY)new char[iNum*sizeof(ANSI_STRING)+sizeof(int)*2];
memset(p,0,iNum*sizeof(ANSI_STRING)+sizeof(int)*2);
p->iNum=iNum;
for(UINT u=0;u<iNum;u++)
p->as.iPrevFree=u+1;
return p;
};
UINT add(PSTRINGARRAY p,char *psz)
{
UINT iFree=p->iFree;
if(iFree>=p->iNum)
return (UINT)-1;
PANSI_STRING pasFree=&p->as[iFree];
int iLen=strlen(psz);
if(pasFree->MaximumLength<iLen)
{
if(pasFree->bAlloc) delete [] pasFree->Buffer;
pasFree->Buffer=new char[iLen+1];
pasFree->MaximumLength=iLen;
pasFree->bAlloc=TRUE;
};
pasFree->bFree=FALSE;
strcpy(pasFree->Buffer,psz);
pasFree->Length=iLen;
p->iFree=pasFree->iPrevFree;
return iFree;
};
void remove(PSTRINGARRAY p,UINT i)
{
if(i>=p->iNum || i==p->iFree)
return;
PANSI_STRING pas=&p->as;
if(pas->bFree)
return;
pas->bFree=TRUE;
pas->iPrevFree=p->iFree;
p->iFree=i;
}
char * get(PSTRINGARRAY p,UINT i)
{
if(i>=p->iNum || i==p->iFree)
return NULL;
PANSI_STRING pas=&p->as;
if(pas->bFree)
return NULL;
return pas->Buffer;
};
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
UINT iPrevFree;
bool bAlloc;
bool bFree;
} ANSI_STRING, *PANSI_STRING;
typedef struct
{
int iNum;
int iFree;
ANSI_STRING as[1];
}STRINGARRAY,*PSTRINGARRAY;
PSTRINGARRAY init(int);
UINT add(PSTRINGARRAY,char*);
void remove(PSTRINGARRAY,UINT);
char * get(PSTRINGARRAY,UINT);
PSTRINGARRAY init(int iNum)
{
PSTRINGARRAY p=(PSTRINGARRAY)new char[iNum*sizeof(ANSI_STRING)+sizeof(int)*2];
memset(p,0,iNum*sizeof(ANSI_STRING)+sizeof(int)*2);
p->iNum=iNum;
for(UINT u=0;u<iNum;u++)
p->as.iPrevFree=u+1;
return p;
};
UINT add(PSTRINGARRAY p,char *psz)
{
UINT iFree=p->iFree;
if(iFree>=p->iNum)
return (UINT)-1;
PANSI_STRING pasFree=&p->as[iFree];
int iLen=strlen(psz);
if(pasFree->MaximumLength<iLen)
{
if(pasFree->bAlloc) delete [] pasFree->Buffer;
pasFree->Buffer=new char[iLen+1];
pasFree->MaximumLength=iLen;
pasFree->bAlloc=TRUE;
};
pasFree->bFree=FALSE;
strcpy(pasFree->Buffer,psz);
pasFree->Length=iLen;
p->iFree=pasFree->iPrevFree;
return iFree;
};
void remove(PSTRINGARRAY p,UINT i)
{
if(i>=p->iNum || i==p->iFree)
return;
PANSI_STRING pas=&p->as;
if(pas->bFree)
return;
pas->bFree=TRUE;
pas->iPrevFree=p->iFree;
p->iFree=i;
}
char * get(PSTRINGARRAY p,UINT i)
{
if(i>=p->iNum || i==p->iFree)
return NULL;
PANSI_STRING pas=&p->as;
if(pas->bFree)
return NULL;
return pas->Buffer;
};
Это С++, а на нем можно было и значительно красивее сделать, если не нравятся стандаотные строки и контейнеры.
можно список строк, можно массив строк.
просто когда у тебя каждый символ - элемент списка, у тебя на эти все строки уходит в 9 раз больше памяти, чем нужно.
Единственно, когда может хорошо пройти вариант "один символ - один узел", это если тебе надо операции с фрагментами в отдельных строках, ну, там удалить фрагмент, вставить в середину, прицепить к другой строке...
Если поиск/сортировка по строкам, удобнее чтобы строка была сплошным блоком
"список строк", выбор контейнера: CN = <мой контейнер> = 0;
доб. строку: loadln( <строка> ); удал. строку по номеру: deleteln(<ном.>); получ. указатель на начало строки: getpln( <номер> );
вроде пашет
Код:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct line{
struct line *up, *dn;
char * s;
} line;
line *CN;
void loadln(char *s)
{
line *tmp, *A = calloc(1, sizeof(line));
int l = strlen(s);
A->s = malloc(l);
strcpy(A->s, s, l);
if (!CN)
{ CN = A; return; }
tmp = CN;
while (tmp->dn)
tmp = tmp->dn;
tmp->dn = A;
tmp->dn->dn = 0;
tmp->dn->up = tmp;
}
line* getpln(int n)
{
int i;
line *tmp = CN;
for (i = 0; i < n; ++i)
if (tmp->dn)
tmp = tmp->dn;
else
return 0;
return tmp;
}
int deleteln(int n)
{
line *tmp = getpln(n);
if (tmp) {
if (! tmp->up)
CN = tmp->dn;
else
tmp->up->dn = tmp->dn;
if (tmp->dn) tmp->dn->up = tmp->up;
free(tmp);
return n;
}
else
return 0;
}
main()
{
line *tmp, *my_lines = CN = 0;
int i;
char s;
loadln( "Hello World" );
loadln( "Microsoft .NET Framework, " );
loadln( "COBOL" );
deleteln(0);
for (i = 0; i < 5; ++i)
if ((tmp = getpln(i)) && tmp->s)
puts(tmp->s);
else
puts("<no line here>");
}
#include <string.h>
#include <stdlib.h>
typedef struct line{
struct line *up, *dn;
char * s;
} line;
line *CN;
void loadln(char *s)
{
line *tmp, *A = calloc(1, sizeof(line));
int l = strlen(s);
A->s = malloc(l);
strcpy(A->s, s, l);
if (!CN)
{ CN = A; return; }
tmp = CN;
while (tmp->dn)
tmp = tmp->dn;
tmp->dn = A;
tmp->dn->dn = 0;
tmp->dn->up = tmp;
}
line* getpln(int n)
{
int i;
line *tmp = CN;
for (i = 0; i < n; ++i)
if (tmp->dn)
tmp = tmp->dn;
else
return 0;
return tmp;
}
int deleteln(int n)
{
line *tmp = getpln(n);
if (tmp) {
if (! tmp->up)
CN = tmp->dn;
else
tmp->up->dn = tmp->dn;
if (tmp->dn) tmp->dn->up = tmp->up;
free(tmp);
return n;
}
else
return 0;
}
main()
{
line *tmp, *my_lines = CN = 0;
int i;
char s;
loadln( "Hello World" );
loadln( "Microsoft .NET Framework, " );
loadln( "COBOL" );
deleteln(0);
for (i = 0; i < 5; ++i)
if ((tmp = getpln(i)) && tmp->s)
puts(tmp->s);
else
puts("<no line here>");
}