Re: Declaring a dynamic pointer to an array of char pointers
Messaggio multiparte in formato MIME.
------=_NextPart_000_0028_01CAA03E.AEEE9BD0
Content-Type: text/plain;
format=flowed;
charset="iso-8859-1";
reply-type=response
Content-Transfer-Encoding: 7bit
"DS" <dsutNOSPAMter@tc3NOSPAMnet.com> ha scritto nel messaggio
news:uQhIpY6nKHA.5520@TK2MSFTNGP05.phx.gbl...
I would like to declare a pointer to an array of char pointers, that
I can allocate at some time during a run.
I'll expect a variable length string of tokens seperated by white space
chars.
I would like to search for each token head and store it's address in a
sequential
array of pointers, Then insert a NULL at each tokens end.
ie: string = "Cmd Arg1 Arg2 Arg3..."
Now I tried:
char ** PtrArray;
But the program hanged.
char** would be just fine in pure C.
I have turned my "C Reference Manual inside and out.
I have read several web documents, pointer tutorials...
Please help,
Considering that you are asking for a pure C solution, you may find useful a
simple C tokenzier I wrote and attached here.
It seems to work in some tests, but it needs more verification.
Note that if you could use C++, vector<CString> would be better choice than
raw C-like array of pointers.
(To my limited knowledge, there are few cases in which you must use pure C
instead of C++, like e.g. developing device drivers in kernel mode; if you
aren't in this elite, C++ could make your life easier.)
HTH,
Giovanni
------=_NextPart_000_0028_01CAA03E.AEEE9BD0
Content-Type: text/plain;
format=flowed;
name="TestTokenizer.c";
reply-type=response
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="TestTokenizer.c"
/************************************************************************=
* FILE: TestTokenizer.c
* DESC: A simple tokenizer written in C.
*
* By Giovanni Dicanio <giovanni.dicanio@gmail.com>
=
************************************************************************/=
/*----------------------------------------------------------------------*=
/
/* INCLUDES =
*/
/*----------------------------------------------------------------------*=
/
#include <stdio.h> /* printf */
#include <stdlib.h> /* calloc/free */
#include <string.h> /* memset */
/*----------------------------------------------------------------------*=
/
/*----------------------------------------------------------------------*=
/
/* HELPER FUNCTIONS FOR THE TOKENIZER =
*/
/*----------------------------------------------------------------------*=
/
/*
* Given a string, skips all consecutive separator characters
* starting from the beginning.
* Returns a pointer to the first non-separator character.
*/
char * SkipSeparators(char * s, char separator)
{
char * p = s; /* Scanner in input string */
/* Until the end of string: */
while (*p != '\0')
{
if (*p != separator)
{
/* A non-separator was found: so return its position */
break;
}
/* Move to next character */
++p;
}
return p;
}
/*
* Given a string, searches the first occurrence of a separator =
character.
* On success, returns pointer to the separator character.
* If no separator is found, returns a pointer to end-of-string =
character.
*/
char * FindNextSeparator(char * s, char separator)
{
char * p = s; /* Scanner in input string */
while (*p != '\0')
{
if (*p == separator)
{
/* Found ! */
break;
}
/* Move to next character */
++p;
}
return p;
}
/*
* Given a string, returns the number of tokens found in it.
*/
int GetTokenCount(char * s, char separator)
{
int tokenCount = 0; /* # of tokens found */
char * p = s; /* Scanner of source string */
/* If string is NULL or empty, there is no token */
if (s == NULL || *s == '\0')
return 0;
/* For each character in input string: */
while (*p != '\0')
{
/* Skip initial separators, if any */
p = SkipSeparators(p, separator);
/* If there are no more character, just quit looping */
if (*p == '\0')
break;
/* Find separator delimiting current token */
p = FindNextSeparator(p, separator);
/* Update token counter */
++tokenCount;
}
/* Return number of tokens found */
return tokenCount;
}
/*----------------------------------------------------------------------*=
/
/*----------------------------------------------------------------------*=
* *** Main Tokenizer Function ***
*
* Given a string, tokenizes it.
*
* A string array is returned, containing pointers to tokens.
* End of array is marked by a NULL pointer.
*
* The caller must call free() to release allocated memory returned
* by this function.
*
* Input string is modified (\0 characters are inserted to separate
* tokens.)
*
* If input string is NULL or empty, or there are no tokens, returns =
NULL.
* On allocation error, returns NULL.
=
*----------------------------------------------------------------------*/=
char ** Tokenize(char * s, char separator)
{
int tokenCount = 0; /* # of tokens found */
int currToken = 0; /* index of current token in token =
array
*/
char * p = s; /* Scanner of source string */
char * end = NULL; /* Token end */
char ** tokens = NULL; /* Array of pointers to tokens
* (last pointer is NULL) */
/* If string is NULL or empty, there is no token */
if (s == NULL || *s == '\0')
return NULL;
/* Get number of tokens in input string */
tokenCount = GetTokenCount(s, separator);
if (tokenCount == 0)
return NULL;
/* Create token array.
* This array stores pointers to each token.
* There are tokenCount+1 array slots, because last slot
* (set to NULL) marks the end of the array.
*/
tokens = (char **) calloc(tokenCount + 1, sizeof(char *));
if (tokens == NULL)
return NULL;
/* Clear array pointers */
memset(tokens, 0, (tokenCount + 1) * sizeof(char *));
/* For each character in input string: */
while (*p != '\0')
{
/* Skip initial separators, if any */
p = SkipSeparators(p, separator);
/* If there are no more character, just quit looping */
if (*p == '\0')
break;
/* Find separator delimiting current token */
end = FindNextSeparator(p, separator);
/* Store token pointer in array */
tokens[currToken] = p;
/* Update token counter */
++currToken;
if (*end != '\0')
{
/* If this was not last character in string,
* terminates token with a \0 */
*end = '\0';
/* Continue looping from next character */
p = end + 1;
}
else
{
/* End of string found: stop looping */
break;
}
}
/* Return found tokens */
return tokens;
}
/*----------------------------------------------------------------------*=
/
/*----------------------------------------------------------------------*=
/
/*----------------------------------------------------------------------*=
/
/* TEST =
*/
/*----------------------------------------------------------------------*=
/
/*
* Prints content of a string array using printf (debug/test purposes).
* End of array is marked by a NULL pointer.
*/
void PrintStringArray(char ** strings)
{
if (strings == NULL )
{
printf(" *** empty string array ***\n");
}
else
{
int i = 0;
while ( strings[i] != NULL )
{
printf(" \"%s\"\n", strings[i]);
i++;
}
}
printf("\n");
}
/*
* Helper macro to get number of items in array
*/
#define COUNTOF(a) (sizeof(a) / sizeof(a[0]))
int main(void)
{
int i; /* loop index */
const char separator = ' '; /* separator character */
/*
* Test strings
*/
char test1[] = "Ciao Arg1 Arg2 hello";
char test2[] = " Ciao Arg1 Arg2 hello ";
char test3[] = "";
char test4[] = " ciao ";
char test5[] = " ";
char test6[] = "ciao";
char *tests[] = {test1, test2, test3, test4, test5, test6};
printf("*** Tokenization in pure C ***\n\n");
for (i = 0; i < COUNTOF(tests); i++)
{
char ** tokens;
printf("------------ Tokenization #%d ----------------\n", =
(i+1));
/* Print current test string */
printf("String: \"%s\"\n\n", tests[i]);
/* Tokenize current string */
tokens = Tokenize(tests[i], separator);
/* Print resulting tokens */
printf("Tokens:\n");
PrintStringArray(tokens);
printf("---------------------------------------------\n\n");
/* Cleanup */
free(tokens);
tokens = NULL;
}
return 0;
}
/************************************************************************=
/
------=_NextPart_000_0028_01CAA03E.AEEE9BD0
Content-Type: text/plain;
format=flowed;
name="TestTokenizer_Output.txt";
reply-type=response
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="TestTokenizer_Output.txt"
*** Tokenization in pure C ***
------------ Tokenization #1 ----------------
String: "Ciao Arg1 Arg2 hello"
Tokens:
"Ciao"
"Arg1"
"Arg2"
"hello"
---------------------------------------------
------------ Tokenization #2 ----------------
String: " Ciao Arg1 Arg2 hello "
Tokens:
"Ciao"
"Arg1"
"Arg2"
"hello"
---------------------------------------------
------------ Tokenization #3 ----------------
String: ""
Tokens:
*** empty string array ***
---------------------------------------------
------------ Tokenization #4 ----------------
String: " ciao "
Tokens:
"ciao"
---------------------------------------------
------------ Tokenization #5 ----------------
String: " "
Tokens:
*** empty string array ***
---------------------------------------------
------------ Tokenization #6 ----------------
String: "ciao"
Tokens:
"ciao"
---------------------------------------------
------=_NextPart_000_0028_01CAA03E.AEEE9BD0--