473,325 Members | 2,872 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,325 software developers and data experts.

Problems with Pointers

Hello All

My question mainly is how to use/reference Double Pointers? I am
currently trying to understand what the meaning of a 'vector of
pointers' means also? What I am trying to do is take a char array and
break it up into words omitting the spaces. What needs to be noted is
that I am trying to accomplish this only using char ** and char *.
Therefore, I am creating it from scratch. Below is code that I have
written so far:

int main()
{
char input[125] = " Hello World\0"
char **doublePointer;
char *receiveArray;

doublePointer = malloc(125 * sizeof(char *));
receiveArray = input;

int i;
for(i = 0; receiveArray [ i ] != '\0'; i++)
{
//Here I am confused
//I'm not sure how to traverse the array and store data into
// the double pointer/vector
//Do I need to do this
// doublePointer [ i ] = malloc ( sizeof( char * ));
}
free(doublePointer);

return 0;
}

Any hints and suggestions about the algorithm/design would be
welcome. Thanks.
Sep 1 '08 #1
14 1673
st********@gmail.com writes:
My question mainly is how to use/reference Double Pointers? I am
currently trying to understand what the meaning of a 'vector of
pointers' means also? What I am trying to do is take a char array and
break it up into words omitting the spaces. What needs to be noted is
that I am trying to accomplish this only using char ** and char *.
Therefore, I am creating it from scratch. Below is code that I have
written so far:
Why start with main? What function would really, really help to solve
this? Image it exists and take it from there. Then all you need do
is write that now slightly simpler function.

Personally, I want a function declared like this:

char *next_word(const char **string);

/* Returns a pointer to a copy (in malloc'd storage) of the
* next word found in *string. *string is updated to point to
* first character found that is not part of the work returned.
* If no word is found, NULL is returned.
*/

With this function in the bag, I'd expect to see a relatively simple
loop, putting the returned pointers into elements of a char * array.
For bonus marks, I'd hope to see a loop that reallocs this array if
more words than expected are found.

Now you just need to write next_word. What function would really,
really help to write next_word? Image it exists and take it from
there...
int main()
{
char input[125] = " Hello World\0"
char **doublePointer;
char *receiveArray;

doublePointer = malloc(125 * sizeof(char *));
If you are going to use 125, just declare

char *doublePointer[125];

BTW, that is a terrible name! Name you variables with what that mean
(usually what they contain) not what type they have.
receiveArray = input;

int i;
for(i = 0; receiveArray [ i ] != '\0'; i++)
{
//Here I am confused
//I'm not sure how to traverse the array and store data into
// the double pointer/vector
//Do I need to do this
// doublePointer [ i ] = malloc ( sizeof( char * ));
I would not start in the middle of a loop in main, sorry.
}
free(doublePointer);

return 0;
}

Any hints and suggestions about the algorithm/design would be
welcome. Thanks.
--
Ben.
Sep 1 '08 #2
On Sun, 31 Aug 2008 20:00:44 -0700, stevenruiz wrote:
Hello All

My question mainly is how to use/reference Double Pointers? I am
currently trying to understand what the meaning of a 'vector of
pointers' means also? What I am trying to do is take a char array and
break it up into words omitting the spaces. What needs to be noted is
that I am trying to accomplish this only using char ** and char *.
Therefore, I am creating it from scratch. Below is code that I have
written so far:

int main()
{
char input[125] = " Hello World\0"
char **doublePointer;
char *receiveArray;

doublePointer = malloc(125 * sizeof(char *)); receiveArray = input;

int i;
for(i = 0; receiveArray [ i ] != '\0'; i++) {
//Here I am confused
//I'm not sure how to traverse the array and store data into //
the double pointer/vector
//Do I need to do this
// doublePointer [ i ] = malloc ( sizeof( char * ));
}
free(doublePointer);

return 0;
}

Any hints and suggestions about the algorithm/design would be welcome.
Thanks.
To answer the OP question. A vector of pointers is an array of pointers
that implements a multidimensional array. Your assumption for accessing
the array of pointer seems correct as far as I can tell.
Sep 1 '08 #3
On Sun, 31 Aug 2008 20:00:44 -0700 (PDT), st********@gmail.com wrote:
>Hello All

