@freddix What you are trying to do doesn't really make sense. You need to allocate new memory (for a new string), put whatever you want in the new string, and then put the string's pointer in place of the old string.
BTW, strcpy will NOT resize the target sting. If you try, it will write past the end of the string, and most likely corrupt something (crash if you are lucky, corrupt data if you are not).
If you were using E instead of C for coding, then I'd write some code as an example... (Personally I don't feel that C is a good language to learn this kind of stuff, due to the horrid way it handles pointers vs non-pointers.)
Like ChrisH said, you have to reallocate the memory yourself. In C++ there's a string class that does it all for you, but in C it's up to you. No, strcpy won't reallocate memory.
// Changing window title to winTitle2 windowTitle = winTitle2;
// Dynamic strings example
const char winTitle1[] = "Title 1";
char *windowTitle = (char*)malloc(strlen(winTitle1) + 1); // +1 for the NULL terminator strcpy(windowTitle, winTitle1);
// Now replace the string with a new one const char winTitle2[] = "A new title"; free(windowTitle); // Deallocating the old string windowTitle = (char*)malloc(strlen(winTitle2) + 1); strcpy(windowTitle, winTitle2);
Which should you use? Well, if there are only a few things that the window title could be, the first example is appropriate. However, if you will be dynamically changing the window title (e.g., multiple strings are combined, or a filename is used, etc.), then dynamically allocating memory is the best option.
WARNING: The above example does no error checking. You should always check if a memory allocation fails.
There's an article I read in an old issue of (the now defunct) Dr. Dobb's Journal that addresses a similar problem: run-time array allocatiob in C. It uses single/nested pointers in a way that creates 1/2D arrays which can be allocated on-the-fly, and can be used anywhere normal 1D and 2D arrays are used. The code doesn't include array extension, but they can be de-allocated and re-allocated during run-time, and the code could probably be modified to permit array extension.
It's too much code to in-line here; I'll send it if you are interested.
I've had the same problem recently, trying to convert my palmos databook database to lipidclock reminder format. Luckily, I just do:
char *string; if((string=malloc(strlen("string to enter"))!=0) { sprintf(string, "%s", "string to enter"); } else { printf("Memory allocation error!\a\n"); }
To swap different string, I guess you need to use the (previously mentioned) realloc() command, eg.. char *string1 = "first string"; char *string2 = "second string"; char *changestring;
Also, I prefer to use sprintf() instead of strcpy, the additional formatting options are very useful. (personal preference though). Sprintf uses the same args as printf, the pointer before the format string is where you put the array name)
I've made extensive use of a couple of websites that have been quite life-savers for looking up stuff, too. cplusplus.com, though you have to be careful with this one if you're using straight C, and not C++. Plus, the language can be kinda thick at times, though it has some good example code.
C Programming Reference is one I found the other day, but it looks like beginner-level example code. Also DOS/X86 based afaik.
I've been getting used to the memory allocation probs myself, having trashed my system memory to the point of requiring a cold reset. (I'm using BlizKick to set up a custom 3.9+goodies kickstart, which isn't "locked", resulting in a restart and a lovely red screen when it gets trashed. Using RTG means I need to flip the VGA switch to even see that...)
EDIT: If you go to those links via Ibrowse, you may want to disable javascript to speed things up a bit. (I have them in the URL prefs w/ Javascript disabled)
Thank you to each of you. in fact, I think I will use another approach. I've made a command to Create/Delete string :
void CreateDeleteString( char * ZePointer, int NewSize ){
// We'll free the word defined at * ZePointer
if ( NewSize == 0 ){
if ( ZePointer != 0 ){
free( ZePointer );
ZePointer = 0;
}
}
// we allocate NewSize bytes to fit the need of the word to create
if ( NewSize != 0 ){
ZePointer = malloc( ( NewSize * sizeof( char ) ) + 1 );
}
}
Used with NewSize of 0 will delete the string from memory. Used with a newsize, it will alloc memory for the string. And then I'll do memory copy with 2 strings pointers when needed :p
What do you think about this idea ?
Regards, AmiDARK
Edited by freddix on 2009/9/15 23:55:30
All we have to decide is what to do with the time that is given to us.
Your example code doesn't allocate space for the null-terminator character (malloc size should be strlen()+1) so it will always write one byte past the memory allocation.
Thank you to each of you. in fact, I think I will use another approach. I've made a command to Create/Delete string :
void CreateDeleteString( char * ZePointer, int NewSize ){
// We'll free the word defined at * ZePointer
if ( NewSize == 0 ){
if ( ZePointer != 0 ){
free( ZePointer );
ZePointer = 0;
}
}
// we allocate NewSize bytes to fit the need of the word to create
if ( NewSize != 0 ){
ZePointer = malloc( ( NewSize * sizeof( char ) ) + 1 );
}
}
Used with NewSize of 0 will delete the string from memory. Used with a newsize, it will alloc memory for the string. And then I'll do memory copy with 2 strings pointers when needed :p
What do you think about this idea ?
Regards, AmiDARK
This code won't work because you're writing a new pointer to ZePointer, but that's a local pointer; the calling code's pointer will remain unchanged. Also, you could have a memory leak if NewSize != 0 and you reallocate ZePointer.
Try something like this:
void ReAllocString( char **ZePointer, int NewSize ){
// We'll free the word defined at * ZePointer
if (*ZePointer)
{
free( *ZePointer );
*ZePointer = 0;
}
// we allocate NewSize bytes to fit the need of the word to create
if ( NewSize != 0 ){
*ZePointer = malloc( ( NewSize * sizeof( char ) ) + 1 );
}
}
The code above has a pointer to the original pointer to the string, so we update that pointer, rather than a local variable.
I recommend that you create functions that do a bit more, such as copyString(), concatenateString() and also have allocString()/freeString(). The best thing to do would be to create a string Abstract Data Type (ADT). Something like:
typedef struct String_s
{
char *string;
int allocLength;
} String;
By ... I mean that I'm too lazy to write everything out.
This way you can easily hide all of the nasty details of manipulating strings in one source file, and won't make mistakes such as trying to reallocate a string that wasn't allocated with malloc() in the first place.
Hans
EDIT: Just found a bad bug in the example that I gave
One could make a C++ class with proper resize functions and assertions for access beyond the allocated size. And add to the mix proper equivalents for string functions . And also make it a template class to unbind the array from specific data type.
I bet STL has something that does that.
Jack
"the expression, 'atonal music,' is most unfortunate--it is on a par with calling flying 'the art of not falling,' or swimming 'the art of not drowning.'. A. Schoenberg
That's why strlcpy() was invented. Using non-size-checking functions and just "assuming" that the allocated size is sufficient should be punished with something really ugly. They may trash memory and you don't even notice it immediately and hunting such bugs is a real PITA.
@tboeckel Or in AmigaE (and PortablE) you use special "e-strings", which know their size, so it is impossible to trash memory when copying or appending to them...
One could make a C++ class with proper resize functions and assertions for access beyond the allocated size. And add to the mix proper equivalents for string functions . And also make it a template class to unbind the array from specific data type.