Problems with Strings

Started by
10 comments, last by v0dKA 20 years, 2 months ago
Today, I wrote a lot of code with a lot of errors (There's always a strange relationship between the two). The compiler misleadingly shows no errors, but when I run this program, there's some sort of "This program has performed an illegal operation" error sign, which I not much like. "If the problem persists, contact the program vendor", which, of course, is me, so that wasn't much help. When I debugged it, the debugger usually doesn't like my strings and arrays of strings and their respective pointers. Sometimes the problem is solved just by adding a set of []'s to the declaration statement, which temporarily revives my self esteem (after trying to solve it in ways that actually make sense millions of times -- adding []'s was something I tried hopelessly) My book is silent about this. Can anyone post common pitfalls with char arrays (in vc++) and how to solve them? Specifically I have a char* mystring = 0; Its contents will depend on users input inside a function (which I pass this string to). I then have yet another char char* arrayOfStrings[] = {0}; And this one will have plenty of mystring's , as in: arrayOfStrings[4] = mystring; mystring is run through a function many times, each time prompting for input which will them be stored to it, and later that mystring will be stored to arrayOfStrings as the next element. Debugger gots problems when I store something new in a string in statements such as: mystring[k] = *(userInput + j); Where k and j are just integers for whatever purpose which I happen to need. That may not be the source of the problem though -- might be in the defenition or what-not. Any ideas on what could POSSIBLY be wrong? ------------------------------------------------------------ .:<<-v0d[KA]->>:. [edited by - v0dKA on February 21, 2004 10:11:38 PM] [edited by - v0dKA on February 21, 2004 10:13:22 PM] [edited by - v0dKA on February 21, 2004 10:14:57 PM] [edited by - v0dKA on February 21, 2004 10:19:46 PM]
.:<<-v0d[KA]->>:.
Advertisement
Common problems:

* buffer overruns
* dangling pointers
* memory leaks

char* mystring = 0; - That''s a null pointer, it''s not pointing to any data. Nor is there any memory allocated to store any data.

char* arrayOfStrings[] = {0}; - The array can hold at most one pointer. [] means the size of the array is determined by the number of elements in the initializer.

arrayOfStrings[4] = mystring; - Trying to write into the 5th array cell... OOOPS there is no such cell.

Debugger gots problems when I store something new in a string - not surprising, since you never reserve any room to store those strings

Solutions:
* learn how to use arrays
* learn how to use pointers
* learn how to use the standard C++ std::string class.
* learn how to make your freaking post even less readable.

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” — Brian W. Kernighan (C programming language co-inventor)
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Fruny, you do know this is the "For beginners" forum right? And people come here for help, not redirection or commands.

Before you assign mystring a value, you need to allocate memory:
char* mystring = 0;

Then allocate memory for it
mystring = new char[/*length of string here*/];

Then you need to deallocate the memory before the application ends:
delete [] mystring;

I can''t help you with arrays of pointers, since I haven''t really used them, sorry. I''d recommend using std::string (just recently switched over myself).

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/
Hello v0dKa,

I might be able to help. I've spent the last 3 months experimenting with pointers, characters, integers, and voids.

Firstly, if you have a character that looks like this:

char* mystring;

You can not write data to it without allocating memory. Now I learned a trick that can allocate but then yet de-reference the pointer when I am done with it in case you dont need that allocation more than once. Back to the *mystring, you can set it to a NULL pointer which will stop the string at that exact point. I could go on about NULL terminators, but I think they are very easy to follow.

Secondly, character arrays are different. You don't have to allocate them just write to them. For instance:

char arrayOfStrings[4] = {0};

The {0} just sets a NULL terminator to arrayOfStrings. In some cases you could write to your character like this:

strcpy(arrayOfStrings, "Cool");

Plus, for a handly tip, array's always start at 0, so you could write to your array also in this fashion:

arrayOfStrings[0] = 'C';
arrayOfStrings[1] = 'o';
arrayOfStrings[2] = 'o';
arrayOfStrings[3] = 'l';
arrayOfStrings[4] = '\0'; // null terminator

But thats the hard way, though I just wanted to show you how to do it like strcpy does.

Thirdly, you can not write a whole string to one character array unless you have a pointer array or a 2 by 2 array. For example:

