Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1] 2

Author Topic: (Hopefully) Quick and Easy C++ Question  (Read 1658 times)

Ironhand

  • Bay Watcher
  • the llama is laughing
    • View Profile
(Hopefully) Quick and Easy C++ Question
« on: June 14, 2011, 09:11:38 pm »

Hey guys! I'm trying to get into C++, and I have a quick question.

I want to concatenate a string with an integer and another string,
and then I want to pass the whole thing as a parameter to a function.
Both the strings will be hardcoded, and the integer is just a local variable.
In Java, I could just say

"image" + i + ".png"

But I haven't been able to find anything similar in C++.
Am I correct that << only works if you're outputting to cout?

I've tried browsing around and I found people talking about something called Boost,
and then there's something else called a stringstream that I don't quite understand...

Which one's better? Which one's easier? Which one do you use?



Unrelated: If you haven't listened to Baba Yetu today, go do that.
Logged
Ironhand Graphics: Here is the most recent version.
Tile Magic: where a squirrel is never just a squirrel!

Glowcat

  • Bay Watcher
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #1 on: June 14, 2011, 09:31:55 pm »

Boost just refers to expanded libraries.

For stringstream, try something like this:

Code: [Select]
#include <iostream>
#include <sstream>

int main()
{
  int number = 123;

  std::stringstream ss;
  ss << number;

  std::cout << ss.str() << endl;
}

Will store the integer into a string so that it can be concatenated with your literals.
Logged
Totally a weretrain. Very much trains!
I'm going to steamroll this house.

Normandy

  • Bay Watcher
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #2 on: June 14, 2011, 10:48:29 pm »

There's also no function in cstdlib or C++ STL which would return a std::string or const char* from an int (i.e. no Integer.toString()), so you can't do that off the bat. The two ways to do it is to use sprintf() and put it into a char*, which you then concatenate with a std::string, or to use std::stringstream, as Glowcat suggested. Boost is basically the de facto C++ standard library which fills in all the gaps STL left due to design decisions. One of these things is lexical_cast<>, which would allow you to do this: "image" + boost::lexical_cast<std::string>i + ".png", which is what you want.
Logged

olemars

  • Bay Watcher
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #3 on: June 15, 2011, 03:12:16 am »

I've used Qt so long I've forgotten problems like this. Absent Qt I'd probably use a stringstream.
Logged

Rose

  • Bay Watcher
  • Spoopy time!
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #4 on: June 15, 2011, 03:41:40 am »

When all else fails, you can always move backwards, and use sprintf.
Logged

Ironhand

  • Bay Watcher
  • the llama is laughing
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #5 on: June 15, 2011, 07:10:02 pm »

Hey guys! Thanks for all the tips.
One thing, though. I don't want to cout the result.
I want to pass it through a function. Here, look at my code:

Code: [Select]
for(int i=0; i<9; i++){
std::stringstream ss;
ss << "image" << i << ".png";
splat[i]->LoadFromFile(ss.str());
}

