simple beginners question for 50 points

Hi, just coming from java and trying to learn c++ now. Now I have a problem, I didn't think it could be a problem, because it looks so simple (and in java, it is simple ;)...

i have:

int n = 5;
char * s = "the value of n is: ";

how can i make one string out of these two values:

"the value of n is: 5"

so:
- how to make a string representation of a number ?
- how to concat two strings ?

thanks a lot!

benutzernameAsked:
Who is Participating?
 
jkrCommented:
The C solution:

#include <stdio.h>
char acString [ 255];

int n = 5;
char * s = "the value of n is: ";

sprintf ( acString, "%s%d", acString, n);

printf ( acString);

The C++ solution:

#include <iostream>
#include <sstream>
using namespace std;

stringstream ss;

int n = 5;
char * s = "the value of n is: ";

ss << s << n;

cout << ss.str();

PS: Interessantes User-Kürzel :o)
0
 
pagladasuCommented:
char *s = new char[256]; //aloocate memory
int n = 5;
sprintf(s,"the value of n is:%d",n);
cout << s;

how to make a string representation of a number :
look at itoa() function

how to concat two strings
look at strcat() function
0
 
PavlikCommented:
#include <string>
#include <sstream>

void f()
{
  int n = 5;
  char * s = "the value of n is: ";

  std::stringstream stream;
  stream << s << n;

  std::string str = stream.str();
}
=====================================

After this code you will have result string in str.

> - how to make a string representation of a number ?
create std::stringstream and serialize this number to it.

> - how to concat two strings ?
If you have 2 objects of std::string (s1 and s2 for example) then concatenation will be s1 + s2


But you definitely should read Stroustrup's 3rd edition.
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
PavlikCommented:
GUYS!!!!!!!


Let's STOP using DANGEROUS function sprintf().

If only you what huge amount of bugs i've seen related to usage of this function.

You can at least use snprintf instead. (_snprintf in windows).

And by the way in c++ you can use streams, that are much more type safe then all the family of printf/scanf.
0
 
benutzernameAuthor Commented:
Thanks for the fast support, guys :))))

Pavlik, you told me, sprintf() is dangerous - what does that mean ? What can happen ? ("unsafe" is a rarely heard word for a Java programmer ;)

If using streams is safer, I still have a problem: I will have to convert the string back into char.

Detail:
I'm using SDL (simple device layer) for graphics programming. SDL has a method called SDL_LoadBMP(const char *filename). If I give it a string instead, it won't work.

So what I have to do is:

char * prefix = "image";
char * suffix = ".bmp";
int n = 5;

now I want to load image number 5:

char * filename = /* working solution */
LoadBitmap(filename);

0
 
jkrCommented:
Well, in this case:

include <iostream>
#include <sstream>
using namespace std;

stringstream ss;


char * prefix = "image";
char * suffix = ".bmp";
int n = 5;

ss << prefix << n << suffix;

char * filename = ss.str().c_str(); // "image5.bmp"
LoadBitmap(filename);
0
 
benutzernameAuthor Commented:
Thanks for the fast support, guys :))))

Pavlik, you told me, sprintf() is dangerous - what does that mean ? What can happen ? ("unsafe" is a rarely heard word for a Java programmer ;)

If using streams is safer, I still have a problem: I will have to convert the string back into char.

Detail:
I'm using SDL (simple device layer) for graphics programming. SDL has a method called SDL_LoadBMP(const char *filename). If I give it a string instead, it won't work.

So what I have to do is:

char * prefix = "image";
char * suffix = ".bmp";
int n = 5;

now I want to load image number 5:

char * filename = /* working solution */
LoadBitmap(filename);

0
 
benutzernameAuthor Commented:
ooops.. it wasn't me, it was the reload button ;)
0
 
AxterCommented:
>>You can at least use snprintf instead. (_snprintf in
>>windows).

_snprintf is not a portable function, and I wouldn't recommend using it.

snprintf is part of the C standards, but it's not part of the C++ standard.

While using sprintf is not type safe, you still should not completely rule it out for code use.
As usual, there isn't a one size fits all with stream methods.
If performance is an issue, you'll usually want to use sprintf VS stringstream or (printf family) VS (std::stream family).
Also many programmers prefer the readability of a printf family functions over the std::streams.

