Sign in to follow this  
dev578

Problems with char*

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
With c style strings, you're supposed to do the following:

/* We need functions */
#include <string.h>

/* Allocate space. */
#define BUFFER_SIZE 256
char 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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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-equivalent
char 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 .

Share this post


Link to post
Share on other sites
me22: Thanks for the link, I was speaking from my experiences.

OFF TOPIC (sorry OP)

The problem with this


std::string my_string = "asd";
std::string other_string = my_string+"l";


is that there are many mechanisms going on that aren't shown. Hence understanding how this actually works is, imho, more difficult, but necessary to be able to use the features of C++.
Eg.. the user might see this code and then attempt to do something like this:


std::string helloString = "hello" + "there";


Which (according to my compiler) will not compile:

test.cpp: In function `int main()':
test.cpp:7: error: invalid operands of types `const char[8]' and `const char[4]' to binary `operator+'


Now ask the user why that is, and because of your string ADT abstraction, he/she will not have a clue. That's the problem with C++ as a first language.

Share this post


Link to post
Share on other sites
try this one......


int g_SomeInt = 0;
char* g_Text = new char[1]; // previously char* g_Text = "";


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


void SomeFunction(char* Text)
{
if (strcmp(g_Text,Text)==0)
return;

//some more code

// g_Text = Text; is replaced with the codes below

// delete previous contents of g_Text
// create g_Text with Text's size (plus 1 for the null terminator)
// copy contents of Text to g_Text
if(g_Text)
{
delete [] g_Text;
g_Text = NULL;
}
int i = strlen(Text)+1;
g_Text = new char[i];
strcpy(g_Text,Text);
}




......although this is already a C code, try using string instead......

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this