I think that middle line there (ss << "image...) is the one that's messing it up.
Is there a way to do that?
Logged
Ironhand Graphics: Here is the most recent version.
Tile Magic: where a squirrel is never just a squirrel!

Ironhand

  • Bay Watcher
  • the llama is laughing
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #6 on: June 15, 2011, 07:46:13 pm »

Err.... apparently it's not actually a problem with that code. That code is fine.

Maybe I'm not initializing my images correctly?

Code: [Select]
sf::Image * images [9];

Now I guess it's a SFML library question rather than just a generic C++ question.
Logged
Ironhand Graphics: Here is the most recent version.
Tile Magic: where a squirrel is never just a squirrel!

olemars

  • Bay Watcher
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #7 on: June 16, 2011, 02:29:58 am »

That's an array of nine pointers to uninitialized images. You want
Code: [Select]
sf::Image *images = new sf::Image[9];and then
Code: [Select]
delete[] images;after you're done.

The first line reserves space in memory for nine images and then initializes them with the default sf::Image constructor. The second frees up the memory after you're done with the images and want to get rid of them again (if that is on program exit then you technically don't have to do this, the program will clean up after itself. It's considered good practice to always delete what you new though).

I recommend reading a little about STL containers, they're the preferred way of dealing with lists of objects in C++, and they're not as complicated as they might seem on first glance. Arrays is something tutorials spend a lot of time on, but in practice they should be used sparingly.

For your example a simple implementation with STL vectors would be:
Code: [Select]
std::vector<sf::Image *> images;

for(int i=0; i<9; i++){
   std::stringstream ss;
   ss << "image" << i << ".png";
   sf::Image *img = new sf::Image();
   img->LoadFromFile(ss.str());
   images->push_back(img);
}

Then you can access the individual images in the vector in any number of ways
Code: [Select]
images.at(3)->whatever();
images[3]->whatever();
for(int i=0; i < images.size(); i++)
{
  images.at(i)->whatever();
}
images->back()->whatever(); //the last image in the vector
There are heaps of functionality to tap in these.

In addition, on the stringstream trick, a common way of doing that is to make some utility functions to deal with the conversion, for example like this:

Code: [Select]
std::string fromInt(int someInt)
{
  std::stringstream ss;
  ss << someInt;
  return ss.str();
}
« Last Edit: June 16, 2011, 07:29:32 am by olemars »
Logged

Virex

  • Bay Watcher
  • Subjects interest attracted. Annalyses pending...
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #8 on: June 16, 2011, 07:56:57 am »

If the string is already hardcoded there is a far more efficient way to do the string conversion you want, especially because each time you do such a concatenation you'll get a fresh string and memory allocation is slow.


Code: [Select]
#define namelength 10; //replace with the actual length of the name of the image. Could use a variable for this, but a #define lets the compiler optimize some things better
#define ascii_offset 48; //character number 48 is the 0 character.


int main()
{
    char[] savename = "imagename00.png"; //use more zeros if you expect to be saving more then 100 images. Note that this variable will be changed each iteration.
    for(int i=0; i<max_image_number; i++)
    {
        savename[namelength] = i/10 + ascii_offset;
        savename[namelength+1] = i%10 + ascii_offset;
        some_function(savename);
    }
}
« Last Edit: June 16, 2011, 07:59:40 am by Virex »
Logged

Ironhand

  • Bay Watcher
  • the llama is laughing
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #9 on: June 16, 2011, 08:13:11 pm »

Awesome. Thanks, guys!
Logged
Ironhand Graphics: Here is the most recent version.
Tile Magic: where a squirrel is never just a squirrel!

SolarShado

  • Bay Watcher
  • Psi-Blade => Your Back
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #10 on: June 21, 2011, 09:24:23 am »

When all else fails, you can always move backwards, and use sprintf.

I'm confused, why isn't this the best way to do it?
Code: [Select]
sprintf(filename, "myIMG%02d.png", i);The syntax may be slightly less nice, but you don't have to create a new object.
I've tinkered with C a bit, but no C++ beyond 'hello world'.

(Virex's code definitely looks like the most efficient, but obviously doesn't work for general concatenation.)
Logged
Avid (rabid?) Linux user. Preferred flavor: Arch

Siquo

  • Bay Watcher
  • Procedurally generated
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #11 on: June 21, 2011, 09:47:48 am »

I'm confused, why isn't this the best way to do it?
Probably because C++ users feel superior to C?
Logged

This one thread is mine. MIIIIINE!!! And it will remain a happy, friendly, encouraging place, whether you lot like it or not. 
will rena,eme sique to sique sxds-- siquo if sucessufil
(cant spel siqou a. every speling looks wroing (hate this))

olemars

  • Bay Watcher
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #12 on: June 21, 2011, 02:36:32 pm »

Because sprintf is very vulnerable to buffer overruns.
Logged

qwertyuiopas

  • Bay Watcher
  • Photoshop is for elves who cannot use MSPaint.
    • View Profile
    • uristqwerty.ca, my current (barren) site.
Re: (Hopefully) Quick and Easy C++ Question
« Reply #13 on: June 21, 2011, 03:12:14 pm »

If you know it is just an integer, you can simply allocate enough extra space to hold the maximum number of characters an integer may print.

It would be nice if there was a version of sprintf that would allocate it's own output buffer, though. Could easily build the string on the stack, then allocate a buffer large enough for it, then copy it into the buffer, or something like that.
Logged
Eh?
Eh!

SolarShado

  • Bay Watcher
  • Psi-Blade => Your Back
    • View Profile
Re: (Hopefully) Quick and Easy C++ Question
« Reply #14 on: June 21, 2011, 09:13:18 pm »

Because sprintf is very vulnerable to buffer overruns.

Ah, I see. Thanks :)
Logged
Avid (rabid?) Linux user. Preferred flavor: Arch
Pages: [1] 2