I, myself, prefer to use the sprintf function when posting example code, because I want the questioner to be able to focus on the part of the code that answers the main question, rather then have to look at a bunch of extra code that has nothing to do with the original question.
0
 
benutzernameAuthor Commented:
hmm... doesn't work:

line 17: char * filename = ss.str().c_str();

E:\CPP\test_7_console\Main.cpp(17) : error C2440: 'initializing' : cannot convert from 'const char *' to 'char *'
        Conversion loses qualifiers
0
 
jkrCommented:
>>rather then have to look at a bunch of extra code that
>>has nothing to do with the original question.

Is that the same Axter who once posted "I like to give advanced examples"? :o)
0
 
AxterCommented:
>>line 17: char * filename = ss.str().c_str();

Make it a constant.
Example:

const char * filename = ss.str().c_str(); // "image5.bmp"
0
 
jkrCommented:
Make it either read

const char * filename = ss.str().c_str();

or

char * filename = conat_cast<char*> (ss.str().c_str());

or

char * filename = ( char*) ss.str().c_str();


0
 
AxterCommented:
>>Is that the same Axter who once posted "I like to give
>>advanced examples"? :o)

I do like to give advance examples, but I dont' want to be nagged when I don't.
0
 
AxterCommented:
jkr,
The last two methods you posted could be dangerous.
char * filename = conat_cast<char*> (ss.str().c_str());
char * filename = ( char*) ss.str().c_str();

Because a string object can change it's pointer at any time, and delete it's old pointer.

filename would then be pointed to a deleted string, which would result in undefined behavior.
0
 
benutzernameAuthor Commented:
>>Make it a constant.
Ok, that works. But: I want to load about 10.000 Bitmaps - if I'm using a constant char, than I always have to delete and reconstruct it (because it's constant). Is that right ? Wouldn't be very efficient in that case...(?true?)

sprintf(..) works fine. What is unsafe about it ?


besides:

Where do I find information about the usage of all these methods you are writing about ? Is there a standard-api-documentation like in java ? I have the MSDN documentation, but I still have my problems, finding the way through this huge and hard to read document...

Any tips for good VC++ documentation ? I don't need something like "Learning VC++" but more like an encyclopedia...
0
 
AxterCommented:
Come to think of it, this applies to a const char* too.

Example:
#include <iostream>
#include <string>

using namespace std;


int main(int argc, char* argv[])
{
     std::string foo = "Hello";
     const char* foo_ptr = foo.c_str();
     foo = "Some really big long string *******";
     foo +=foo+foo+foo+foo;

     cout << "foo = " << foo << endl;
     cout << "foo_ptr = " << foo_ptr << endl;

     system("puase");
     return 0;
}
 
0
 
benutzernameAuthor Commented:
I'm using

     char *s = new char[256]; //aloocate memory
     int n = 5;
     sprintf(s,"image%d.bmp",n);

now, for reasons of simplicity. Is that code safe ?
0
 
PavlikCommented:
The reason why i am against sprintf is that it helps hackers a lot.
Consider function:

void f(char* szStr)
{
  char buf[256];
  sprintf(buf, "parameter is %s", szStr);
}