arrayOfStrings[4] = mystring; // will not work

Because arrayOfStrings[4] as shown above can only handle one character like 'A' or 'a'. Now for the character array you can do:

char *myArray[2];

This will allow you to do the following:

char *myArray[2] = {"I am good at characters", "This stuff is awesome"};

Now myArray[0] will look like "I am good at characters". If you want to write over the existing array's you will need to allocate memory for these, for example:

// Writing to myArray[0]char newString[32];strcpy(newString, "This is a new string...");	// set newStringmyArray[0] = (char*) malloc (strlen(newString) + 1);	// + 1 for null terminatorif(myArray[0] != NULL) {	// if myArray is not NULL, then copy data.	strcpy( myArray[0], newString );}

Fourthly, mystring[k] can also only hold one character as in 'A' or 'a' for examples. Since my string is a regular character and not a pointer character array, you can only hold one letter per array number. So if you remembered to allocate *mystring, you could always set mystring[k] to equal 'A' or 'a'.

If you want to make mystring write a whole string per array do as mention above with myArray[2]. Since it has a pointer and an array you can write a string per array. Now for simpler terms you could do a 2 by 2 array looking like:

char myArray2[2][128];

To explain this one would be saying the following.:

myArray[n][sizeof(string)];

Like you could do:

strcpy(myArray[0], "This is awesome!");

and myArray[0] would look like "This is awesome!". No memory allocation is needed for these arrays.

Now for that trick about a temporary address to a pointer using an array would look like this:

char* myTrick() {	int index = 0;	static char myArray[1][1024];	strcpy(myArray[index], "This is a neat trick!");	return myArray[index];}int main() {	char* myString;	myString = myTrick();	printf("myString: %s\n", myString);	return 0;}

This is not to recommended at least not by most people, but for the cases that you want to get a string for that second and never worry about it later, this would help.

I hope all of this has helped, and if you have anymore questions feel free to ask.

- [BDS]StackOverflow

BlueDev Studios

[edited by - BlueDev on February 23, 2004 1:17:51 PM]
[/quote]
quote:Original post by BlueDev
char arrayOfStrings[4] = {0};

The {0} just sets a NULL terminator to arrayOfStrings. In some cases you could write to your character like this:

strcpy(arrayOfStrings, "Cool");

Plus, for a handly tip, array''s always start at 0, so you could write to your array also in this fashion:

arrayOfStrings[0] = ''C'';
arrayOfStrings[1] = ''o'';
arrayOfStrings[2] = ''o'';
arrayOfStrings[3] = ''l'';
arrayOfStrings[4] = ''\0''; // null terminator


Just to avoid some confusion, that won''t work. You haven''t allocated enough space. When you do Array[4] you''re telling the array to have 4 elements, including 0.

So Array[4] has 4 elements: 0, 1, 2, 3

You''d have to declare arrayOfStrings[5] for that example to work.
quote:Original post by BlueDev
Now for that trick about a temporary address to a pointer using an array would look like this:
   char* myTrick() {	int index = 0;	static char myArray[1][1024];	strcpy(myArray[index], "This is a neat trick!");	return myArray[index];}int main() {	char* myString;	myString = myTrick();	printf("myString: %s\n", myString);	return 0;}

This is not to recommended at least not by most people, but for the cases that you want to get a string for that second and never worry about it later, this would help.


OMFG! this is HORRIBLE! Talk about a waste of time and memory!
If you want a string literal then use a string literal, not some hacky function which just wastes time and space.
Sorry, i'm truely shocked that someone would think that this waste is a 'neat trick', it isnt, not by a long shot, for the love of god NEVER recomend this code to anyone EVER again without a damned good reason!

Btw, having read this thread, while the other explinations were probably helpfull i agree with Fruny, the OP needs to learn or re-cover the things he outlined, with a proper understanding of those subjects most of the issues outlined wouldnt be a problem.

@Programmer16
char * mystring = 0;mystring = new char[whatever]  


Is bad code(tm), it should be written
char * mystring = new char[whatever];  

There is very rarely a good reason to seperate declaration from initialization in C++, its even better from a code efficancy point of view.

[edited by - _the_phantom_ on February 23, 2004 1:55:37 PM]
quote:Original post by BlueDev
<snip>char arrayOfStrings[4] = {0};

