473,883 Members | 1,618 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

General method for dynamically allocating memory for a string

I have searched the internet for malloc and dynamic malloc; however, I still
don't know or readily see what is general way to allocate memory to char *
variable that I want to assign the substring that I found inside of a
string.

Any ideas?
Aug 30 '06 #1
94 4826
"smnoff" <34************ **@hotmail.comw rites:
I have searched the internet for malloc and dynamic malloc; however, I still
don't know or readily see what is general way to allocate memory to char *
variable that I want to assign the substring that I found inside of a
string.
If you want to allocate memory for a string, pass the number of
non-null characters in it, plus one, to malloc, then copy the
string into it, being sure to null-terminate the result.

If you can be more specific about what you're trying to do,
perhaps we can help with some details.
--
"I hope, some day, to learn to read.
It seems to be even harder than writing."
--Richard Heathfield
Aug 30 '06 #2
smnoff posted:
I have searched the internet for malloc and dynamic malloc; however, I
still don't know or readily see what is general way to allocate memory
to char * variable that I want to assign the substring that I found
inside of a string.

Any ideas?

Unchecked code, may contain an error or two:

#include <stdlib.h>
#include <stddef.h>
#include <assert.h>

char *to_release;

void ReleaseLastStri ng(void)
{
free(to_release );
}

char const *CreateSubstrin g(char const *const p,
size_t const istart,size_t const iend)
{
int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);

if(!p[iend+1]) return to_release = 0, p + istart;

to_release = malloc(iend - istart + 1);

memcpy(to_relea se,p,iend - istart);

to_release[iend - istart] = 0;

return to_release;
}

int main()
{
puts(CreateSubs tring("abcdefgh ijklmnop",2,7)) ;
ReleaseLastStri ng();

puts(CreateSubs tring("abcdefgh ijklmnop",4,15) );
ReleaseLastStri ng();
}

--

Frederick Gotham
Aug 31 '06 #3

"Frederick Gotham" <fg*******@SPAM .comwrote in message
news:r9******** ***********@new s.indigo.ie...
smnoff posted:
>I have searched the internet for malloc and dynamic malloc; however, I
still don't know or readily see what is general way to allocate memory
to char * variable that I want to assign the substring that I found
inside of a string.

Any ideas?


Unchecked code, may contain an error or two:

#include <stdlib.h>
#include <stddef.h>
#include <assert.h>

char *to_release;

void ReleaseLastStri ng(void)
{
free(to_release );
}

char const *CreateSubstrin g(char const *const p,
size_t const istart,size_t const iend)
{
int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);


Why are there double exclamation marks in the line show above?


Aug 31 '06 #4
Frederick's code is hard to read and harder to learn from. Here is
some fully checked code with lots of comments.
///////////////////////////////////////////////////////////////////////////////
// file: substr.c
// Note: C++ style comments are allowed for C99 compliant compilers.
///////////////////////////////////////////////////////////////////////////////
#include <stdlib.h // for malloc() and free()
#include <string.h // for strncpy()
#include <sys/types.h // for size_t
#include <stdio.h // for printf()

char * substr( char * string, size_t start, size_t end);

int main( void ) {

char *str1 = substr("abcdefg hijklmnop",2,7) ;
char *str2 = substr("abcdefg hijklmnop",4,15 );

if( str1 != NULL ) {
printf( "str1: %s\n", str1);
} else {
// Setting a null pointer to zero ensures you
// can delete it more than once (free) without
// undefined behavior. This is a good
// programming habit.
str1 = 0;
}

if( str2 != NULL ) {
printf( "str2: %s\n", str2 );
} else {
// Setting a null pointer to zero ensures you
// can delete it more than once (free) without
// undefined behavior. This is a good
// programming habit.
str2 = 0;
}

free( str1 );
free( str2 );

return 0;
}

/**
* Note: this function will return a newly allocated string. It
* is your responsibility to delete this memory to prevent a leak.
*
* param "string" - the string you want to extract a substring from.
* param "start" - the array index to begin your substring.

* param "start" - the array index to begin your substring.
* param "end" - the array index to terminate your substring.
*
* On Error: this function returns null;
*/
char * substr( char * string, size_t start, size_t end) {
// pointer to the substring on the heap
char *subString;

// calculate the total amount of memory needed
// to hold the substring.
// Algo: end - start + null terminator
size_t subStringSize = end - start + 1;

// request enough bytes to store the entire
// substring and null terminator.
subString = malloc( subStringSize );

// test to make sure we got the memory
// from malloc
if( subString != NULL ) {
// Note this copies one extra byte (the
// null terminator's spot) which is garbage.
// We have to terminate this string.
strncpy( subString, string + start, subStringSize );

subString[subStringSize] = '\0';
}

// This will either be NULL if we didn't get the
// memory from malloc or it will have our substring.
return subString;

} // end function substr
I hope this helps you.