(I know this looks wrong but believe me i've seen such code a lot)

What will happen when i pass 256 bytes long string to szStr?
Right! It will overwrite the stack. And do you know where your new IP value will point to? Good hacker can make it to point to the code he passed in the same string. And can you imagine what this hacker can do having 256 bytes of code executing on your box? For example load another 50Kb of code and run it. After that your box isn't yours anymore.
0
 
AxterCommented:
The point of the above code, is that you should never store a pointer to an std::string or stringstream.
This can cause all kinds of problems.
If the string or stringstream object goes out of scope, you'll again end up with a pointer to a deleted string.

If you need to safe the information in the object, safe it to another std::string instead.
Example:
std::string filename = ss.str().c_str();
LoadBitmap(filename.c_str());

0
 
AxterCommented:
>>now, for reasons of simplicity. Is that code safe ?
Safer would be if you didn't create the string using new.

char s[256]; //Don't use new
int n = 5;
sprintf(s,"image%d.bmp",n);

If you did it this way, you don't have to worry about deleteing the string later.
0
 
benutzernameAuthor Commented:
So pointers to strings only become unsafe, when I exceed the original length of the string ? Otherwise C++ won't have a reason for changing the address of the string - is that true ?

Pavlik: The hackers won't be a problem, as long as I'm not writing network software - true ?
...for network software I could simply close the security hole by checking the length of the parameter.

0
 
PavlikCommented:
About using c_str() member:

(from the C++ standart)
The program shall not treat the returned value as a valid pointer after any subsequent call to a non-const member function of the same object (string).

So you can use pointer returned from c_str() as long as you don't modify this string.
0
 
AxterCommented:
>>So you can use pointer returned from c_str() as long as
>>you don't modify this string.
And as long as the string does not go out of scope.
0
 
PavlikCommented:
> The hackers won't be a problem, as long as I'm not writing network software - true ?
...for network software I could simply close the security hole by checking the length of the parameter

You are wrong. Microsoft event viewer don't have anything to do with network at all. But some hacker hacked network related program runing under user privilegies and made it to write event to event log containing hacker's code. And event was formatted in the way that it caused the problem with stack overwrite in the event viewer. And when admin of this box opened that event this hacker's code was run UNDER ADMINISTRATOR PRIVILEGIES!!!!!

There was interesting problem related to soft links in Linux that allowed to elevate privilegies for almost guest user to admin level.
0
 
AxterCommented:
>>So pointers to strings only become unsafe, when I exceed
>>the original length of the string ? Otherwise
>>C++ won't have a reason for changing the address of the
>>string - is that true ?
This is not entirely true.
The standard allows for implementation to use refferncing.  That means you could have two string objects pointing to the same buffer.
Example:
std::string Str1 = "Foo Foo";
std::string Str2 = Str1;
const char *FooFoo = Str2.c_str();
Str2 = "Not Foo";

With the above code, Str2 can actually be pointing to Str1 data at first.
But when you modify Str2, Str2 will then stop pointing to Str1, and create it's own buffer that will store the new string.

Now your FooFoo pointer is pointing to data in Str1, instead of data in Str2, and if Str1 goes out of focus, you'll be pointing to deleted data.

There are too many things that can go wrong when pointing to an std::string data pointer, so I highly recommend, never to store a pointer to a std::string object.
Use it, but don't store it.
0
 
AxterCommented:
Here's a running example of using a pointer and changing reference.

int main(int argc, char* argv[])
{
     std::string FooFoo = "Foo Foo";
     std::string NotFoo = FooFoo;
     const char *NotFoo_ptr = NotFoo.c_str();
     NotFoo = "Not Foo";
     cout << "FooFoo = " << FooFoo << endl;
     cout << "NotFoo = " << NotFoo << endl;
     cout << "NotFoo_ptr = " << NotFoo_ptr << endl;

     return 0;
}

The above code will have the following output in VC 6.0

FooFoo = Foo Foo
NotFoo = Not Foo
NotFoo_ptr = Foo Foo

As you can see, NotFoo_ptr ends up pointing to FooFoo, instead of pointing to NotFoo.

Not all implementations use referencing, but most do.

This is just one of the many unexpected problems you can come accross when storing a pointer to a std::string object.
So I recommend you don't do it.  Just call on the object's c_str() member function when ever you need to access the data.  It's much safer.
0
 
benutzernameAuthor Commented:
Pavlik: Wow! That says, as long as i run any software on my computer, that was made by someone who didn't know/care about this security hole, someone could hack my computer through this hole ? I have so many programs running, it would be a wonder if i didn't have any holes...

Does a firewall help against this risk ? I'm using a router (1st firewall, ip masking) and ZoneAlarm (2nd firewall, programs need privileges to acces internet)

0
 
benutzernameAuthor Commented:
thanks a lot, guys - who will get the points now ?
0
 
PavlikCommented:
benutzername:
Assume that every softvare has security holes. The more software you have running, the more chances you can be hacked. And there is no unified way to protect from all possible attacks.
So my point is: shut down all the software you don't use. Check for software updates. Don't have resources which would be interesting for hacker.
If you happen to have some important resources (for example information or access to some private network) think about ways how you box can be hacked and protect it.

About points: i don't need it. If i were i would post my message as an answer.
0
 
AxterCommented:
IMHO, pagladasu and jkr answered your original question.

Although pagladasu, answered the question first, jkr gave you two methods with better implementation.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.