Suppose I have a 2D array of characters, which will define a screen, like this one:
char consoleBuffer[20][50];
How can I put a row of this 2D array (which will be a text line in a string? (char*)
sprintf doesn't seem to work (or maybe i'm using it wrongfully).
The following example tries to read 1 line of this 2D character field and write it in a string... unsuccesfully, because the program crashes when it's executed.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-06
I allready made it work :) sry for the topic.
I managed it by this:
char temp[50];
temp = consoleBuffer[1];
Greetz,
Vich
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-06
In C you cannot assign strings.
What you have done allocated 50 bytes, then assigned a pointer to the first line to temp. So your original 50 bytes are now orphaned, and temp points to the actual line not a copy of it!
In C++ you can assign objects of the class 'string' but that is done through operator overloading. A C style string is not an object so will not support this.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-06
1) temp is a pointer to an empty string so you have reserved only 1byte (the NUL) for the string.
2) Your format string is expexting a string, followed by a character. This is probably not what you want, but even so you have only provided a single parameter.
3) this won't compile because of the extraneous ; in the sprintf() call.
4) consoleBuffer[1][j] is a single character, not a string, it will be interpreted incorrectly as a char pointer becaise of the %s.
You have not specified, and your code does not make it clear, but I would expect consoleBuffer to be a character array with spaces in the unoccupied characters (rather than an array of strings). The following code makes that assumption.
#define SCREEN_WIDTH 50
char temp[SCREEN_WIDTH + 1] ; /* width plus one for NUL */
temp[SCREEN_WIDTH] = '\0' ; /* ensure line has nul terminator */
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-06
Only if that is what you intended, but probably not!
The code in the original post was attempting to copy the screen data to a new array. This code just assigns a pointer to the actual screen data.
In this case, if you change the data pointed to by temp, the data at consoleBuffer[1] will also be changed (because it is the same).
This may be exactly what you want, or you may not want to change the data through tems at all. In which case referencing the data through a pointer is more efficient than copying it to a new location, but then why not just access it through consoleBuffer[1], which is why is say it is probably not what you want to do.
Please sign your posts with something if you wish to be a "nobody". I can't tell who is asking the questions!
Clifford.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-06
I have an array of strings (char*), and if I want to add one, then it will be added at the end of the string, which will push all other strings up, like this:
when adding "d" to this array:
{"a","b","c"}
will result in:
{"b","c","d"}
The following code should work, but it doesn't. Not even when I try to use strcpy (that just don't work).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-06
Again you need to understand that a pointer is just that, it points to some data that exists.
consoleBuffer in this example is an array of pointers - not an array of strings, no memory has been allocated to hold a string, just the pointer. If you pass a string to your function, the function places a pointer to that string into the consoleBuffer[] array. It does not copy the string to an new place. If you used strcpy(), you would need somewhere to copy the data to, but you only have an array of pointers to nothing!
So if the string that the parameter 'text' points to, ceases to exist (by going out of scope), the memory that the pointers in consoleBuffer[] point to may get reused. This will happen if the string you are passing is a local auto variable (i.e. not static).
What is actually happening depends on how you are calling the function, and what you actually want to do, but you may try this approach:
static char* consoleBuffer[CNS_LINES];
void Cns_Addline(char* text)
{
int i ;
/* Free up th ememory for the line to be discarded */
if( consoleBuffer[0] != NULL )
{
free( consoleBuffer[0] ;
}
/* move existing pointers up one line */
for( i = 0; i < CNS_LINES - 1 && consoleBuffer[i] != NULL; i++)
{
consoleBuffer[i] = consoleBuffer[i+1];
}
/* Allocate memory for new line */
consoleBuffer[i] = (char*)malloc( strlen(text) + 1) ;
/* Copy new line to allocated memory */
strcpy( consoleBuffer[i], text ) ;
}
void Cns_DeleteAll()
{
int i ;
/* Free up all allocate memory */
for( i = 0; i < CNS_LINES - 1 && consoleBuffer[i] != NULL; i++)
{
free( consoleBuffer[i] ) ;
consoleBuffer[i] = NULL ; /* just in case AddLine is called later */
}
}
This version dynamically allocates the memory required for the strings. I have added a function to free up any memory when you are finished - this should be called before your program terminates to prevent memory leaks. I have also added code so that lines are correctly added when there are fewer that CNS_LINES. Note that ANSI C guarantees that static data is initialised with zero, so consoleBuffer[] will initially contain NULL pointers. I have added the static stroage class to consoleBuffer[] to force its scope to just this module, since it need not have global linkage if all the access functions are in the same file (good practice).
CAUTION: untested code, but it should get you started.
An alterantive solution would have a 2D char array to avoid the dynamic allocation, but the method shown allows lines of any length, and the 2D array method would have to use strcpy() to move all the strings, rather than just the pointers (faster), (unless you used it as a circular buffer, and maintained an index to the first line, but I'll let you consider that one!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-06
anyone? i don't understand it. i do know it's something about pointers, but I don't see why strcpy() doesn't work. can anyone give me a solution?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks a lot, I weren't available this weekend, so sorry about this late reply. I'm gonna check this code as soon as possible.
Greetz,
Ken
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-10
@slocombe ( Clifford Slocombe ):
Thanks a lot for your code, it compiled (almost) flawlessly and I finally got my console to work properly(I'm working on a 3D engine). Thanks to you, I now understand 'malloc' and 'free' in C++. If you want, then I can put you in the credits of my program? If so: please tell me what you want me to put there (name/nick/both?).
Greetz,
Ken
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2003-02-10
I normally use my own name. If you credit me make sure it is good! ;-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Suppose I have a 2D array of characters, which will define a screen, like this one:
char consoleBuffer[20][50];
How can I put a row of this 2D array (which will be a text line in a string? (char*)
sprintf doesn't seem to work (or maybe i'm using it wrongfully).
The following example tries to read 1 line of this 2D character field and write it in a string... unsuccesfully, because the program crashes when it's executed.
char* temp="";
for (int j=0; j<50; j++)
{
sprintf(temp, "%s%c", consoleBuffer[1][j];);
}
I allready made it work :) sry for the topic.
I managed it by this:
char temp[50];
temp = consoleBuffer[1];
Greetz,
Vich
In C you cannot assign strings.
What you have done allocated 50 bytes, then assigned a pointer to the first line to temp. So your original 50 bytes are now orphaned, and temp points to the actual line not a copy of it!
In C++ you can assign objects of the class 'string' but that is done through operator overloading. A C style string is not an object so will not support this.
Clifford
1) temp is a pointer to an empty string so you have reserved only 1byte (the NUL) for the string.
2) Your format string is expexting a string, followed by a character. This is probably not what you want, but even so you have only provided a single parameter.
3) this won't compile because of the extraneous ; in the sprintf() call.
4) consoleBuffer[1][j] is a single character, not a string, it will be interpreted incorrectly as a char pointer becaise of the %s.
You have not specified, and your code does not make it clear, but I would expect consoleBuffer to be a character array with spaces in the unoccupied characters (rather than an array of strings). The following code makes that assumption.
#define SCREEN_WIDTH 50
char temp[SCREEN_WIDTH + 1] ; /* width plus one for NUL */
temp[SCREEN_WIDTH] = '\0' ; /* ensure line has nul terminator */
memcpy( temp, consoleBuffer[line], SCREEN_WIDTH ) ;
If each line is a NUL terminates string, then simply:
#define SCREEN_WIDTH 50
char temp[SCREEN_WIDTH + 1] ; /* width plus one for NUL */
strcpy( temp, consoleBuffer[line] ) ;
Your approach could work if modified thus:
#define SCREEN_WIDTH 50
char temp[SCREEN_WIDTH + 1] ; /* width plus one for NUL */
for (int j=0; j<SCREEN_WIDTH; j++)
{
sprintf(temp, "%c", consoleBuffer[line][j] ) ;
}
OR again if the buffer contains NUL terminated strings:
#define SCREEN_WIDTH 50
char temp[SCREEN_WIDTH + 1] ; /* width plus one for NUL */
sprintf(temp, "%s", consoleBuffer[line] ) ;
Take your pick, but sprintf() is a bit over the top for this purpose.
Clifford
should be like so, no?
char *temp;
temp = consoleBuffer[1];
Only if that is what you intended, but probably not!
The code in the original post was attempting to copy the screen data to a new array. This code just assigns a pointer to the actual screen data.
In this case, if you change the data pointed to by temp, the data at consoleBuffer[1] will also be changed (because it is the same).
This may be exactly what you want, or you may not want to change the data through tems at all. In which case referencing the data through a pointer is more efficient than copying it to a new location, but then why not just access it through consoleBuffer[1], which is why is say it is probably not what you want to do.
Please sign your posts with something if you wish to be a "nobody". I can't tell who is asking the questions!
Clifford.
I have an array of strings (char*), and if I want to add one, then it will be added at the end of the string, which will push all other strings up, like this:
when adding "d" to this array:
{"a","b","c"}
will result in:
{"b","c","d"}
The following code should work, but it doesn't. Not even when I try to use strcpy (that just don't work).
char* consoleBuffer[CNS_LINES];
void Cns_Addline(char* text)
{
for (int i=0; i<CNS_LINES-1; i++)
{
consoleBuffer[i] = consoleBuffer[i+1];
}
consoleBuffer[CNS_LINES-1] = text;
}
Again you need to understand that a pointer is just that, it points to some data that exists.
consoleBuffer in this example is an array of pointers - not an array of strings, no memory has been allocated to hold a string, just the pointer. If you pass a string to your function, the function places a pointer to that string into the consoleBuffer[] array. It does not copy the string to an new place. If you used strcpy(), you would need somewhere to copy the data to, but you only have an array of pointers to nothing!
So if the string that the parameter 'text' points to, ceases to exist (by going out of scope), the memory that the pointers in consoleBuffer[] point to may get reused. This will happen if the string you are passing is a local auto variable (i.e. not static).
What is actually happening depends on how you are calling the function, and what you actually want to do, but you may try this approach:
static char* consoleBuffer[CNS_LINES];
void Cns_Addline(char* text)
{
int i ;
/* Free up th ememory for the line to be discarded */
if( consoleBuffer[0] != NULL )
{
free( consoleBuffer[0] ;
}
/* move existing pointers up one line */
for( i = 0; i < CNS_LINES - 1 && consoleBuffer[i] != NULL; i++)
{
consoleBuffer[i] = consoleBuffer[i+1];
}
/* Allocate memory for new line */
consoleBuffer[i] = (char*)malloc( strlen(text) + 1) ;
/* Copy new line to allocated memory */
strcpy( consoleBuffer[i], text ) ;
}
void Cns_DeleteAll()
{
int i ;
/* Free up all allocate memory */
for( i = 0; i < CNS_LINES - 1 && consoleBuffer[i] != NULL; i++)
{
free( consoleBuffer[i] ) ;
consoleBuffer[i] = NULL ; /* just in case AddLine is called later */
}
}
This version dynamically allocates the memory required for the strings. I have added a function to free up any memory when you are finished - this should be called before your program terminates to prevent memory leaks. I have also added code so that lines are correctly added when there are fewer that CNS_LINES. Note that ANSI C guarantees that static data is initialised with zero, so consoleBuffer[] will initially contain NULL pointers. I have added the static stroage class to consoleBuffer[] to force its scope to just this module, since it need not have global linkage if all the access functions are in the same file (good practice).
CAUTION: untested code, but it should get you started.
An alterantive solution would have a 2D char array to avoid the dynamic allocation, but the method shown allows lines of any length, and the 2D array method would have to use strcpy() to move all the strings, rather than just the pointers (faster), (unless you used it as a circular buffer, and maintained an index to the first line, but I'll let you consider that one!
anyone? i don't understand it. i do know it's something about pointers, but I don't see why strcpy() doesn't work. can anyone give me a solution?
Thanks a lot, I weren't available this weekend, so sorry about this late reply. I'm gonna check this code as soon as possible.
Greetz,
Ken
@slocombe ( Clifford Slocombe ):
Thanks a lot for your code, it compiled (almost) flawlessly and I finally got my console to work properly(I'm working on a 3D engine). Thanks to you, I now understand 'malloc' and 'free' in C++. If you want, then I can put you in the credits of my program? If so: please tell me what you want me to put there (name/nick/both?).
Greetz,
Ken
I normally use my own name. If you credit me make sure it is good! ;-)