Solved

simple beginners question for 50 points

Posted on 2002-04-11
248 Views
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!

0
Question by:benutzername
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• 11
• 9
• 6
• +2

LVL 4

Expert Comment

ID: 6934354
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

LVL 86

Accepted Solution

jkr earned 50 total points
ID: 6934357
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

LVL 1

Expert Comment

ID: 6934377
#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

LVL 1

Expert Comment

ID: 6934394
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

Author Comment

ID: 6934527
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 */

0

LVL 86

Expert Comment

ID: 6934539
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"
0

Author Comment

ID: 6934552
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 */

0

Author Comment

ID: 6934556
ooops.. it wasn't me, it was the reload button ;)
0

LVL 30

Expert Comment

ID: 6934557
>>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

Author Comment

ID: 6934568
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

LVL 86

Expert Comment

ID: 6934573
>>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

LVL 30

Expert Comment

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

Make it a constant.
Example:

const char * filename = ss.str().c_str(); // "image5.bmp"
0

LVL 86

Expert Comment

ID: 6934578

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

LVL 30

Expert Comment

ID: 6934579
>>Is that the same Axter who once posted "I like to give

I do like to give advance examples, but I dont' want to be nagged when I don't.
0

LVL 30

Expert Comment

ID: 6934582
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

Author Comment

ID: 6934587
>>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

LVL 30

Expert Comment

ID: 6934591
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

Author Comment

ID: 6934592
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

LVL 1

Expert Comment

ID: 6934595
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

LVL 30

Expert Comment

ID: 6934603
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();

0

LVL 30

Expert Comment

ID: 6934615
>>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

Author Comment

ID: 6934634
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

LVL 1

Expert Comment

ID: 6934639

(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

LVL 30

Expert Comment

ID: 6934663
>>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

LVL 1

Expert Comment

ID: 6934673
> 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

LVL 30

Expert Comment

ID: 6934692
>>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

LVL 30

Expert Comment

ID: 6934752
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

Author Comment

ID: 6934767
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

Author Comment

ID: 6934779
thanks a lot, guys - who will get the points now ?
0

LVL 1

Expert Comment

ID: 6934804
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

LVL 30

Expert Comment

ID: 6934818

Although pagladasu, answered the question first, jkr gave you two methods with better implementation.
0

Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generatâ€¦
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticallâ€¦
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Botâ€¦
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.