C++ remap

Aw great, here we go again!

I’m just starting out in C[sup]++[/sup]. One of my assignments needs a final output made up of asterisks (yep, the old two counter countdown program.) I’ll do the long version for the grade, but the code could really be simplified if I could just print out the output of an integer counter but replace all the ones in it with asterisks. So, is there an easy way (in other words, something even I could understand) to either substitute asterisks inside an integer variable and swap back after printing, or to remap the character set so that one character prints as another and undo the mapping at the end?

Wow, the OP posted on this one!

I’m not sure I entirely understand what you’re trying to do… as far as I can gather you want the integer: 12134 to appear as 234 ? Is that right?

If so, you’ll have to convert to a string(*, for obvious reasons, cannot be part of an int), then use the replace function…

hmm, I may have slipped into VB there - I can’t remember if there is a standard replace function in C++… if not, then write a function that steps through the string, replacing all of char x with char y

hmm it’s years since I did C-programming, but here you go:
this uses a global variable for the original string, becasue I can’t remember how to pass strings

void Replace(char orig, char repl)
for(i=0;i<strlen(OriginalString);1++)
{

hmmm… well, that was weird - hamsters managed to prematurely post - trying to make up for the repeated eating of the OP, I guess… anyway, to continue…

{
if originalstring* = orig
replacestring* = repl
else
replacestring* = originalstring*
}

or something like that - as I say, it’s been a while since I did C, so syntax might need to be cleared up… also ,I’ve just spotted that I wrote 1++ in my first post, which should of course be i++

hope that helps

oh and to call the function:

char originalstring

void main()
{
int count
count = <whatever your counting algorithm is here>
originalstring = cstr(count)
replace(“1”,"*")
cout << replacestring
}

this could easily be condensed into a single line by making replace a function instead of a proc, and passing it the Cstr(count) as a parameter, instead of using globals - but I’ll leave that as an exercise for the OPer

I dont think a replace function exists in the standard library. At least not if you are working with null-terminated strings.

Anyways, here’s what i would do (i won’t give you the code since its homework):

use the function itoa() to convert an integer to a null-terminated string(ie an array of chars).
Now loop through this array and for each element check if it equals ‘1’. If so output ‘*’, if not output something else.

Have fun :slight_smile:

whoops! yeah, i think cstr is a VB function - itoa is the C++ equivalent… damn, it’s amazing how much you can forget when you don’t use a language for a while… I use to live and breathe C++, now I can hardly construct asimple loop! I still remember enough to bugger up my VB programming, though…

I’ll toss in my two bits… C++ question on Straight Dope, who knew?

I’ll suggest a C++ solution rather than the C-within-C++ solutions suggested so far (just as a variant).

First, use an ostrstream object as a stream (like the cout object used in C++ for console I/O)… #include <ostrstream> is needed:

ostrstream stringout;

Output your variable via this object:

stringout << counter;

Extract the assembled string object:

string counterstring;
counterstring=stringout.str();

At this point, counterstring contains the string representation of the counter. This sequence of events is equivalent so far to using the itoa routine. But I’m not even sure itoa is ANSI standard C/C++… I’m pretty sure the standard way would normally use sprintf, and a character array as the destination. Anyway, moving on with my C++ solution.

You can iterate through counterstring as if it were an array of chars, up to a size limit of counterstring.size() and replacing all ‘1’ with ‘*’ (string objects are not necessarily null terminated as far as I know).

Alternately, you can simply output the characters as you go, in the loop, but outputting a ‘*’ if a ‘1’ is at the current position.

Personally, since I’m starting to get a serious handle on the Standard Template Library, I suggest (having #include <algorithm>):

replace(counterstring.begin(),counterstring.end(),‘1’,’*’);

using counterstring as a standard STL container which has a begin() iterator value and an end() iterator value.
Normally I wouldn’t produce code for homework either, but your professor probably won’t believe you wrote this if you pull STL code out of a hat without showing an understanding of it. :smiley:

Anyway, having produced a replaced counterstring, you can now output it via the cout object:

cout << counterstring << endl;
The nice thing about doing it using the ostrstream and string classes (even if you don’t use the replace algorithm) is that you avoid monkeying around with straight C arrays which are occasionally fraught with peril.

Yes, this isn’t the most efficient solution, but the code is clean. Efficiency can be gained by pre-creating the string object and passing it into the ostrstream object (so only one is ever created). Also, in a loop, the ostrstream can be reused if it is reset so it doesn’t have to be created or destroyed either. Lots of options for optimizations if necessary.

Or, you can use a straight C array of sufficient size, and sprintf, to remain cross-platform (behaves like printf, but with a new first parameter being a character buffer/array). I don’t personally condone using the (as far as I know) nonstandard itoa.

Comments?

Sorry, I meant:

#include <strstream>

back there. Pardon the glitch. Both ostrstream and istrstream are provided in there.

Sigh. My kingdom to be able to edit my posts.

Last fix, I promise.

Replace, in my discussion,

ostrstream

with

ostringstream
The use of ostrstream is deprecated as it deals with straight dynamically allocated character buffers, and is even more obnoxious to manage than a straight C array.

ostringstream on the other hand works with actual string objects and is far more memory-safe and easier to work with.

Oy, so much for making a good impression.

William_Ashbless: I agree on using streams. I shouldn’t be passing on my own bad habits :).
STL on the other hand is somewhat overkill IMHO.

If you’re willing to use streams (the ostringstream for example) for clarity or robustness of prewritten tools, why is it overkill to use the other parts of the STL?
:confused:

Also, ostringstream is in <sstream> not <strstream>.


#include <osstream>
#include <algorithm>
using namespace std;

...

  int x = value;
  ostringstream os;
  os << x;
  string s = os.string();
  string replaced = s;

  replace_copy(s.begin(), s.end(), replaced.begin(), '1', '*');
...


crimeny. #include <sstream> not <osstream>…

oh sigh. that’s os.str(). I’ll just go hide now.

Let’s kill this once and for all!

#include <iostream> //for the cin object, but otherwise not needed
#include <sstream> //for ostringstream
#include <algorithm> //for replace
#include <string> //for string
using namespace std;
int main()
{
int x;
cin >> x;
ostringstream os;
os << x;
string s = os.str();

replace(s.begin(), s.end(), ‘1’, ‘*’);
cout << s;

return 0;
}
Sorry to get explicit on everybody, but this was starting to get personally embarrassing. :slight_smile: This has been compiled and run, and has been cross-checked with the SGI STL and the ANSI C++ 1999 standard, just to be THOROUGHLY anal.

ARGH! :smiley:

Cornflakes, could you clarify what exactly it is you want? “the old two counter countdown problem” isn’t ringing a bell for me, and your description isn’t very complete. I’m skeptical that the problem these guys are solving is actually the problem you want solved… after all, these toy CS problems are usually ostensibly solving an actual “problem”, and I’m having a hard time imagining a problem, no matter how contrived, where the solution is to print “2323” instead of “123123”.

Ok, I thought of one: “you wish to simulate a broken manual typewriter…” :slight_smile:

galt has a point. The value of what we’re doing here is… well, roundabout nil. The sentence (fragment):

is about all we’re going on, and it ain’t much. :stuck_out_tongue:

Maybe if the counter were in binary, and you were replacing 1’s with '*'s and 0’s with something else, just to look pretty.

Oh well, now I’m just talking to myself and contributing no useful information. Hey Cornflakes, clarification please! :slight_smile: