C++ Strings Question - Adding int variable to a string literal

{NcsO}ReichstaG

[H]ard|Gawd
Joined
Aug 13, 2004
Messages
1,768
:eek:
I totally forgot my C++. Anyway, let's say I want to create 5 ".txt files" named 1.txt to 5.txt.
1.txt
2.txt
3.txt
4.txt
5.txt
How do I add ints to a string in C++ again? I want to do something like this:
Code:
int go = 1;
while(go <=5)
{
 ofstream a_file (go + ".txt");
}
-ThaNkS
 
Code:
#include <fstream>
#include <iostream>
#include <stdio.h>

void main()
{
	for (int n = 1; n <= 5; n ++)
	{
		char sz[10];
		sprintf(sz, "%d.txt", n);
		std::ofstream a_file(sz);
	}
}
 
Not that it particularly matters, but wouldn't using ostringstream meet the standard better?
 
Feel free to post a code fragment that uses ostrstream, if you'd like.

Meanwhile: what standard?
 
I thought it was in the latest ANSI standard for converting between integers and strings.

I believe you could do something like this, I have no compiler with me right now however,

Code:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
      for(int i = 1; i <= 5 i++)
      {
          ofstream a_file((ostringstream << i << ".txt").c_str());
      }
}

I have no idea if that'll work written like that, this would prolly be better,

Code:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;

int main()
{
      ostringstream sout;
      for(int i = 1; i <= 5 i++)
      {
           sout << i << ".txt";
           ostream a_file(sout.c_str());
           sout.flush();    //  or clear()??  I can't remember
      }
}

I have no compiler to test with right now, but I think one of those should work. I have no idea why one would be better then the other or why either would be better then mike's, but I was under the impression it was the ANSI standard.
 
Wingy said:
I thought it was in the latest ANSI standard for converting between integers and strings.

Not really. It's a recent idea for serializing various data types into a string-backed stream. The differenece is that the conversion does just the conversion from one type to another; serializing does a bunch of other stuff -- memory management, allcoation, handling different data types, providing a mechanism for extensibility, an so on.

The idea behind the ANSI standard is defining how things should behave; what should work and what shouldn't, and what they do when they do work. (And, sometimes, what they might do when they don't work.) it doesn't prescribe a particular solution for a particular problem, though. It doesn't make much sense, then, to say that one program "meets the standard better" because it uses correct syntax and constructs to solve the same problem in a different way.

The solution I provided uses a routine normally associated with the C standard. Some consider it "old", or out dated, but it is no less C++ than the ostringstream-based solution.

To know which one is better, we'd have to know lots more about the specific problem that {NcsO}ReichstaG is trying to solve, and learn which tradeoffs he'd like to make in reaching that solution.

The code I've provided is substantially smaller. And I mean at runtime: when I build it with the current version of VC++ for release, I get an executable that's about 122000 bytes in length. The fixed version of your code (below) is 151000 bytes in length. Does that 29,000 matter? To me it does -- I'm a minimalist. NcsO might not care.

You might make an argument for my code being insecure -- you have to choose the size of sz so that it fits whatever strings you throw at it. If someone changes the loop to create files numbered 2000000000 through 2000000005, then my program will crash because sz[] is too narrow, for example. It's a simple fix, of course. Maybe that aspect of it makes someone like your program better.

The conversion in my program can't fail at runtime -- it has preallocated memory. Your conversion needs memory from the heap, so it might throw an exception. Adding in code to correctly react to that exception would mean more work and time.

Wingy said:
I have no compiler to test with right now, but I think one of those should work.

Not quite. Here's your first program fixed up so that it builds and works:

Code:
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main()
{
	for(int i = 1; i <= 5; i++)
	{
		ostringstream foo;
		foo << i << ".txt";
		ofstream a_file(foo.str().c_str());
	}
}
 
Thanks mike, you always teach me something :)

For some reason I though there was one line way to do that, even though it's not a good idea, in my styling opinion.

Two more questions, that I should prolly know the answer to already,

what is the performance hit on destroying and recontructing the ostringstream?

Also, I thought that you could have a runtime error also if the 10 bytes weren't available, since you keep redeclaring the char[10]?

These are things I should really know by now I think.

Edit: or were you talking specifically about your call to sprintf... sprintf won't fail at runtime, because of your buffer that was allocated before the call. Which makes sense.
 
Wingy said:
Thanks mike, you always teach me something :)
Thank you for your kind words.

Wingy said:
For some reason I though there was one line way to do that, even though it's not a good idea, in my styling opinion.
You can probably get it down to two lines. You need a ostringstream object, which you didn't have -- you named the class. So that's one line.

"foo << i << ".txt"" evaluates to a reference to an object of type ostream, so you can't call str() directly on it. Maybe you can create some wrapper class that helps you with these things, but then you have a lot more code elsewhere. (Which is good, if it makes something you frequently do a one-line solution. That's reuse!)

Wingy said:
what is the performance hit on destroying and recontructing the ostringstream?
Depends on the implementaiton you're using. You'll want to step through the implementation (use the "step into" command in your debugger) and watch it go. You can also measure it with a profiler. I'm sure that it's allocating a string-like structure, so you have to figure it's calling the memory manager. And then it'll free the memory, and so on.

Wingy said:
Also, I thought that you could have a runtime error also if the 10 bytes weren't available, since you keep redeclaring the char[10]?
No. The memory goes in and out of scope; it doesn't accumulate. (You might be thinking of _alloca(), which really is evil unless carefully used -- and it could accumulate if you dont' use it right.) The allocation here is implemneted by most compilers as: get the stack pointer, subtract ten from it, use that resulting pointer.

Wingy said:
Edit: or were you talking specifically about your call to sprintf... sprintf won't fail at runtime, because of your buffer that was allocated before the call. Which makes sense.
Well, both together, really. I'm comparing allocating on the stack a fixed size to allocating something on the stack which has a contructor that touches the heap; then invoking other methods which (could) touch the heap, too.
 
Back
Top