-Randall
Frederick Gotham wrote:
smnoff posted:
I have searched the internet for malloc and dynamic malloc; however, I
still don't know or readily see what is general way to allocate memory
to char * variable that I want to assign the substring that I found
inside of a string.

Any ideas?


Unchecked code, may contain an error or two:

#include <stdlib.h>
#include <stddef.h>
#include <assert.h>

char *to_release;

void ReleaseLastStri ng(void)
{
free(to_release );
}

char const *CreateSubstrin g(char const *const p,
size_t const istart,size_t const iend)
{
int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);

if(!p[iend+1]) return to_release = 0, p + istart;

to_release = malloc(iend - istart + 1);

memcpy(to_relea se,p,iend - istart);

to_release[iend - istart] = 0;

return to_release;
}

int main()
{
puts(CreateSubs tring("abcdefgh ijklmnop",2,7)) ;
ReleaseLastStri ng();

puts(CreateSubs tring("abcdefgh ijklmnop",4,15) );
ReleaseLastStri ng();
}

--

Frederick Gotham
Aug 31 '06 #5
"smnoff" <34************ **@hotmail.comw rites:
"Frederick Gotham" <fg*******@SPAM .comwrote in message
news:r9******** ***********@new s.indigo.ie...
>smnoff posted:
>>I have searched the internet for malloc and dynamic malloc; however, I
still don't know or readily see what is general way to allocate memory
to char * variable that I want to assign the substring that I found
inside of a string.

Any ideas?


Unchecked code, may contain an error or two:

#include <stdlib.h>
#include <stddef.h>
#include <assert.h>

char *to_release;

void ReleaseLastStri ng(void)
{
free(to_release );
}

