string array

M

Magix

Hi,

I would like to use array of array to store different string, or if you have
better idea to store different string in array index.
How can I achieve that ? Any example will be greatly appreciate.

Thanks.
 
B

bjrnove

Hi.

This really depends on what you are going to use this for, but an array
of strings is the way I usaly do it. If you could describe what you are
going to use this index of strings for, an example should be possible
to make. Is it something you are going to declare once, or is it going
to grow during runtime?
 
M

Magix

an array pointer to hold mutiple string.
Not declare once, but the array index is fixed with empty contents, and the
contents will be updated during runtime using strcpy.
 
B

bjrnove

So, something like this will help?

You wil of course have to free the memory of each string at the end, or
when you are done.

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

/* This function returns the number of items in the array of strings.
*/
size_t StringsSize(char** ppszStrings)
{
char** ppszTmp = ppszStrings;

if(!ppszStrings)
return 0;

while(*ppszTmp)
ppszTmp++;

return (ppszTmp - ppszStrings);
}


/* This function adds a string to the end of the array of strings */
int AddString(char*** pppszStrings, char* pszString)
{
char** ppszStrings = *pppszStrings;
size_t nSize = 0;

nSize = StringsSize(ppszStrings);

if(!(ppszStrings = (char**)realloc(ppszStrings, sizeof(char**) *
(nSize + 2)))){
return errno;
}

if(!(ppszStrings[nSize] = (char*)malloc(strlen(pszString) + 1))){
return errno;
}

strcpy(ppszStrings[nSize], pszString);

ppszStrings[nSize + 1] = NULL;

*pppszStrings = ppszStrings;
return 0;
}

int main()
{
char **ppszStrings = NULL;
int i,j;

AddString(&ppszStrings, "Test1");
AddString(&ppszStrings, "Test2");
AddString(&ppszStrings, "Test3");

for(i = 0, j = StringsSize(ppszStrings); i < j; i++){
printf("String %i: %s\n", i + 1, ppszStrings);
}

return 0;
}
 
B

bjrnove

And you could use something like this to delete one string somewhere in
the array.

int RemoveString(char*** pppszStrings, int nIndex)
{
char** ppszStrings = *pppszStrings;
int i, j;
size_t nSize = 0;

nSize = StringsSize(ppszStrings);

/* Check if the index exist in the array. */
if(nIndex >= nSize)
return 1; /* Should be defined as an error constant */

free(ppszStrings[nIndex]);

for(i = nIndex + 1, j = nSize + 1; i < j; i++){
ppszStrings[i - 1] = ppszStrings;
}

if(!(ppszStrings = (char**)realloc(ppszStrings, nSize))){
return errno; /* FATAL ERROR. THIS SHOULD NOT HAPPEND,
* AND MOST PROBABLY WIL NOT */
}

*pppszStrings = ppszStrings;

return 0;
}

And something like this to delete it all.

int FreeStrings(char** ppszStrings)
{
int i,j;

for(i = 0, j = StringsSize(ppszStrings); i < j; i++)
free(ppszStrings);

free(ppszStrings);
}
 
A

Al Bowers

bjrnove said:
So, something like this will help?

The code appears good. However, I believe you have an almost
unnoticeable flaw in function AddString. Look over carefully
what will happen should function realloc fail or function
malloc fail(on the first call).
You wil of course have to free the memory of each string at the end, or
when you are done.
size_t StringsSize(char** ppszStrings)
{
char** ppszTmp = ppszStrings;

if(!ppszStrings)
return 0;

while(*ppszTmp)
ppszTmp++;

return (ppszTmp - ppszStrings);
}


/* This function adds a string to the end of the array of strings */
int AddString(char*** pppszStrings, char* pszString)
{
char** ppszStrings = *pppszStrings;
size_t nSize = 0;

nSize = StringsSize(ppszStrings);

if(!(ppszStrings = (char**)realloc(ppszStrings, sizeof(char**) *
(nSize + 2)))){
return errno;
}

if(!(ppszStrings[nSize] = (char*)malloc(strlen(pszString) + 1))){
return errno;
}

strcpy(ppszStrings[nSize], pszString);

ppszStrings[nSize + 1] = NULL;

*pppszStrings = ppszStrings;
return 0;
}
 
B

bjrnove

This was something I put together just to make an example. Yes it would
be a problem if malloc failed the first time. And it would definitly
create a memory leak. If realloc fails howewer, I don't see a problem.
 
