Problems with char*

Started by
10 comments, last by jetxmx 18 years, 9 months ago
I have been using char* as a string, but I am having a problem. I will just try to explain it using code:

//I am writing this off the top of my head, to show my problem:
int g_SomeInt = 0;
char* g_Text = "";

void SomeFunctionCalledOncePerFrame()
{
     char String[512];
     g_SomeInt++;
     sprintf(String,"Number:  %i",g_SomeInt);
     SomeFunction(String);
}

void SomeFunction(char* Text)
{
     if (g_Text == Text)
          return;
     
     //some more code

     g_Text = Text;
}

g_Text is supposed to store the text from the last time the function was called, so when the Text supplied to the function changes, it is not supposed to return, however, it always returns (except for the first time). I think I may know why, because g_Text is a char*, it is actually a pointer, so it is pointing to the Text, so when the text changes, g_Text changes as well, and therefore, g_Text will always equal Text. What is the best way around this? No matter what I try, g_Text is always equal to Text. I REALLY don't want to use a char array because then it would have to be a specified size, and the text supplied to this function varies dramatically. Any help is appreciated, -Dev578
Advertisement
Hmm, so what exactly are you trying to do? If you explain your intention then I can help...

Your code contains a few problems:
1. As soon as SomeFunctionCalledOncePerFrame() is exitted, the string pointed to by g_Text doesn't exist anymore...
2. Why do this?
char* g_Text = ""

Its just a waste of the data segment.
If you're using C++:
int g_SomeInt = 0;std::string g_Text = "";void SomeFunctionCalledOncePerFrame(){	SomeFunction("Number: " + boost::lexical_cast< std::string >(++g_SomeInt));}void SomeFunction(std::string const & text){	if (g_Text == text)	{		return;	}	//some more code	g_Text = text;}

Else:
int g_SomeInt = 0;char * g_Text = 0;void SomeFunctionCalledOncePerFrame(){	char string[std::strlen("Number: ") + MAX_DIGITS_IN_INT + 1];	sprintf(string, "Number: %i", ++g_SomeInt);	SomeFunction(string);}void SomeFunction(char const * const text){	if (g_Text && strcmp(g_Text, text) == 0)	{		return;	}	//some more code	free(g_Text);	g_Text = strdup(text);}

Or something like that.

Enigma
First, g_Text == Text compares the addresses of the strings involved not the content. Second, g_Text = Text makes (as you said) g_Text point to the memory location that Text points to (considering that Text is a local variable this is extremely bad).

Either use std::string or use the appropriate functions. That's strcmp and strcpy. However, using these functions requires you to allocate enough memory to hold the string in g_Text which you are currently not doing.
You need to learn how the stack works.
The stack is a special reserved memory in which all local variables and arguments are stored temporarily. 'char String[512]' is a local char array which will be stored on the stack. When the function returns this stack memory is freed, and ready to be used by other functions.

If you make g_Text point to an address on the stack you never know what it will contain, because every function you call use that memory for its own variables.

What you should do is allocate separate memory for g_Text when you need it.

#include <malloc.h>#include <string.h>char* g_Text = NULL;void SomeFunction(char* Text){    if(g_Text != NULL)        free(g_Text);  // Free the memory previously allocated    g_Text = (char *)malloc(strlen(Text) + 1);  // Allocate new memory    strcpy(g_Text, Text);  // Copy the entire string too g_Text}


Now g_Text will be allocated with the amount of space that is needed to store the string.
I highly recommend you use std::string if you're using C++!

Back to your problem, when you write g_Text == Text you are actually comparing pointers. What you actually need to do is to compare the strings, so you need to use strcmp. Also, at the end of SomeFunction, you're not doing what you think you are! You are actually assigning g_Text to point to the location of String (which is VERY bad, as String is a local variable. What you need to do is allocate g_Text some memory (using strlen to ge the string's length) AFTER you've checked to see if g_Text has already had some memory assigned. Then use strncpy to copy the string over.

Here's some code, but as you can see, there is a lot to do, which is why I recommend using a std::string
#include <cstddef>#include <string.h>int g_SomeInt = 0;char * g_Text = 0; //We are going to assign to it later!void SomeFunctionCalledOncePerFrame(){	g_SomeInt++;	char String[512];	sprintf(String, "Number:  %i", g_SomeInt);	SomeFunction(String);}void SomeFunction(const char * Text) //I'm sure you just missed off the const ;){	if (g_Text) //We may of not yet allocated g_Text	{		if (strcmp(g_Text, Text) == 0) //They match			return;	//some more code	}	delete g_Text; //Remember, it's safe to delete null pointers - no need to check for NULL!!	std::size_t stringLength = strlen(Text) + 1; //+1 for null terminator (can't remeber if it's needed, but best be safe!)	g_Text = new char[stringLength]; 	strncpy(g_Text, Text, stringLength);}


Now, for intrest, lets compare it with std::string

#include <cstddef>#include <sstream> //std::istringstream#include <string> //No ".h"//I am writing this off the top of my head, to show my problem:int g_SomeInt = 0;std::string g_Text;void SomeFunctionCalledOncePerFrame(){	std::istringstream buffer;	buffer << "Number:  " << ++g_SomeInt;	SomeFunction(buffer.str());}void SomeFunction(const std::string & Text) //Can also pass in a char *, such as "Hello world"!{	if (g_Text == Text) //std::string has comparison operators!          return;	//some more code	g_Text = Text; //How easy was that??}


Code has not been tested!
With c style strings, you're supposed to do the following:
/* We need functions */#include <string.h>/* Allocate space. */#define BUFFER_SIZE 256char g_Text[ BUFFER_SIZE ];/* And a test function */int do_something(){  strncpy( g_Text, "Its a cool thing.", BUFFER_SIZE );  g_Text[ BUFFER_SIZE - 1 ] = 0;  return 0;}


See, you don't assign c-styled strings. You COPY c-style strings. Make sure you always have enough memory assigned, and although everyone likes strcpy because its faster, I like strncpy because its safer, no segmentation faults.
william bubel
Quote:Original post by desertcube
I highly recommend you use std::string if you're using C++!


And if you're not using C++, I suggest you consider starting. Most C code will compile with a C++ compiler, and you can continue to do almost everything the way you do it in C, with the additional ability to use std::string and std::vector (for arrays).
Quote:Original post by Will F
And if you're not using C++, I suggest you consider starting.


I highly recommend that you don't start using C++ until you've mastered the basics of imperative programming with C. C's hard to learn for a beginner, C++ is harder..

Good luck.
That's debatable, Kuladus.
std::string my_string = "asd";std::string other_string = my_string+"l";//is much easier to learn than// the ugly C sortof-equivalentchar my_string[] = "asd";char other_string[16];strncpy( other_string, my_string, 16 );strncat( other_string, "l", 16 - strlen(other_string) );


Stroustrup has a nice paper on the topic: http://www.research.att.com/~bs/new_learning.pdf .

This topic is closed to new replies.

Advertisement