My question mainly is how to use/reference Double Pointers? I am
currently trying to understand what the meaning of a 'vector of
pointers' means also? What I am trying to do is take a char array and
The phrase has no defined meaning in the standard. Since the word
vector also has no special meaning in C, I would take the phrase to be
synonymous with "array of pointers".
>break it up into words omitting the spaces. What needs to be noted is
Define break it up.

Do you want to replace the word separators (usually a space)
with '\0' so that the array now contains multiple strings, each
corresponding to a word? If so, do you want to build an array of
pointers that points to each word?

Or do you want to copy the portions of the string that
constitute words to new arrays of char? If so, do you want the
resulting arrays to contain valid strings or just the characters in
the words? Do you want to define the target arrays or dynamically
allocate them?
>that I am trying to accomplish this only using char ** and char *.
This is probably adequate for this task but why would you arbitrarily
limit yourself to a subset of the language? Usually arbitrary
restrictions like this are a sure sign of homework.
>Therefore, I am creating it from scratch. Below is code that I have
written so far:
Writing code before the intent is defined is perilous.
>
int main()
{
char input[125] = " Hello World\0"
char **doublePointer;
char *receiveArray;

doublePointer = malloc(125 * sizeof(char *));
Do you really think you will need a char* for char in input?
receiveArray = input;

int i;
for(i = 0; receiveArray [ i ] != '\0'; i++)
{
//Here I am confused
//I'm not sure how to traverse the array and store data into
// the double pointer/vector
Until you decide what data to store in the space pointed to by
doublePointer, we will be unsure also.
//Do I need to do this
// doublePointer [ i ] = malloc ( sizeof( char * ));
This is definitely wrong. doublePointer is a char**. Therefore
doublePointer[i] is a char*. If you want doublePointer[i] to point to
dynamically allocated memory, the argument passed to malloc should
always be the (maximum) number of characters you intend to store in
that memory. On most system, your code would limit you to 4 or 8.
This is the reason that many here recommend the following syntax for
allocating a dynamic array to a pointer named x:
x = malloc(number_of_elements_desired * sizeof *x);
}
free(doublePointer);
If doublePointer and all the doublePointer[i] point to allocated
memory, the doublePointer[i] need to be freed before you free
doublePointer.
>
return 0;
}
--
Remove del for email
Sep 1 '08 #4
On Aug 31, 10:57 pm, Barry Schwarz <schwa...@dqel.comwrote:
On Sun, 31 Aug 2008 20:00:44 -0700 (PDT), stevenr...@gmail.com wrote:
Hello All
My question mainly is how to use/reference Double Pointers? I am
currently trying to understand what the meaning of a 'vector of
pointers' means also? What I am trying to do is take a char array and

The phrase has no defined meaning in the standard. Since the word
vector also has no special meaning in C, I would take the phrase to be
synonymous with "array of pointers".
break it up into words omitting the spaces. What needs to be noted is

Define break it up.

Do you want to replace the word separators (usually a space)
with '\0' so that the array now contains multiple strings, each
corresponding to a word? If so, do you want to build an array of
pointers that points to each word?

Or do you want to copy the portions of the string that
constitute words to new arrays of char? If so, do you want the
resulting arrays to contain valid strings or just the characters in
the words? Do you want to define the target arrays or dynamically
allocate them?
that I am trying to accomplish this only using char ** and char *.

This is probably adequate for this task but why would you arbitrarily
limit yourself to a subset of the language? Usually arbitrary
restrictions like this are a sure sign of homework.
Therefore, I am creating it from scratch. Below is code that I have
written so far:

Writing code before the intent is defined is perilous.
int main()
{
char input[125] = " Hello World\0"
char **doublePointer;
char *receiveArray;
doublePointer = malloc(125 * sizeof(char *));

Do you really think you will need a char* for char in input?
receiveArray = input;
int i;
for(i = 0; receiveArray [ i ] != '\0'; i++)
{
//Here I am confused
//I'm not sure how to traverse the array and store data into
// the double pointer/vector

Until you decide what data to store in the space pointed to by
doublePointer, we will be unsure also.
//Do I need to do this
// doublePointer [ i ] = malloc ( sizeof( char * ));

This is definitely wrong. doublePointer is a char**. Therefore
doublePointer[i] is a char*. If you want doublePointer[i] to point to
dynamically allocated memory, the argument passed to malloc should
always be the (maximum) number of characters you intend to store in
that memory. On most system, your code would limit you to 4 or 8.
This is the reason that many here recommend the following syntax for
allocating a dynamic array to a pointer named x:
x = malloc(number_of_elements_desired * sizeof *x);
}
free(doublePointer);

If doublePointer and all the doublePointer[i] point to allocated
memory, the doublePointer[i] need to be freed before you free
doublePointer.
return 0;
}