B

bjrnove

This should fix the problem mentioned above.

int AddString(char*** pppszStrings, char* pszString)
{
char** ppszStrings = *pppszStrings;
size_t nSize = 0;

nSize = StringsSize(ppszStrings);

if(!(ppszStrings = (char**)realloc(ppszStrings, sizeof(char**) *
(nSize + 2)))){
/* If this fail I will return without making any changes to the

* string assay. If it fail the first time everything is NULL
* anyway, so that shouldn't be a problem. */
return errno;
}

if(!(ppszStrings[nSize] = (char*)malloc(strlen(pszString) + 1))){
int nErr = errno;
/* If this fails it's a bit of a problem. My solution is to
* realloc the array back to it's original size. */

if(!(ppszStrings = (char**)realloc(ppszStrings, sizeof(char**)
* (nSize + 1)))){
/* This shouldn't be possible since you're asking for less
memory than you
* already have. */

return 123; /* Should be defined as an FATAL ERROR constant
of some
* kind. If you get an error here the system is
unstable,
* and your program should quit. */
}
*pppszStrings = ppszStrings;
return nErr;
}

strcpy(ppszStrings[nSize], pszString);

ppszStrings[nSize + 1] = NULL;

*pppszStrings = ppszStrings;
return 0;
}
 
A

Al Bowers

bjrnove said:
This should fix the problem mentioned above.

int AddString(char*** pppszStrings, char* pszString)
{
char** ppszStrings = *pppszStrings;
size_t nSize = 0;

nSize = StringsSize(ppszStrings);

if(!(ppszStrings = (char**)realloc(ppszStrings, sizeof(char**) *
(nSize + 2)))){
/* If this fail I will return without making any changes to the

* string assay. If it fail the first time everything is NULL
* anyway, so that shouldn't be a problem. */
return errno;
}

if(!(ppszStrings[nSize] = (char*)malloc(strlen(pszString) + 1))){
int nErr = errno;
/* If this fails it's a bit of a problem. My solution is to
* realloc the array back to it's original size. */

if(!(ppszStrings = (char**)realloc(ppszStrings, sizeof(char**)
* (nSize + 1)))){
/* This shouldn't be possible since you're asking for less
memory than you
* already have. */

return 123; /* Should be defined as an FATAL ERROR constant
of some
* kind. If you get an error here the system is
unstable,
* and your program should quit. */
}

No, you cannot simply realloc and return an error code. Either one
of the two realloc statements may move the array of pointers to a
new location. Therefore, the value of the char ** argument in function
main may no longer point to the array. See, below the function
modified that should correct the problem.

*pppszStrings = ppszStrings;
return nErr;
}

strcpy(ppszStrings[nSize], pszString);

ppszStrings[nSize + 1] = NULL;

*pppszStrings = ppszStrings;
return 0;
}

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

size_t ArrayCount(char **p);
int AddString(char ***p, const char *s);
void PrintArray(char **p);
void FreeArray(char ***p);

int main(void)
{
char **name = NULL;

AddString(&name,"George Washington");
AddString(&name, "John Adams");
AddString(&name, "Bill Clinton");
AddString(&name,"George W. Bush");
AddString(&name, "Abraham Lincoln");
puts("\tContents of the array of strings");
PrintArray(name);
FreeArray(&name);
return 0;
}

size_t ArrayCount(char **p)
{
size_t tmp;

if(!p) return 0;
for(tmp = 0;(*p); p++,tmp++) ;
return tmp;
}

int AddString(char ***p, const char *s)
{
char **tmp, *s1;
size_t ele_nr = ArrayCount(*p);

if(!p || !s) return 0;
if((tmp = realloc(*p,(ele_nr+2)*sizeof *tmp)) == NULL)
return 0;
tmp[ele_nr] = tmp[ele_nr+1] = NULL;
*p = tmp;
if((s1 = malloc(strlen(s)+1)) == NULL)
return 0;
strcpy(s1,s);
tmp[ele_nr] = s1;
return 1;
}

void PrintArray(char **p)
{
for( ; *p; p++)
printf("%s\n",*p);
return;
}

void FreeArray(char ***p)
{
char **tmp;

for(tmp = *p ; *tmp; tmp++) free(*tmp);
free(*p);
*p = NULL;
return;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,421
Latest member
StacyTaver

Latest Threads

Top