The {0} just sets a NULL terminator to arrayOfStrings. In some cases you could write to your character like this:

strcpy(arrayOfStrings, "Cool");

Plus, for a handly tip, array's always start at 0, so you could write to your array also in this fashion:

arrayOfStrings[0] = 'C';
arrayOfStrings[1] = 'o';
arrayOfStrings[2] = 'o';
arrayOfStrings[3] = 'l';
arrayOfStrings[4] = '\0'; // null terminator

You're not allocating enough room for the string.
Like you strings are null terminated which means you have a bounds overflow.

quote:
<snip>char *myArray[2];

This will allow you to do the following:

char *myArray[2] = {"I am good at characters", "This stuff is awesome"};

Please use const char's when pointing to constant memory. I know it's not required but it's helpful to know that you cannot change this memory.

quote:
Now myArray[0] will look like "I am good at characters". If you want to write over the existing array's you will need to allocate memory for these, for example:

// Writing to myArray[0]char newString[32];strcpy(newString, "This is a new string...");	// set newStringmyArray[0] = (char*) malloc (strlen(newString) + 1);	// + 1 for null terminatorif(myArray[0] != NULL) {	// if myArray is not NULL, then copy data.	strcpy( myArray[0], newString );}


Again not enough to hold the null char.

quote:
<snip>

- [BDS]StackOverflow

BlueDev Studios


Edit: Removes unmatched /quote in original post
My kingdom for a preview button.

[edited by - Wormy Hellcar on February 23, 2004 5:17:37 PM]
I used to be indecisive, but now I''m not so sure.
quote:Original post by _the_phantom_
@Programmer16
char * mystring = 0;mystring = new char[whatever]  


Is bad code(tm), it should be written

char * mystring = new char[whatever];  

There is very rarely a good reason to seperate declaration from initialization in C++, its even better from a code efficancy point of view.


Well, I guess you can do that in a class?
I thought you had to use this:
class Foo
{
public:
char* m_pString;

Foo(){ m_pString = 0; }
void Set(char* pValue)
{
m_pString = new char[strlen(pValue) + 1];
strcpy(m_pString, pValue);
}
};

And what if you're using an if-else statement? You can't use char* pString = new char[Amount];
This really defeats the purpose because you could just do char String[Amount];

And if that's bad code then how come everybody uses it for DirectX?

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

[edited by - Programmer16 on February 24, 2004 10:11:22 PM]
the rule applies to in function declarations of varibles, in that instance, your code should look like this :

class foo{public:    char * m_string;    foo() : m_string(0)    {    }    void Set(char* pValue)    {         m_string = new char[strlen(pValue) + 1];         strcpy(m_string, pValue);    }}


although, really again you should be using std::string unless you have a good reason not too (target platform or profiled to be too slow), in which case your code becomes the much more simple;

class foo{public:    std::string m_string;    foo()     {    }    void Set(const std::string & value)    {         m_string = value;    }}


how much cleaner is that?
std::string is your friend.
Well, I abandoned this post, and while reasonlessly checking through recent posts, I saw this one.

By now, I already learned std::string, but the trouble doesnt end here. I know most of the functions of it and how to use it and what not, but here''s my problem...

I declared an array of strings in main()...

string array[80];

Then sent it to an experimental function...

changeString(array);

But... here''s my problem. The return type is void, and yet I need to change the array from within the function. Passing a normal string as a reference in an argument is legal, but when I try it with the array of strings, it''s illegal. Pointers -- it''s legal, but from within the function the blasphemy starts. Here''s my code to attempt to change the array of strings (it doesn''t work)...

#include <iostream>using namespace std;// void change(string* array[]);// int main(){string terms[10];change(terms);return 0;}//void change(string* array[]){array[0] = "Bonjour";return;}


This returns two errors:

error C2664: ''change'' : cannot convert parameter 1 from ''class std::basic_string,class std::allocator > [10]'' to ''class std::basic_stringd::char_traits,class std::allocator > *[]''
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

error C2440: ''='' : cannot convert from ''char [8]'' to ''class std::basic_string,class std::allocator > *''
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Suggestions?

------------------------------------------------------------
.:<<-v0d[KA]->>:.
.:<<-v0d[KA]->>:.

This topic is closed to new replies.

Advertisement