--
Remove del for email
Pretty much what I'm trying to do is create a tokenizer or a (strtok)
and yes I would like to build an array of
pointers that points to each word. This is for I return or print out
to see the words in each position of the array of pointers. I
understand if I were to have a char[] which had, for example, "hello
world\0". The way I have been approaching this is first by
establishing a pointer to that array's first position at the letter
'h' using char *inputData = <the char array>. At this point, I have
the beginning of the char array. Next, I was thinking I would loop
through inputData while it is not equal to a space, I'm thinking that
I would point that doublePointer to that specific address of inputData
[ i ]? Please advise.
Sep 1 '08 #5
On Sep 1, 12:46 am, stevenr...@gmail.com wrote:
Pretty much what I'm trying to do is create a tokenizer or a (strtok)
and yes I would like to build an array of
pointers that points to each word.
This is for I return or print out
to see the words in each position of the array of pointers. I
understand if I were to have a char[] which had, for example, "hello
world\0".
Ok.
The way I have been approaching this is first by
establishing a pointer to that array's first position at the letter
'h' using char *inputData = <the char array>. At this point, I have
the beginning of the char array. Next, I was thinking I would loop
through inputData while it is not equal to a space, I'm thinking that
I would point that doublePointer to that specific address of inputData
[ i ]? Please advise.
This is pretty much what strtok does (overwriting the original
character buffer so each token is null-terminated). The main reasons
not to use strtok for this would be that you don't want to overwrite
the incoming text buffer, or that you're reimplementing strtok.
Sep 1 '08 #6
st********@gmail.com said:

<snip>
Pretty much what I'm trying to do is create a tokenizer or a (strtok)
and yes I would like to build an array of
pointers that points to each word.
Okay. ("To me, the term "double pointer" means the same as "pointer to
double", just as "char pointer" means "pointer to char", so your use of it
to mean "pointer to pointer", whilst far from unusual, does seem rather
strange to me. Just a thought.)
Please advise.
Divide and conquer.

Let's start by counting the number of words in the input string - and we
will define 'word' as 'a sequence, as long as possible, of one or more
contiguous characters containing no whitespace characters'. Whilst we
*could* count as we go along, it's easier if we know in advance how many
pointers we will need. So:

#include <stddef.h>
#include <ctype.h>

#define NOT_IN_WORD 0
#define IN_WORD 1

size_t wc(const char *s)
{
size_t count = 0;
int state = NOT_IN_WORD;
int space = 0;
while(*s != '\0')
{
space = isspace((unsigned char)*s);
if(state == NOT_IN_WORD && !space)
{
++count;
state = IN_WORD;
}
else if(state == IN_WORD && space)
{
state = NOT_IN_WORD;
}
++s;
}
return count;
}

Now let's test that. I added a simple driver, which looks like this:

#include <stdio.h>

int main(int argc, char **argv)
{
while(argc 0)
{
size_t count = wc(argv[--argc]);
printf("%d\n", count);
}
return 0;
}

Well, perhaps not the greatest test program in the world, but it allowed me
to drive the code and convince myself that I'd got it right. Okay, now we
have a way - wc() - to count the number of words in a string. Fine - now
we'd like to point at them. Remember, divide and conquer - so we'd like a
function that can build a sequence of these pointers, rather than have all
the intestines of this idea clogging up main.