char const *CreateSubstrin g(char const *const p,
size_t const istart,size_t const iend)
{
int assert_dummy = (assert(!!p),as sert(!!istart), assert(!!iend), 0);

Why are there double exclamation marks in the line show above?
The assert() macro doesn't necessarily accept an argument of a type
other than int. (It does in C99, but not all compilers support C99.)

The ! (logical not) operator, applied to any scalar operand, yields
the int value 1 if the operand compares equal to 0, 0 if it doesn't.
A pointer value compares equal to 0 only if it's a null pointer. So
!p means "p is a null pointer". Applying it a second time reverses
the result, so !!p means "p is not a null pointer". !! normalizes a
scalar value, mapping 0 to 0 and anything else to 1.

So the declaration asserts that each of the pointers is non-null.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 31 '06 #6
On 30 Aug 2006 21:04:57 -0700, "Randall" <ra************ *@gmail.com>
wrote:
>Frederick's code is hard to read and harder to learn from. Here is
some fully checked code with lots of comments.
///////////////////////////////////////////////////////////////////////////////
// file: substr.c
// Note: C++ style comments are allowed for C99 compliant compilers.
///////////////////////////////////////////////////////////////////////////////
#include <stdlib.h // for malloc() and free()
#include <string.h // for strncpy()
#include <sys/types.h // for size_t
#include <stdio.h // for printf()

char * substr( char * string, size_t start, size_t end);

int main( void ) {

char *str1 = substr("abcdefg hijklmnop",2,7) ;
char *str2 = substr("abcdefg hijklmnop",4,15 );

if( str1 != NULL ) {
printf( "str1: %s\n", str1);
} else {
// Setting a null pointer to zero ensures you
// can delete it more than once (free) without
// undefined behavior. This is a good
// programming habit.
str1 = 0;
}

if( str2 != NULL ) {
printf( "str2: %s\n", str2 );
} else {
// Setting a null pointer to zero ensures you
// can delete it more than once (free) without
// undefined behavior. This is a good
// programming habit.
str2 = 0;
}

free( str1 );
free( str2 );

return 0;
}

/**
* Note: this function will return a newly allocated string. It
* is your responsibility to delete this memory to prevent a leak.
*
* param "string" - the string you want to extract a substring from.
* param "start" - the array index to begin your substring.

* param "start" - the array index to begin your substring.
* param "end" - the array index to terminate your substring.
*
* On Error: this function returns null;
*/
char * substr( char * string, size_t start, size_t end) {
// pointer to the substring on the heap
char *subString;

// calculate the total amount of memory needed
// to hold the substring.
// Algo: end - start + null terminator
size_t subStringSize = end - start + 1;

// request enough bytes to store the entire
// substring and null terminator.
subString = malloc( subStringSize );
Make that:

subString = malloc( subStringSize + 1 );
>
// test to make sure we got the memory
// from malloc
if( subString != NULL ) {
// Note this copies one extra byte (the
// null terminator's spot) which is garbage.
// We have to terminate this string.
strncpy( subString, string + start, subStringSize );

subString[subStringSize] = '\0';
Otherwise this indexes one past the end of malloc()ed memory, which is
undefined behavior.

Best regards
--
jay
Aug 31 '06 #7
Randall said:
Frederick's code is hard to read and harder to learn from. Here is
some fully checked code with lots of comments.
It didn't compile for me, so I just took a very quick look, and one thing
caught my eye:
if( str1 != NULL ) {
printf( "str1: %s\n", str1);
} else {
// Setting a null pointer to zero ensures you
// can delete it more than once (free) without
// undefined behavior. This is a good
// programming habit.
str1 = 0;
}
This is exactly equivalent to:

if(str1 != NULL) {
printf("str1: %s\n", str1);
}

The else is utterly unnecessary because, if str1 is not a null pointer, it
is never entered, and if it /is/ a null pointer, setting it to a null
pointer value is a redundant operation.
if( str2 != NULL ) {
printf( "str2: %s\n", str2 );
} else {
Likewise.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Aug 31 '06 #8
Randall posted:
#include <stdlib.h // for malloc() and free()
#include <string.h // for strncpy()
#include <sys/types.h // for size_t


Non-standard header. "stddef.h" contains "size_t".
#include <stdio.h // for printf()

char * substr(char * string, size_t start, size_t end);


First parameter should be "pointer to const".
int main( void ) {

char *str1 = substr("abcdefg hijklmnop",2,7) ;
char *str2 = substr("abcdefg hijklmnop",4,15 );


Both variables should be const. (You don't want the address to change
before you pass it to "free".)
if( str1 != NULL ) {
printf( "str1: %s\n", str1);
} else {
// Setting a null pointer to zero ensures you
// can delete it more than once (free) without
// undefined behavior. This is a good
// programming habit.
str1 = 0;
}

if( str2 != NULL ) {
printf( "str2: %s\n", str2 );
} else {
// Setting a null pointer to zero ensures you
// can delete it more than once (free) without
// undefined behavior. This is a good
// programming habit.
str2 = 0;
}


As Richard Heathfield pointed out, both "else" clauses are redundant.
free( str1 );
free( str2 );

return 0;
}

/**
* Note: this function will return a newly allocated string. It
* is your responsibility to delete this memory to prevent a leak.
*
* param "string" - the string you want to extract a substring from.
* param "start" - the array index to begin your substring.

* param "start" - the array index to begin your substring.
* param "end" - the array index to terminate your substring.
*
* On Error: this function returns null;
*/
char * substr( char * string, size_t start, size_t end) {


First parameter should be "pointer to const".
// pointer to the substring on the heap
char *subString;

// calculate the total amount of memory needed
// to hold the substring.
// Algo: end - start + null terminator
size_t subStringSize = end - start + 1;


Perhaps you should have written:

size_t len = end - start;

And then added the +1 only when malloc'ing.
// request enough bytes to store the entire
// substring and null terminator.
subString = malloc( subStringSize );


subString = malloc(len+1);
// test to make sure we got the memory
// from malloc
if( subString != NULL ) {
// Note this copies one extra byte (the
// null terminator's spot) which is garbage.
// We have to terminate this string.
strncpy( subString, string + start, subStringSize );


"memcpy" would be more efficient if you were strict about the length of
the string, e.g.:

assert( strlen(string) - istart >= len );
subString[subStringSize] = '\0';


Here you invoke undefine behaviour by writing past the end of the buffer.

subString[len] = 0;

You should _always_ check array indexes.
}

// This will either be NULL if we didn't get the
// memory from malloc or it will have our substring.
return subString;

} // end function substr
--

Frederick Gotham
Aug 31 '06 #9
Frederick Gotham <fg*******@SPAM .comwrote:
Randall posted:
#include <stdlib.h // for malloc() and free()
#include <string.h // for strncpy()
#include <sys/types.h // for size_t

Non-standard header. "stddef.h" contains "size_t".
So so <stdlib.h>, <string.h>, and...
#include <stdio.h // for printf()
.... <stdio.h>.

It is not often necessary to #include <stddef.h>. It is very rarely
necessary to do so just for the declaration of size_t. All headers whose
functions need it also declare it themselves, and it's a rare program
that does not use one of those headers.
char * substr(char * string, size_t start, size_t end);

First parameter should be "pointer to const".
No, it shouldn't, because that's not how the function is defined. It may
be a wise idea to _define_ it as a pointer to const char, or even a
const pointer to const char, and then also declare it as such, but
"should" is too strong.
if( str2 != NULL ) {
printf( "str2: %s\n", str2 );
} else {
// Setting a null pointer to zero ensures you
// can delete it more than once (free) without
// undefined behavior. This is a good
// programming habit.
str2 = 0;
}

As Richard Heathfield pointed out, both "else" clauses are redundant.
The reasoning given in the comment is also bogus. It is a very _bad_
programming habit to start expecting that you can free pointers twice.
// calculate the total amount of memory needed
// to hold the substring.
// Algo: end - start + null terminator
size_t subStringSize = end - start + 1;

Perhaps you should have written:

size_t len = end - start;

And then added the +1 only when malloc'ing.
Why?

Richard
Aug 31 '06 #10

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

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.