473,326 Members | 2,095 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

Array of strings

Hello,

I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Then I should do something like that : StringArray[x*100][50]
But x can be huge, then I must allocate it dynamically.

I have searched on Google, but I only found different solutions (malloc,
realloc, calloc, ...)
What could be the best solution ?

Thanks in advance.
Nov 14 '05 #1
13 1924
Hi,

Hoping that you can use STLs in your set-up...one solution can be....

list<vector<string> >

string to store the 50 character string
vector<> to store 100 such strings and
list<> to store the packets...

Hope you the know the usage of STLs....

If you use STL you can be least bothered about the memory allocation
and deallocation.

-vs_p...

Nov 14 '05 #2
jesper <je****@nospam.com> wrote:
I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Then I should do something like that : StringArray[x*100][50]
But x can be huge, then I must allocate it dynamically.
Rather likely, especially if you don't know in advance how many
strings you're going to get, which wouldn't be unusal when dealing
with databases.
I have searched on Google, but I only found different solutions (malloc,
realloc, calloc, ...)
What could be the best solution ?


They are not mutually exclussive and you don't mention free() ;-)
You are probably going to need malloc() and realloc() and free()
afterwards to get rid of the memory once you don't need it any-
more (calloc() probably won't be too useful here). What would be
the best solution depends a lot on your requirements, so it's a
bit like asking "Which is the best car?". What exactly do you
have problems with and how far did you got? It's usually a lot
easier to discuss things when one has some code to start with.
Or are you complete lost? And do you understand how pointers
work? If not you probably should start learning about them (plus
the methods for memory allocation) using some simpler examples
than the task you're talking about.

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #3
Achintya <vs********@yahoo.com> wrote:
Hoping that you can use STLs in your set-up...one solution can be....
list<vector<string> >


Not very likely when the OP is asking in comp.lang.c, isn't it?

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #4

jesper a écrit :
Hello,
Hello,
I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Then I should do something like that : StringArray[x*100][50]


Assuming that you have only a packet (x=1), I don't think that it would
be the correct (easiest) form to deal with 100 strings of 50
characters.
char StringArray[50][100] would be better. In that way, your strings
are "organized by lines" (X myArray[COLUMN][ROW];), and when you want
to access to the i-th string, you just have to write StringArray[i].

A basic and first possible approach is to define a packet type and then
use pointers to packet typed variables.

exple:
typedef char StringsPacket[50][100];
StringsPacket * packets;

But this is ugly and difficult to handle. Furthermore It hides the
array type of StringsPacket.

A better way to do it is to use structures to split your data in simple
items.

exple:
/**
* @def LG_MAX
* Max length of a string, including the '\0'
*/
#define LG_MAX 50

/**
* @def NB_STR_PACKET
* Number of strings per packet
*/
#define NB_STR_PACKET 100

/**
* @struct typeString_s
* Structure type used for a string
*/
typedef struct typeString_s {
char str[LG_MAX]; /* String */
unsigned pos; /* Position in the packet (subscript)*/
}String_s;

/**
* @struct typeStringPacket_s
* Structure type that describes a packet of strings
*/
typedef struct typeStringPacket_s {
String_s str_arr[NB_STR_PACKET]; /* Array of String_s */
}StringPacket_s;

/**
* @struct typeNodePacket_s
*/
typedef struct typeNodePacket_s {
StringPacket_s packet; /* Packet */
struct typePacket_s * next; /* Next packet in the list */
}NodePacket_s;

In that way, it is easy to handle a linked list of NodePacket_s. This
is a common used solution when you don't know the number of data items
to handle. Here, you'll just have to allocate (and free) NodePackets_s*
variables as needed with malloc(or calloc)/free. realloc() isn't really
useful here.

HTH
Regis

Nov 14 '05 #5
Achintya wrote:

Hoping that you can use STLs in your set-up...one solution can be....

list<vector<string> >


C++ is off-topic in c.l.c. We deal with the C language.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #6


jesper wrote:
Hello,

I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Then I should do something like that : StringArray[x*100][50]
But x can be huge, then I must allocate it dynamically.


As I understand, your input,ie. packets, is firm at 100 strings of
50 characters. But the number of packets is unknown.

Then one possiblity may be to declare a StringArray
typedef char StringArray[100][50];

And make a data struct like

struct PACKET
{
StringArray *packet;
unsigned packet_nr;
}

Define a function that will allocate an array of packet
growing with you needs. See function AddPACKET below.

You will need a function that copies the packet into
the allocated space. In a example below I use the function
GetPacket. And as a test this function reads a text file stream
and stores the data in the newly allocated packet element.
Of course, you would have to adapt that function to your steam
requirements.

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

#define NR_STR 100
#define SZ_STR 50

typedef char StringArray[NR_STR][SZ_STR];
typedef enum PERR {NO_ERROR, ALLOC_FAILURE, STREAM_ERROR}PERR;

PERR packeterror;

typedef struct PACKET
{
StringArray *packet;
unsigned nr_packets;
} PACKET;
/* Prototypes */
int GetPacket(StringArray p, FILE *stream);
StringArray *AddPACKET(PACKET *p, FILE *stream);
void PrintStringArray(StringArray p, FILE *ostream);
void FreePACKET(PACKET *p);

int main(void)
{
FILE *fp;
PACKET mypackets= {NULL};
StringArray *pac;

if((fp = fopen("test.c","r")) != NULL)
{
if((pac=AddPACKET(&mypackets,fp)) != NULL)
PrintStringArray(*pac,stdout);
else switch(packeterror)
{
case ALLOC_FAILURE: puts("Allocation failure");
break;
case STREAM_ERROR: puts("Stream error");
break;
case NO_ERROR: puts("Unspecified ERROR");
};
fclose(fp);
FreePACKET(&mypackets);
}
else puts("Unable to open stream");
return 0;
}

void FreePACKET(PACKET *p)
{
free(p->packet);
p->packet = NULL;
p->nr_packets = 0U;
return;
}

StringArray *AddPACKET(PACKET *p, FILE *stream)
{
StringArray *tmp;

packeterror = NO_ERROR;
tmp = realloc(p->packet,(p->nr_packets+1)*sizeof *tmp);
if(tmp == NULL)
{
packeterror = ALLOC_FAILURE;
return NULL;
}
p->packet = tmp;
if(!GetPacket(p->packet[p->nr_packets], stream))
return NULL;
return &p->packet[p->nr_packets++];
}

void PrintStringArray(StringArray p, FILE *ostream)
{
unsigned i;

for(i = 0; i < NR_STR; i++)
printf("%s",p[i]);
putchar('\n');
return;
}

int GetPacket(StringArray p, FILE *stream)
{
unsigned i;

packeterror = NO_ERROR;
for(i = 0;i < NR_STR; i++)
if(!fgets(p[i],SZ_STR,stream))
{
packeterror = STREAM_ERROR;
return 0;
}
return 1;
}

--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #7

Targeur fou a écrit :
jesper a écrit :
Hello,
Hello,
I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Then I should do something like that : StringArray[x*100][50]


Assuming that you have only a packet (x=1), I don't think that it

would be the correct (easiest) form to deal with 100 strings of 50
characters.
char StringArray[50][100] would be better. In that way, your strings
are "organized by lines" (X myArray[COLUMN][ROW];), and when you want
to access to the i-th string, you just have to write StringArray[i].


Sorry, I said bullshits just above. It's char StringArray[100][50], you
were right. 2D arrays aren't so easy to use...

My apologies.

Regis

Nov 14 '05 #8
"jesper" <je****@nospam.com> wrote in message
news:42***********************@news.free.fr...
I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.


Thanks for answers.
In fact my loading works, but it's the "free()" which crashes.
I absolutely need to free allocated memory, as I have many other arrays to
fill afterwards.
I did this, just for test (contiguous array) :

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

#define NBENR 100

int main(int argc, char* argv[])
{
char sBuffer[50];
int i;
int j, k;

j=0;
while (j<=1000)
{
char **sArray = (char **)malloc(NBENR * sizeof(char *));
sArray[0] = (char*)malloc(NBENR * 50 * sizeof(char));
for(k= i = j; i <= k+ NBENR; i++)
{
sArray[i] = sArray[0] + i * 50;
sprintf(sBuffer, "String[%d]\n", j);
strcpy(sArray[i], sBuffer);
printf(sArray[i]);
j++;
if (j> 1000)
break;
}
// crashes !!!
free((char*)sArray[0]);

}
return 0;
}

Nov 14 '05 #9

jesper a écrit :

Hi,
"jesper" <je****@nospam.com> wrote in message
news:42***********************@news.free.fr...
I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Thanks for answers.
In fact my loading works, but it's the "free()" which crashes.
I absolutely need to free allocated memory, as I have many other

arrays to fill afterwards.
I did this, just for test (contiguous array) :

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

#define NBENR 100

int main(int argc, char* argv[])
{
char sBuffer[50];
int i;
int j, k;

j=0;
while (j<=1000)
{
char **sArray = (char **)malloc(NBENR * sizeof(char *));
Notice that you have to test the return of malloc here.
sArray[0] = (char*)malloc(NBENR * 50 * sizeof(char));
The same here. But I wonder why you don't allocate 50 characters for
each pointer to pointer to char in the packet.

e.g:

char **sArray = malloc(NBENR * sizeof (char**));
if (sArray != NULL)
{
/* Loop to allocate memory for each string in the packet */
int i, j, brkFlag = 0;
for (i=0, j=0; i<NBENR; ++i, ++j)
{
sArray[i] = malloc(50);
/* Trace and break the loop in case of failure */
if (sArray[i] == NULL)
{
fprintf(stderr,
"Failed to allocate memory for the %d string in the
packet\n",
i+1);
brkFlag = 1;
break;
}
}

if ( brkFlag != 0)
/* Loop to free already allocated items if it failed above */
for(i=0; i<=j && brkFlag ==1; ++i)
{
free(sArray[i]);
}
free(sArray);
exit(EXIT_FAILURE);
}

/* PROCESSING HERE */

/* Loop to free already memory items */
for(i=0; i<=j; ++i)
{
free(sArray[i]);
}
/* At last, free the pointer to pointers to char */
free(sArray);

}
else
{
fprintf(stderr,
"Failed to allocate memory for the pointer to pointers to
char\n");
}
for(k= i = j; i <= k+ NBENR; i++)
{
sArray[i] = sArray[0] + i * 50;
sprintf(sBuffer, "String[%d]\n", j);
strcpy(sArray[i], sBuffer);
printf(sArray[i]);
j++;
if (j> 1000)
break;
}
// crashes !!!
free((char*)sArray[0]);


Surprising. Are you sure sArray[0] (its value) isn't modified somewhere
in your program (realloc(), a shift...) ? You retrieved a pointer value
with malloc() but it shall be the same pointer value to pass to free()
to avoid crashes.

HTH
Regis

Nov 14 '05 #10

jesper wrote:
Hello,

I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Then I should do something like that : StringArray[x*100][50]
But x can be huge, then I must allocate it dynamically.

I have searched on Google, but I only found different solutions (malloc, realloc, calloc, ...)
What could be the best solution ?

Thanks in advance.


You can use a wrapper function like that in the following link:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c
Example usage:
char **StringArray = ALLOCATE2DARRAY(char, x*100, 50);

You can access above type with [][]

Nov 14 '05 #11
Axter wrote:
jesper wrote:
Hello,

I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Then I should do something like that : StringArray[x*100][50]
But x can be huge, then I must allocate it dynamically.

I have searched on Google, but I only found different solutions
(malloc, realloc, calloc, ...)
What could be the best solution ?

Thanks in advance.


You can use a wrapper function like that in the following link:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c
Example usage:
char **StringArray = ALLOCATE2DARRAY(char, x*100, 50);

You can access above type with [][]


You suggested this code to someone else back on the 30th April, and is
was explained back then why this code is not portable.

Your code assumes that the void** can be converted to a valid Type**
pointer which is not guaranteed by the standard. It also assumes that
the representation of void* is the same as Type* (I think the standard
says something about this for Type==char, but not in general).

You even admitted on May 1st Message-ID:
<11**********************@f14g2000cwb.googlegroups .com> that it was
possible for sizeof(void*) to be different from sizeof(Type*) and that
your code was therefore not portable.

Recommending non-portable code without clearly stating it is
non-portable is not a nice thing to do. Especially on a group dedicated
to portable programming.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #12

Flash Gordon wrote:
Axter wrote:
jesper wrote:
Hello,

I have to load strings from a datbase and put them into an array.
I get them by packets of 100 strings of 50 characters.
Then I should do something like that : StringArray[x*100][50]
But x can be huge, then I must allocate it dynamically.

I have searched on Google, but I only found different solutions
(malloc, realloc, calloc, ...)
What could be the best solution ?

Thanks in advance.
You can use a wrapper function like that in the following link:
http://code.axter.com/allocate2darray.h
http://code.axter.com/allocate2darray.c
Example usage:
char **StringArray = ALLOCATE2DARRAY(char, x*100, 50);

You can access above type with [][]


You suggested this code to someone else back on the 30th April, and

is was explained back then why this code is not portable.

Your code assumes that the void** can be converted to a valid Type**
pointer which is not guaranteed by the standard. It also assumes that the representation of void* is the same as Type* (I think the standard says something about this for Type==char, but not in general).

You even admitted on May 1st Message-ID:
<11**********************@f14g2000cwb.googlegroups .com> that it was
possible for sizeof(void*) to be different from sizeof(Type*) and that your code was therefore not portable.

Recommending non-portable code without clearly stating it is
non-portable is not a nice thing to do. Especially on a group dedicated to portable programming.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
The code is portable if used with a char type. Read the C standard section section 6.2.5-26.
I stated that I thought that the standard stated something about
char,however you did not state that your code only works for char despite
what the comments say.
If you had bother to read the *.c file, and read the comments at the
bottom, you see that I made a full disclosure on the code's portability
issue, with direct reference to the standard.

The code is portable when used with a char type, and that's is what the
questioner is asking about.
Your complaint of non-portability is out of topic for this paticular
question.
If you had stated it was only suitable for char that would have been
been fine. Although you should also change the comments and/or change itto using char type. I don't have to state that, if the questioner not asking about other
types or types in general.
The question was specific.
If you want to give that additional information, please feel free to do
so, but please don't try and tell me how I should give advise.
In your code you state it works for any type, therefore it is not
portable. If it stated it was only portable for char I would not have commented.


It does state that in the implementation. Please do your homework.

IMHO, is more inappropriate for you to state that the code is not
portable, with stating that it is portable for the example I posted,
and for the specific question asked.
Recommending non-portable code without clearly stating it is
non-portable is not a nice thing to do. Especially on a group dedicated to portable programming.
--
Flash Gordon
Living in interesting times.


Stating something is not portable, when the specific code posted is
portable, is not a nice thing to do, and moreover, it's basically a
lie.

If you would have stated that it's not portable with any other type
other then char, then that would be truthful.
But what you stated is misleading at best, and a lie at worse. This
does do well for your credibility.

When critiquing someone in the future, please try to be a little more
honest, or at least a little more accurate.

FYI:
Sorry for emailing my last reply. I click the wrong Google button.

Nov 14 '05 #13
If your database is a file, get FreeDOS Edlin 2.5 (available on ibiblio
or the alt.sources newsgroup) and borrow that code.

Gregory Pietsch

Nov 14 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Federico G. Babelis | last post by:
Hi All: I have this line of code, but the syntax check in VB.NET 2003 and also in VB.NET 2005 Beta 2 shows as unknown: Dim local4 As Byte Fixed(local4 = AddressOf dest(offset)) ...
3
by: SilverWolf | last post by:
I need some help with sorting and shuffling array of strings. I can't seem to get qsort working, and I don't even know how to start to shuffle the array. Here is what I have for now: #include...
4
by: Simon Schaap | last post by:
Hello, I have encountered a strange problem and I hope you can help me to understand it. What I want to do is to pass an array of chars to a function that will split it up (on every location where...
7
by: arkobose | last post by:
hey everyone! i have this little problem. consider the following declaration: char *array = {"wilson", "string of any size", "etc", "input"}; this is a common data structure used to store...
12
by: arkobose | last post by:
my earlier post titled: "How to input strings of any lengths into arrays of type: char *array ?" seems to have created a confusion. therefore i paraphrase my problem below. consider the...
24
by: Michael | last post by:
Hi, I am trying to pass a function an array of strings, but I am having trouble getting the indexing to index the strings rather than the individual characters of one of the strings. I have...
2
by: Potiuper | last post by:
Question: Is it possible to use a char pointer array ( char *<name> ) to read an array of strings from a file in C? Given: code is written in ANSI C; I know the exact nature of the strings to be...
14
by: Shhnwz.a | last post by:
Hi, I am in confusion regarding jargons. When it is technically correct to say.. String or Character Array.in c. just give me your perspectives in this issue. Thanx in Advance.
11
by: Bob Rock | last post by:
Hello, I have an array of strings and need to find the matching one with the fastest possible code. I decided to order the array and then write a binary search algo. What I came up with is the...
3
by: Morten71 | last post by:
I have a strange problem. I have a local string() var I populate this way: clmns() As String = {"InvoiceNo", "InvoiceDate"} When I call: Array.IndexOf(clmns,"InvoiceDate") I get 0 (zero) as...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.