Because we want to *tokenise* the string, in this simple solution we will
allow our function to modify the string itself. Note that this isn't
always what you want - it's "lazy" tokenisation, where we simply point
into the string at various points. That's fine as long as the string
persists (and as long as we don't mind hacking at it!).

Here, then, is a function to do that. Observe its similarities and
differences with regard to wc() - which it itself calls, by the way:

#include <stdlib.h>
#include <assert.h>
char **wl_build(char *s)
{
int space = 0;
int state = 0;
size_t thisword = 0;
size_t wordcount = wc(s);
char **wl = malloc((wordcount + 1) * sizeof *wl);
if(wl != NULL)
{
while(*s != '\0')
{
space = isspace((unsigned char)*s);
if(state == NOT_IN_WORD && !space)
{
wl[thisword++] = s;
state = IN_WORD;
}
else if(state == IN_WORD && space)
{
*s = '\0'; /* terminate the token */
state = NOT_IN_WORD;
}
++s;
}
wl[thisword] = NULL; /* list is NULL-terminated */
}
assert(thisword == wordcount);
return wl;
}

The alternative to doing this whole state machine thing twice is to count
and reallocate as we go. Possible, and microscopically faster, but perhaps
more effort than we'd like to go to, and the code would be messier, harder
to follow, and harder to maintain.

Once we have a way of creating such a list, we ought to have a way to
destroy it:
void wl_destroy(char ***wl)
{
if(wl != NULL)
{
free(*wl);
*wl = NULL;
}
}

And of course we will want a demonstration of how to use it. One easy way
to do that is to write a print function for it:

#include <stdio.h>

void wl_print(char **wl)
{
while(*wl != NULL)
{
printf("%s\n", *wl++);
}
}

Putting it all together, we throw away our old main(), and write a new one:

int main(int argc, char **argv)
{
while(argc 0)
{
char **wl = wl_build(argv[--argc]);
wl_print(wl);
wl_destroy(&wl);
}
return 0;
}

Now, that's all very well if we're content to do lazy evaluation. But what
if we're not? Let's say we need for these tokens to persist beyond the
lifetime of the string. Oh, and hey, let's say the string is sacrosanct,
too - we can look, but we'd better not touch.

Very few modifications are required, as it happens, to what we already
have, but all the mods are important. Perhaps most significant is the
addition of a token-duplicating function, since it is this that allows us
to create token copies that will persist after their originals have either
ceased to exist or at least changed in some way.

The creation of token copies allows us to leave the original string
unmodified, but it slightly complicates the destruction of the word list.

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

#define NOT_IN_WORD 0
#define IN_WORD 1

size_t wc(const char *s)
{
size_t count = 0;
int state = NOT_IN_WORD;
int space = 0;
while(*s != '\0')
{
space = isspace((unsigned char)*s);
if(state == NOT_IN_WORD && !space)
{
++count;
state = IN_WORD;
}
else if(state == IN_WORD && space)
{
state = NOT_IN_WORD;
}
++s;
}
return count;
}

char *token_duplicate(const char *p, size_t len)
{
char *new = malloc(len + 1);
if(new != NULL)
{
memcpy(new, p, len);
new[len] = '\0';
}
return new;
}

#include <assert.h>
char **wl_build(const char *s)
{
int space = 0;
int state = 0;
size_t thisword = 0;
size_t wordcount = wc(s);
const char *tokenstart = NULL;
size_t tokenlen = 0;
char **wl = malloc((wordcount + 1) * sizeof *wl);
if(wl != NULL)
{
while(*s != '\0')
{
space = isspace((unsigned char)*s);
if(state == NOT_IN_WORD && !space)
{
tokenstart = s;
tokenlen = 0;
state = IN_WORD;
}
else if(state == IN_WORD)
{
++tokenlen;
if(space)
{
wl[thisword++] = token_duplicate(tokenstart, tokenlen);
state = NOT_IN_WORD;
}
else
{
}
}
++s;
}
/* the last token may be null-terminated rather than space-terminated
*/
if(state == IN_WORD)
{
wl[thisword++] = token_duplicate(tokenstart, ++tokenlen);
}
wl[thisword] = NULL; /* list is NULL-terminated */
}
assert(thisword == wordcount);
return wl;
}

void wl_destroy(char ***wl)
{
if(wl != NULL)
{
if(*wl != NULL)
{
char **w = *wl;
while(*w != NULL)
{
free(*w++);
}
}
free(*wl);
*wl = NULL;
}
}

void wl_print(char **wl)
{
while(*wl != NULL)
{
printf("%s\n", *wl++);
}
}

int main(int argc, char **argv)
{
while(argc 0)
{
char **wl = wl_build(argv[--argc]);
wl_print(wl);
printf("Integrity of arg: %s\n", argv[argc]);
wl_destroy(&wl);
}
return 0;
}

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 1 '08 #7
On Aug 31, 10:00 pm, stevenr...@gmail.com wrote:
Hello All

My question mainly is how to use/reference Double Pointers? I am
currently trying to understand what the meaning of a 'vector of
pointers' means also? What I am trying to do is take a char array and
break it up into words omitting the spaces. What needs to be noted is
that I am trying to accomplish this only using char ** and char *.
As a learning exercise: assume we don't #include <string.h?
Therefore, I am creating it from scratch. Below is code that I have
written so far:

int main()
{
char input[125] = " Hello World\0"
\0 is mostly redundant here. The string literal will implicitly have
a \0 character appended to its representation as an array of
characters.
char **doublePointer;
array_of_c_strings would be a more descriptive name.
char *receiveArray;

doublePointer = malloc(125 * sizeof(char *));
receiveArray = input;
There's an easy rewrite to prepare this for isolating into a function,
but as a concept mockup this works. The rewrite also makes the code
C90-friendly. (right now it's using the C99 feature of intermixing
declarations and code).

In this case, it's a matter of coding style whether to use calloc or
malloc for doublePointer. Due to how things are defined in C, calloc
will automatically set all of the pointers in the dynamically
allocated array to NULL.
int i;
for(i = 0; receiveArray [ i ] != '\0'; i++)
{
//Here I am confused
//I'm not sure how to traverse the array and store data into
// the double pointer/vector
The loop is using i to traverse the array fine. It's what to do that
matters.
//Do I need to do this
// doublePointer [ i ] = malloc ( sizeof( char * ));
i is already being used to traverse receiveArray, so it should not be
used to index into doublePointer. For sake of discussion, assume we
declared another variable

int j = 0;

before entering the loop.

Also, the proposed malloc is mismatched. Once allocated, the "slots"
in the array of char* pointed to by doublePointer will be perfectly
fine to use directly to point to C strings. The malloc expression
would be read as intending to allocate a char** (array of char*), but
doublePointer[j] is of type char* .

Having ruled out strtok as an option, you would be wanting to allocate
an array of char for each token, of length one longer than the
observed token length. As 1==sizeof(char) for standard-compliant
compilers, you could get away with something like the following:

doublePointer[j] = malloc(token_length+1); /* alternately,
malloc((token_length+1)*sizeof(char)) to look like the other malloc */
doublePointer[j][token_length+1] = '\0'; /* plain 0 also works in
place of '\0' */
strncpy(doublePointer[j],receiveArray+i,token_length); /* requires
#include <string.h>, could use a for-loop to hand-roll copying
token_length characters like this */
++j; /* adjust strict upper bound upwards. j++; also works. */

where token_length is some expression you calculated using the other
variables you need to even track being in a strtok-compatible word, as
well as i.
Sep 1 '08 #8
za*****@zaimoni.com said:

<snip>
In this case, it's a matter of coding style whether to use calloc or
malloc for doublePointer.
No, malloc is the better choice.
Due to how things are defined in C, calloc
will automatically set all of the pointers in the dynamically
allocated array to NULL.
Only on platforms where the representation of NULL is all-bits-zero, and
real platforms exist on which it is not. (ISTR that the FAQ mentions them
- feel free to go look it up if you wish.)

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 1 '08 #9
On Sep 1, 2:55 am, Richard Heathfield <r...@see.sig.invalidwrote:
zaim...@zaimoni.com said:

<snip>
In this case, it's a matter of coding style whether to use calloc or
malloc for doublePointer.

No, malloc is the better choice.
As a correct implementation can be explicitly verified to never
inspect the values in the malloc'd array in the first place, malloc is
the objectively better choice; the implied memset call has no
observable effect.

(Regardless of whatever style guidelines that are in force at a
specific locale, and whether portability to platforms from the age of
the computing dinosaurs where the binary representation of NULL is not
all-zero-bits is a concern. Obviously, the following paragraph should
have been qualified with "for typical platforms".)
Sep 1 '08 #10
On Mon, 1 Sep 2008 08:43:08 -0700 (PDT), za*****@zaimoni.com wrote:
>On Sep 1, 2:55 am, Richard Heathfield <r...@see.sig.invalidwrote:
>zaim...@zaimoni.com said:

<snip>
In this case, it's a matter of coding style whether to use calloc or
malloc for doublePointer.

No, malloc is the better choice.

As a correct implementation can be explicitly verified to never
inspect the values in the malloc'd array in the first place, malloc is
the objectively better choice; the implied memset call has no
observable effect.
At the very least it wastes time. At the worst, it creates the false
impression that the pointers have been properly initialized.
>
(Regardless of whatever style guidelines that are in force at a
specific locale, and whether portability to platforms from the age of
the computing dinosaurs where the binary representation of NULL is not
all-zero-bits is a concern. Obviously, the following paragraph should
You really believe that there are no modern systems that can support
accessing location 0? Even when using C to write the operating
system?
>have been qualified with "for typical platforms".)
--
Remove del for email
Sep 1 '08 #11
On Mon, 1 Sep 2008 00:42:34 -0700 (PDT), za*****@zaimoni.com wrote:
>On Aug 31, 10:00 pm, stevenr...@gmail.com wrote:
>Hello All

My question mainly is how to use/reference Double Pointers? I am
currently trying to understand what the meaning of a 'vector of
pointers' means also? What I am trying to do is take a char array and
break it up into words omitting the spaces. What needs to be noted is
that I am trying to accomplish this only using char ** and char *.

As a learning exercise: assume we don't #include <string.h?
>Therefore, I am creating it from scratch. Below is code that I have
written so far:

int main()
{
char input[125] = " Hello World\0"

\0 is mostly redundant here. The string literal will implicitly have
a \0 character appended to its representation as an array of
characters.
The literal, if it exists in the object module, will indeed have a
second '\0' appended to it. The array named input, however, will
consist of 11 characters followed by 114 '\0's independent of whether
there are any '\0's specified or implied in the initialization.

--
Remove del for email
Sep 1 '08 #12
In article <A8******************************@bt.com>
Richard Heathfield <rj*@see.sig.invalidwrote:
>Let's start by counting the number of words in the input string ...
[which results in]
>size_t wc(const char *s)
{
size_t count = 0;
int state = NOT_IN_WORD;
int space = 0;
while(*s != '\0')
{
space = isspace((unsigned char)*s);
if(state == NOT_IN_WORD && !space)
{
++count;
state = IN_WORD;
}
else if(state == IN_WORD && space)
{
state = NOT_IN_WORD;
}
++s;
}
return count;
}
>... now we'd like to point at them. ...
Here, then, is a function to do that. Observe its similarities and
differences with regard to wc() - which it itself calls, by the way:

#include <stdlib.h>
#include <assert.h>
char **wl_build(char *s)
{
int space = 0;
int state = 0;
size_t thisword = 0;
size_t wordcount = wc(s);
char **wl = malloc((wordcount + 1) * sizeof *wl);
if(wl != NULL)
{
while(*s != '\0')
{
space = isspace((unsigned char)*s);
if(state == NOT_IN_WORD && !space)
{
wl[thisword++] = s;
state = IN_WORD;
}
else if(state == IN_WORD && space)
{
*s = '\0'; /* terminate the token */
state = NOT_IN_WORD;
}
++s;
}
wl[thisword] = NULL; /* list is NULL-terminated */
}
assert(thisword == wordcount);
return wl;
}

The alternative to doing this whole state machine thing twice is to count
and reallocate as we go. Possible, and microscopically faster, but perhaps
more effort than we'd like to go to, and the code would be messier, harder
to follow, and harder to maintain.
Given the similarities and differences, I would consider one other
tweak. Suppose we rewrite both wc() and wl_build() in terms of a
third function. This third function is passed a "word list pointer"
value, which may be given as NULL, as well as a string ("s" above)
to split up into words. It counts the words, and -- if and only
if the word-list-pointer is non-NULL -- records and breaks up the
words as well. This results in:

static int wc_and_optionally_build(char *s, char **wl) {
size_t count = 0;
int state = NOT_IN_WORD;
int space = 0;

while (*s != '\0') {
space = isspace((unsigned char)*s);
if (state == NOT_IN_WORD && !space) {
if (wl != NULL) /* record start of token */
wl[count] = s;
count++;
state = IN_WORD;
} else if (state == IN_WORD && space) {
if (wl != NULL)
*s = '\0'; /* terminate the token */
state = NOT_IN_WORD;
}
++s;
}
return count;
}

(I have made this "static" as it is not intended to be used by
any callers other than the two we are about to supply.)

Now we can rewrite both wc() and wl_build() in terms of this third
function, which exposes a slight flaw or two:

size_t wc(const char *s) {
return wc_and_optionally_build((char *)s, NULL);
}

char **wl_build(char *s) {
size_t wordcount = wc(s);
char **wl = malloc((wordcount + 1) * sizeof *wl);

if (wl != NULL) {
size_t repeat = wc_and_optionally_build(s, wl);

assert(repeat == wordcount);
wl[repeat] = NULL;
}
return wl;
}

The first flaw is that we have to "cast away const" in wc(), because
wc_and_optionally_build() *might* write to *s. It does not in fact
write to *s as long as we pass NULL as the second argument.

The second flaw (or perhaps non-flaw) is that this code does not
fail the assert() if the malloc() fails. Instead, this code has
wl_build() return NULL. Richard's version will fail the assert
(unless of course you turn on NDEBUG) for any non-empty word list
(because "wordcount" will be non-zero, but "thisword" will be 0).
>The creation of token copies allows us to leave the original string
unmodified ...
and, if you use a third "base" function to "do the real work",
allows one to fix the first flaw.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
Sep 1 '08 #13
On Sep 1, 2:14 pm, Barry Schwarz <schwa...@dqel.comwrote:
On Mon, 1 Sep 2008 08:43:08 -0700 (PDT), zaim...@zaimoni.com wrote:
(Regardless of whatever style guidelines that are in force at a
specific locale, and whether portability to platforms from the age of
the computing dinosaurs where the binary representation of NULL is not
all-zero-bits is a concern. ....

You really believe that there are no modern systems that can support
accessing location 0?
Accessing location zero is different than compiling a program so that
some C entity actually has location zero. E.g., I'd expect location
zero to be accessible (with suitable privileges) in C on an Intel
platform simply because that's the start of the hardware interrupt
vector table. That doesn't mean a C variable or function could
actually be compiled to live there.

As for a compiler placing entities at location zero:
Extant? Sure, such systems exist and remain in use. They don't seem
to be very high on the porting priority list for the FSF, as the use
of calloc to NULL-initialize pointer arrays is explicitly approved in
their portability checklist.

Chronologically new design? I wouldn't be surprised at all, even
though I don't have an example "on tap".

Vaguely modern design? Theoretically possible -- but I'd be surprised
if an example actually existed.
Sep 1 '08 #14
Chris Torek said:

<snip>
The second flaw (or perhaps non-flaw) is that this code does not
fail the assert() if the malloc() fails. Instead, this code has
wl_build() return NULL. Richard's version will fail the assert
(unless of course you turn on NDEBUG) for any non-empty word list
(because "wordcount" will be non-zero, but "thisword" will be 0).
I have to confess that the assert was in any case mere scaffolding, which I
ought to have removed before posting. I actually put it in for debugging
purposes, but this particular assertion has no business being in the final
code because it can be fired by a runtime resource shortage as well as by
a programming error. (The assertion helped me to find such an error, but
it was nevertheless the wrong tool for the job in this case.)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 2 '08 #15

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

Similar topics

11
by: Bob Hairgrove | last post by:
The following class contains start and end points of a range of values. The range can have a direction which is implied from the relative order of start and end, or it can be without direction. IOW...
3
by: kohvirus | last post by:
Well after embaressing myself and posting in the wrong fourm, I found my way to the right one and I'm hoping to seek some help. This is the program without any modifications that I am making...
5
by: Sona | last post by:
I understand the problem I'm having but am not sure how to fix it. My code passes two char* to a function which reads in some strings from a file and copies the contents into the two char*s. Now...
5
by: JS | last post by:
I give a function a void pointer as an argument. But in the function I would like to treat this argument as an integer (only pointers to integers will be sent to the function) therefor I would like...
4
by: pcnate | last post by:
I've been having some problems with pointers and such.This is homework, so I don't want people writing codeand telling me to use it. I just want some direction on what isn't working. here is...
9
by: bwaichu | last post by:
I am starting this thread after having run into two separate programming problems, where the compiler offered no help. The compiler did not even warn. The programs compiled fine. And the...
9
by: olf | last post by:
Hello all, I have very recently trying to make a small program in c++ and I am having problems with pointers. I want to read a line from a file, send that line to a function that parses and...
10
by: Jess | last post by:
Hello, I have a program that stores dynamically created objects into a vector. #include<iostream> #include<vector> using namespace std;
84
by: jacob navia | last post by:
As many people know, I think that garbage collection is a good solution for many memory allocation problems. I am aware however, that nothing is "the silver bullet", not even the GC. A recent...
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
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
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: 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...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.