Valhalla Legends Forums Archive | C/C++ Programming | Declaring Variables

AuthorMessageTime
Crypticflare
I've been reading in my book and I got up to the declaring variables and naming them, and I'm a bit sketchy yet on how to declare say a string of text. I was wondering if someone could be kind enough to show me an example of the correct format.

I'm using Microsoft Visual C++ compiler if that makes a difference (not sure)

Thanks!
November 6, 2003, 3:44 AM
CupHead
[code]
char MyString[] = "Blah blah blah";

char MyString[256];

char *MyString;
MyString = new char[256];

[/code]

No guarantees that those are all right, just going off of memory.

Edit:
Oh, easiest way is probably this:
[code]
#include <string>
using std::string;

string MyString;
[/code]

Edit2: Fixed code.
November 6, 2003, 3:59 AM
Eibro
[quote author=CupHead link=board=30;threadid=3446;start=0#msg27665 date=1068091140]
[code]
char [] MyString = "Blah blah blah";

char MyString[256];

char *MyString;
MyString = new char[256];

[/code]

No guarantees that those are all right, just going off of memory.

Edit:
Oh, easiest way is probably this:
[code]
#include <string.h>

string MyString;
[/code]
[/quote]Pretty close:
Should be: char MyString[] = "Blah blah blah"; or char* MyString = "Blah blah blah";
Also, you need to #include <string> for std::string, not string.h:
[code]#include <string>

std::string myString;[/code]
November 6, 2003, 5:05 AM
iago
Easier would be to declare namespace:

[code]#include <iostream>
#include <string>
using namespace std;

void main()
{
string TestString = "Moo";
cout << TestString << endl;
TestString = TestString + "Wee!";
cout << TestString << endl;
cout << "Enter your string:" << endl;
cin >> TestString;
cout << "You entered: " << TestString << "!!" << endl;
}[/code]

hopefully that works, but it should be a simple enough program to play with/learn from :)
November 6, 2003, 8:33 AM
Kp
Unfortunately, someone associated with C++/STL decided to create a C++ class named [u]string[/u] which handles a great deal of string related functionality. It should be noted that this is not a built-in type and as such cannot be directly used with system functions (e.g. send, recv, CreateFile). You can use the c_str() method of the string class to get at its enclosed data for sending, but you'll have to do some extra work if you want to read a string from the system and then put it in the [u]string[/u] class.

Prior to the C++ string class, string typically referred to an array of characters, and CupHead/iago already covered how to do that. Beware that when using a character array, it is your problem to ensure sufficient space is available. The following will work, but produce bad results.
[code]char x[4]; strcpy (x, "a very long string that doesn't fit");[/code]The compiler will (probably) let you compile this, but running it will result in a [u]buffer overrun[/u] of x, which will likely cause your program to crash. Careless string copying is the source of most buffer overflow exploits in programs; afaik, it's difficult/impossible to do this in "managed" languages like Java and C# because the compiler does lots of extra checking on array use. In C and normal C++, you're responsible for checking that condition manually.
November 6, 2003, 3:42 PM
Skywing
Note that void main() is illegal, iago.
November 6, 2003, 4:48 PM
iago
[quote author=Skywing link=board=30;threadid=3446;start=0#msg27730 date=1068137327]
Note that void main() is illegal, iago.
[/quote]

It'll compile in his compiler! I wanted to give him something easy.

Kp - it was Eibro that posted about char* I think, I didn't.

And note that he hasn't gotten past variable declarations. Introducing him to string is the easiest way of doing it, he can worry about how it's implemented later.
November 6, 2003, 5:53 PM
Skywing
[quote author=iago link=board=30;threadid=3446;start=0#msg27749 date=1068141238]
[quote author=Skywing link=board=30;threadid=3446;start=0#msg27730 date=1068137327]
Note that void main() is illegal, iago.
[/quote]

It'll compile in his compiler! I wanted to give him something easy.

Kp - it was Eibro that posted about char* I think, I didn't.

And note that he hasn't gotten past variable declarations. Introducing him to string is the easiest way of doing it, he can worry about how it's implemented later.
[/quote]
So you think it's a good idea to teach people to do stuff the wrong way, just because a particular compiler supports it...?
November 6, 2003, 6:14 PM
iago
okokok, I recant. I edited my post and promise to never EVER for ANY REASON use or teach void main() to anybody ever again. Happy? :P


lol, can't modify after 10 minutes. So, here's fix:
[quote author=iago link=board=30;threadid=3446;start=0#msg27688 date=1068107619]
Easier would be to declare namespace:

[code]#include <iostream>
#include <string>
using namespace std;

int main(int argc, char *argv[])
{
string TestString = "Moo";
cout << TestString << endl;
TestString = TestString + "Wee!";
cout << TestString << endl;
cout << "Enter your string:" << endl;
cin >> TestString;
cout << "You entered: " << TestString << "!!" << endl;
}[/code]

hopefully that works, but it should be a simple enough program to play with/learn from :)
[/quote]
November 6, 2003, 6:21 PM
Eibro
[quote author=Kp link=board=30;threadid=3446;start=0#msg27718 date=1068133357]
Unfortunately, someone associated with C++/STL decided to create a C++ class named [u]string[/u] which handles a great deal of string related functionality. It should be noted that this is not a built-in type and as such cannot be directly used with system functions (e.g. send, recv, CreateFile). You can use the c_str() method of the string class to get at its enclosed data for sending, but you'll have to do some extra work if you want to read a string from the system and then put it in the [u]string[/u] class.

Prior to the C++ string class, string typically referred to an array of characters, and CupHead/iago already covered how to do that. Beware that when using a character array, it is your problem to ensure sufficient space is available. The following will work, but produce bad results.
[code]char x[4]; strcpy (x, "a very long string that doesn't fit");[/code]The compiler will (probably) let you compile this, but running it will result in a [u]buffer overrun[/u] of x, which will likely cause your program to crash. Careless string copying is the source of most buffer overflow exploits in programs; afaik, it's difficult/impossible to do this in "managed" languages like Java and C# because the compiler does lots of extra checking on array use. In C and normal C++, you're responsible for checking that condition manually.
[/quote]With a little thrusting here and there, you can use std::string just as you would a char* :)
Example of retrieving window text (GetWindowText) straight into an std::string buffer:

[code]
// tstring is: typedef std::basic_string<TCHAR> tstring;

tstring IWindow::Text() const
{
int textLength = GetWindowTextLength( m_hWnd );

// Neat (icky) trick. Use std::string internal buffer as buffer
// by reserving specified amount of space and casting const-ness away
tstring stringBuf( textLength, TCHAR( '\0' ) );

TCHAR* bufHandle = const_cast<TCHAR*>( stringBuf.c_str() );

int charsCopied = GetWindowText( m_hWnd, bufHandle, textLength );

// must resize to actual length, or std::string will flip out
// when it goes to deallocate
stringBuf.resize( charsCopied );

return stringBuf;
}[/code]

Then to pass an std::string to functions that want a const char*, do something like:[code]
template <typename T>
class stringEx : public std::basic_string<T>
{
public:
operator const char*() const { return this->c_str(); }
};[/code]It's flawless!
November 6, 2003, 8:49 PM
iago
What if the functions need a non-constant string? A couple time I've done, "send((char*)myString.c_str(), ..);", but I know that's a bad idea.
November 6, 2003, 10:01 PM
Skywing
[quote author=Eibro link=board=30;threadid=3446;start=0#msg27777 date=1068151763]
[quote author=Kp link=board=30;threadid=3446;start=0#msg27718 date=1068133357]
Unfortunately, someone associated with C++/STL decided to create a C++ class named [u]string[/u] which handles a great deal of string related functionality. It should be noted that this is not a built-in type and as such cannot be directly used with system functions (e.g. send, recv, CreateFile). You can use the c_str() method of the string class to get at its enclosed data for sending, but you'll have to do some extra work if you want to read a string from the system and then put it in the [u]string[/u] class.

Prior to the C++ string class, string typically referred to an array of characters, and CupHead/iago already covered how to do that. Beware that when using a character array, it is your problem to ensure sufficient space is available. The following will work, but produce bad results.
[code]char x[4]; strcpy (x, "a very long string that doesn't fit");[/code]The compiler will (probably) let you compile this, but running it will result in a [u]buffer overrun[/u] of x, which will likely cause your program to crash. Careless string copying is the source of most buffer overflow exploits in programs; afaik, it's difficult/impossible to do this in "managed" languages like Java and C# because the compiler does lots of extra checking on array use. In C and normal C++, you're responsible for checking that condition manually.
[/quote]With a little thrusting here and there, you can use std::string just as you would a char* :)
Example of retrieving window text (GetWindowText) straight into an std::string buffer:

[code]
// tstring is: typedef std::basic_string<TCHAR> tstring;

tstring IWindow::Text() const
{
int textLength = GetWindowTextLength( m_hWnd );

// Neat (icky) trick. Use std::string internal buffer as buffer
// by reserving specified amount of space and casting const-ness away
tstring stringBuf( textLength, TCHAR( '\0' ) );

TCHAR* bufHandle = const_cast<TCHAR*>( stringBuf.c_str() );

int charsCopied = GetWindowText( m_hWnd, bufHandle, textLength );

// must resize to actual length, or std::string will flip out
// when it goes to deallocate
stringBuf.resize( charsCopied );

return stringBuf;
}[/code]

Then to pass an std::string to functions that want a const char*, do something like:[code]
template <typename T>
class stringEx : public std::basic_string<T>
{
public:
operator const char*() const { return this->c_str(); }
};[/code]It's flawless!

[/quote]
That's 'const' for a reason. You're violating the C++ standard.
November 7, 2003, 2:46 AM
iago
I was saying, "what if" he needed a non-const char* for an api call?
November 7, 2003, 3:18 AM
Etheran
Object-Oriented Programming Using C++ Second Edition -- Joyce Farrell
*ALL* of her examples are void main().. I think we need to denounce this book!!
November 7, 2003, 4:00 AM
MrRaza
I believe either way works fine, but skywing is correct. By the way, I think most people are getting ahead of themselves, remember, he's just learning to declare variables....
November 7, 2003, 4:54 AM
Zakath
[quote author=MrRaza link=board=30;threadid=3446;start=0#msg27866 date=1068180840]
I believe either way works fine, but skywing is correct. By the way, I think most people are getting ahead of themselves, remember, he's just learning to declare variables....
[/quote]

No, either way does not work fine. As has been stated multiple times already, declaring main as returning void is an incorrect, non-standard method that has, unfortunately, been perpetuated by most modern compilers. Also, declaring a main function is the very first thing you learn in C or C++ (at least in all cases I'm aware of). It is not a good idea to allow someone to get used to doing something wrong, then come back later and try to get them to change their habits. In short, always have main return an int.
November 7, 2003, 4:54 PM
Crypticflare
Thanks a lot everyone, The book can be a bit sketchy at parts its always good to know the local vL forums are always available for help.

Unless your banned =p
November 7, 2003, 7:55 PM
Eibro
[quote author=Skywing link=board=30;threadid=3446;start=0#msg27833 date=1068173213]
[quote author=Eibro link=board=30;threadid=3446;start=0#msg27777 date=1068151763]
[quote author=Kp link=board=30;threadid=3446;start=0#msg27718 date=1068133357]
Unfortunately, someone associated with C++/STL decided to create a C++ class named [u]string[/u] which handles a great deal of string related functionality. It should be noted that this is not a built-in type and as such cannot be directly used with system functions (e.g. send, recv, CreateFile). You can use the c_str() method of the string class to get at its enclosed data for sending, but you'll have to do some extra work if you want to read a string from the system and then put it in the [u]string[/u] class.

Prior to the C++ string class, string typically referred to an array of characters, and CupHead/iago already covered how to do that. Beware that when using a character array, it is your problem to ensure sufficient space is available. The following will work, but produce bad results.
[code]char x[4]; strcpy (x, "a very long string that doesn't fit");[/code]The compiler will (probably) let you compile this, but running it will result in a [u]buffer overrun[/u] of x, which will likely cause your program to crash. Careless string copying is the source of most buffer overflow exploits in programs; afaik, it's difficult/impossible to do this in "managed" languages like Java and C# because the compiler does lots of extra checking on array use. In C and normal C++, you're responsible for checking that condition manually.
[/quote]With a little thrusting here and there, you can use std::string just as you would a char* :)
Example of retrieving window text (GetWindowText) straight into an std::string buffer:

[code]
// tstring is: typedef std::basic_string<TCHAR> tstring;

tstring IWindow::Text() const
{
int textLength = GetWindowTextLength( m_hWnd );

// Neat (icky) trick. Use std::string internal buffer as buffer
// by reserving specified amount of space and casting const-ness away
tstring stringBuf( textLength, TCHAR( '\0' ) );

TCHAR* bufHandle = const_cast<TCHAR*>( stringBuf.c_str() );

int charsCopied = GetWindowText( m_hWnd, bufHandle, textLength );

// must resize to actual length, or std::string will flip out
// when it goes to deallocate
stringBuf.resize( charsCopied );

return stringBuf;
}[/code]

Then to pass an std::string to functions that want a const char*, do something like:[code]
template <typename T>
class stringEx : public std::basic_string<T>
{
public:
operator const char*() const { return this->c_str(); }
};[/code]It's flawless!

[/quote]
That's 'const' for a reason. You're violating the C++ standard.
[/quote]const_cast is part of the language for a reason. With some extra care, casting away the const-ness has no side effects. Sure beats allocating a temporary buffer, copying it to a tstring and deleting the buffer.
November 9, 2003, 12:00 AM
Adron
Isn't there a possible problem with a smart string using the same buffer for two different strings and only allocating a new buffer when you're assigning a new value to one of the strings using one of the string member functions?
November 9, 2003, 1:24 AM
Skywing
[quote author=Eibro link=board=30;threadid=3446;start=15#msg28198 date=1068336000]
[quote author=Skywing link=board=30;threadid=3446;start=0#msg27833 date=1068173213]
[quote author=Eibro link=board=30;threadid=3446;start=0#msg27777 date=1068151763]
[quote author=Kp link=board=30;threadid=3446;start=0#msg27718 date=1068133357]
Unfortunately, someone associated with C++/STL decided to create a C++ class named [u]string[/u] which handles a great deal of string related functionality. It should be noted that this is not a built-in type and as such cannot be directly used with system functions (e.g. send, recv, CreateFile). You can use the c_str() method of the string class to get at its enclosed data for sending, but you'll have to do some extra work if you want to read a string from the system and then put it in the [u]string[/u] class.

Prior to the C++ string class, string typically referred to an array of characters, and CupHead/iago already covered how to do that. Beware that when using a character array, it is your problem to ensure sufficient space is available. The following will work, but produce bad results.
[code]char x[4]; strcpy (x, "a very long string that doesn't fit");[/code]The compiler will (probably) let you compile this, but running it will result in a [u]buffer overrun[/u] of x, which will likely cause your program to crash. Careless string copying is the source of most buffer overflow exploits in programs; afaik, it's difficult/impossible to do this in "managed" languages like Java and C# because the compiler does lots of extra checking on array use. In C and normal C++, you're responsible for checking that condition manually.
[/quote]With a little thrusting here and there, you can use std::string just as you would a char* :)
Example of retrieving window text (GetWindowText) straight into an std::string buffer:

[code]
// tstring is: typedef std::basic_string<TCHAR> tstring;

tstring IWindow::Text() const
{
int textLength = GetWindowTextLength( m_hWnd );

// Neat (icky) trick. Use std::string internal buffer as buffer
// by reserving specified amount of space and casting const-ness away
tstring stringBuf( textLength, TCHAR( '\0' ) );

TCHAR* bufHandle = const_cast<TCHAR*>( stringBuf.c_str() );

int charsCopied = GetWindowText( m_hWnd, bufHandle, textLength );

// must resize to actual length, or std::string will flip out
// when it goes to deallocate
stringBuf.resize( charsCopied );

return stringBuf;
}[/code]

Then to pass an std::string to functions that want a const char*, do something like:[code]
template <typename T>
class stringEx : public std::basic_string<T>
{
public:
operator const char*() const { return this->c_str(); }
};[/code]It's flawless!

[/quote]
That's 'const' for a reason. You're violating the C++ standard.
[/quote]const_cast is part of the language for a reason. With some extra care, casting away the const-ness has no side effects. Sure beats allocating a temporary buffer, copying it to a tstring and deleting the buffer.
[/quote]
Given that the language explicitly says that the buffer returned by c_str is not to ever be modified, I think that your code is a fairly bad idea.
November 9, 2003, 1:46 AM
Eibro
[quote author=Adron link=board=30;threadid=3446;start=15#msg28206 date=1068341079]
Isn't there a possible problem with a smart string using the same buffer for two different strings and only allocating a new buffer when you're assigning a new value to one of the strings using one of the string member functions?
[/quote]No doubt, but I don't think this applies to what we're discussing.

[quote]Given that the language explicitly says that the buffer returned by c_str is not to ever be modified, I think that your code is a fairly bad idea.[/quote]I disagree. When the buffer returned by c_str() is of known length, you can safely modify the buffer while taking care not to go out of bounds. Unless there is some situation I have overlooked, this is one instance where i'll not blindly follow the standard.
November 9, 2003, 9:09 PM
Skywing
[quote author=Eibro link=board=30;threadid=3446;start=15#msg28331 date=1068412143]
[quote author=Adron link=board=30;threadid=3446;start=15#msg28206 date=1068341079]
Isn't there a possible problem with a smart string using the same buffer for two different strings and only allocating a new buffer when you're assigning a new value to one of the strings using one of the string member functions?
[/quote]No doubt, but I don't think this applies to what we're discussing.

[quote]Given that the language explicitly says that the buffer returned by c_str is not to ever be modified, I think that your code is a fairly bad idea.[/quote]I disagree. When the buffer returned by c_str() is of known length, you can safely modify the buffer while taking care not to go out of bounds. Unless there is some situation I have overlooked, this is one instance where i'll not blindly follow the standard.
[/quote]
Yes, there are a number of situations which you have blindly overlooked. Most blatantly obvious is Adron's point about implementing copy-on-write for std::basic_string. Bjarne Stroustrup (the creator of C++)'s book, [u]The C++ Programming Language[/u] even explictly says something about this:
[quote]
As mentioned in §11.12, it is possible to optimize a string so that copying doesn't actually take place until two copies of a string are needed. The design of the standard string encourages implementations that minimize actual copying. This makes read-only uses of strings and passing of strings as function arguments much cheaper than one could have naively assumed.[/quote]
Standards are there for a reason. Perhaps in the future you'll actually do some research instead of blindly following a completely horrible idea like that, or even worse, teaching it to people.
November 9, 2003, 9:28 PM
Eibro
[quote author=Skywing link=board=30;threadid=3446;start=15#msg28336 date=1068413291]
[quote author=Eibro link=board=30;threadid=3446;start=15#msg28331 date=1068412143]
[quote author=Adron link=board=30;threadid=3446;start=15#msg28206 date=1068341079]
Isn't there a possible problem with a smart string using the same buffer for two different strings and only allocating a new buffer when you're assigning a new value to one of the strings using one of the string member functions?
[/quote]No doubt, but I don't think this applies to what we're discussing.

[quote]Given that the language explicitly says that the buffer returned by c_str is not to ever be modified, I think that your code is a fairly bad idea.[/quote]I disagree. When the buffer returned by c_str() is of known length, you can safely modify the buffer while taking care not to go out of bounds. Unless there is some situation I have overlooked, this is one instance where i'll not blindly follow the standard.
[/quote]
Yes, there are a number of situations which you have blindly overlooked. Most blatantly obvious is Adron's point about implementing copy-on-write for std::basic_string. Bjarne Stroustrup (the creator of C++)'s book, [u]The C++ Programming Language[/u] even explictly says something about this:
[quote]
As mentioned in §11.12, it is possible to optimize a string so that copying doesn't actually take place until two copies of a string are needed. The design of the standard string encourages implementations that minimize actual copying. This makes read-only uses of strings and passing of strings as function arguments much cheaper than one could have naively assumed.[/quote]
Standards are there for a reason. Perhaps in the future you'll actually do some research instead of blindly following a completely horrible idea like that, or even worse, teaching it to people.
[/quote]Firstly, where did I try to teach this to anyone? My original post was a lighthearted reply to Kp. I'm not speaking generally when I talk about modifying the buffer returned by c_str(), i'm talking about my code. I don't need to worry about copy-on-write semantics for the above code. It's obviously const for a reason, but sometimes it's okay to bend the rules.

Why did I choose to do it this way? Consider the other options:
1) Have the user pass their own buffer, which may or not be long enough to hold the entire string.
2) Have a static buffer within the function that recieves the data, and return that. This is a problem because repeated calls to the function will modify data returned in previous calls.
3) Allocate a buffer of required length and return it. This is a memory leak waiting to happen.
4) Allocate a buffer, copy it to a tstring, delete the buffer and return the tstring. This is way to inefficient.
November 10, 2003, 1:11 AM
Moonshine
I'm going to have to agree with Skywing here; MSDN explicitly says:

[quote]
Converts the contents of a string as a C-style, null-terminated string.

const value_type *c_str( ) const;
Return Value
A pointer to the C-style version of the invoking string.

Remarks
... (previous remarks removed here for brevity) ...

The returned C-style string should not be modified, as this could invalidate the pointer to the string, or deleted, as the string has a limited lifetime and is owned by the class string.
[/quote]

(Note the last sentence in that pasting)

[quote]1) Have the user pass their own buffer, which may or not be long enough to hold the entire string.[/quote]

In addition to the documentation, it's not as big of a deal as you say when the user passes their own buffer in the function parameters; for one can always do something along the lines of:

[code]void IWindow::Text(char *pszBuffer, const int iMaxSize) {
// ...
}[/code]

Then just check iMaxSize vs. GetWindowTextLength(). Anyways, that's my take on it, I believe using that method is a much safer bet (even though it might be a little more work, but so is the case with void main()) than violating the standards and having possible unwanted side effects.
November 10, 2003, 2:09 AM
Skywing
Note that the buffer returned by c_str() is also only guaranteed to be valid and untouched until the next non-const call to the std::string. On the next such function call, it's entirely acceptable for the implementation to completely overwrite any changes that you made (improperly, potentially to the wrong buffer).

Just because something "works" on your compiler implementation does not make it a good idea to use it. Besides simply violating const, you're also making asumptions about how memory for the std::string buffer is allocated that are quite probably not going to hold for a large number of compilers.

Also, note that the purpose of this entire thread was to answer a user's request for information on the C++ language. Given this, it's fair to assume that somebody might read it to learn something about C++, and possibly pick up the wrong way of doing things from your post. Inaccuracy is a bad thing to bring into these kinds of situations.
November 10, 2003, 5:23 AM
Kp
[quote author=Eibro link=board=30;threadid=3446;start=15#msg28384 date=1068426706]1) Have the user pass their own buffer, which may or not be long enough to hold the entire string.[/quote]They pass the buffer's length, you check it with GetWindowTextLength, and bail if it isn't big enough. Then it's their problem to handle the error.

[quote author=Eibro link=board=30;threadid=3446;start=15#msg28384 date=1068426706]2) Have a static buffer within the function that recieves the data, and return that. This is a problem because repeated calls to the function will modify data returned in previous calls.[/quote]Static data is usually a bad idea (among other problems, it's usually not threadsafe unless you take extra steps). Never use this option.

[quote author=Eibro link=board=30;threadid=3446;start=15#msg28384 date=1068426706]3) Allocate a buffer of required length and return it. This is a memory leak waiting to happen.[/quote]That would seem to imply a lack of trust in the user's competency about memory management. If the user can't be trusted to write good code, why are we trusting them to write code at all?

[quote author=Eibro link=board=30;threadid=3446;start=15#msg28384 date=1068426706]4) Allocate a buffer, copy it to a tstring, delete the buffer and return the tstring. This is way to inefficient.[/quote]This is why I always tell people not to use std::string if you're going to be passing the data into/out of the OS.
November 10, 2003, 10:58 PM
CupHead
Eibro: I think it's time to cut your losses. Arguing to the bitter end is only ok when you're right or there isn't some glaring standard to say you're wrong.
November 10, 2003, 11:43 PM
iago
[quote author=CupHead link=board=30;threadid=3446;start=15#msg28590 date=1068507821]
Eibro: I think it's time to cut your losses. Arguing to the bitter end is only ok when you're right or there isn't some glaring standard to say you're wrong.
[/quote]

And this is coming from Cuphead!
November 11, 2003, 12:58 AM
Eibro
[quote author=CupHead link=board=30;threadid=3446;start=15#msg28590 date=1068507821]
Eibro: I think it's time to cut your losses. Arguing to the bitter end is only ok when you're right or there isn't some glaring standard to say you're wrong.
[/quote]The "argument" got pretty trivial a few posts ago. I've already said what I needed to say, I don't understand where you're seeing a bitter end.
November 11, 2003, 2:51 AM

Search