Add value to beginning (left hand side) of string

Pages: 12
This is probably a stupid question, but how do you add a value to the beginning of a string instead of the end?

This is for an assignment and I have to convert the user input (always assuming its a valid decimal number) to binary and store it in a string. I've got up to dividing by two to get the remainder ...
You have to be more specific.

C or C++?

What do you mean by "value"? Integer? String?


[edit]
On re-reading your question, perhaps you want this:

1
2
3
string s = "234567";
char c = '1';
s = c + s;

Hope this helps.
Last edited on
Yea, thanks, that helps heaps. I can't believe i didn't think of it
Sorry about this, but how would you do the same thing but with an int, instead of a char? I'm having trouble with the conversion ...
Take the initial binary number (any int variable,suppose b_num) as 0.
In a loop, assign b_num = remainder*(power of 10) + b_num.


Something like this :
bnum=(dnum%2)*pow(10,x)+bnum;

Each time, raise x by 1 and divide the decimal integer(dnum) by 2.

or...
1
2
3
4
std::string s = "234567";
int i = 1;
s = ( char )( i + '0' ) + s;
std::cout << s << std::endl;


or
1
2
3
4
5
std::string s = "234567";
int i = 1;
char c = i + '0';
s = c + s;
std::cout << s << std::endl;
Last edited on
corbett when i do it your way an error comes up saying no match for operator * in ((double)remain * pow(1.0e+1, (double)i)) + binary. At the moment i have:

1
2
3
4
5
6
string binary = "";
for (int i = 0; input != 0; i++) {
    int remainder = input%2;
    binary = (remainder * power(10, i))  + "" + binary;
    input = input/2;
}
1
2
3
4
5
6
7
8
9
10
11
std::string binary;
binary.reserve( std::numeric_limits<unsigned int>::digits );

const unsigned int base = 2;
do
{
   unsigned int digit = input % base;
   binary += digit + '0';
} while ( input /= base );

binary.assign( binary.rbegin(), binary.rend() );
Last edited on
I don't think you need the power (or pow) in your code? Also, giblit's suggestion does make sense! If you alter line 4 accordingly, your code will work.

vlad's solution is the standard one -- add to back of string and then swap at the end -- but your add-to-the-front approach should produce the same result.

Note that the reserve is an optimization, to speed up operator++; the conversion code will work fine if it is omitted. If it is used, then you can remove the space capacity using binary.shrink_to_fit(); if you're using C++11 or [code]string(binary).swap(binary); .

Personally I would use reverse( binary.begin(), binary.end() ); (the std::reverse algorithm) rather than binary.assign( binary.rbegin(), binary.rend() );

As your code stands, it's line 4 which is very sick:

binary = (remainder * pow(10.0, i)) + "" + binary;

Breaking it down...

- pow(10.0, i) - returns a double [1]

Note that passing an int for the first parameter of pow() can confuse the compiler as there is more than one overload of pow(). But they do all return some sort of floating point number: float, double, long double.

- remainder * {value} - returns another double (int values are promoted to doubles before performing multiplication with a double.)

- {value} + "" - is invalid for a double value.

It's also invalid for an int value, so casting to an int would be a waste of time.

In this situation, "" is seen as the memory address of a blank string. And you can't add a memory address to an int. You can, however, add the value of the address:

1
2
    int i = 0;
    int j = i + (int)"";


or add an integer to an address; this is part of pointer arithmatic (see Pointer craft
http://www.cplusplus.com/articles/z186b7Xj/ )

1
2
    const char* p = "Hello world" + 6;
    cout << p << endl; // outputs "world" 


But there is a std::string overload of operator= which knows how to add a C null-terminated string to a C++ string. So you if you convert (not cast) the required value to a string, then you can add it on.

To convert a double or int to string you need to use an ostringstream (there are other ways, but this is the prefered method in C++ code.)

So, bearing all of this in mind, you could "fix" your code like this:

1
2
3
4
5
6
7
8
9
10
    string binary = "";
    for (int i = 0; input != 0; i++) {
        int remainder = input%2;
        //binary = (remainder * power(10, i))  + "" + binary;
        int j = (remainder * power(10, i))  + (int)"";
        ostringstream oss; // needs <sstream>
        oss << j;
        binary = oss.str() + binary;
        input = input/2;
    }


But the o/p value of this code for 64 is:

5329930432993043299304329930432993043299304329930


rather than the required

1000000


Andy
Last edited on
Recursive:
1
2
3
4
5
6
7
8
9
#include <string>

std::string to_binary( unsigned int v )
{
    if( v == 0 ) return "" ;
    else return to_binary(v/2) + char( v%2 ? '1' : '0' ) ;
}

std::string itob( unsigned int v ) { return v == 0 ? "0" : to_binary(v) ; }

1
2
3
4
5
std::string itob( unsigned int number ) 
{
	char digit = '0' + ( number & 1 );
	return ( ( number >>= 1 ) ? itob( number ) + digit : std::string( 1, digit ) );
}
Another recursive version, using bits stolen from both JLBorge's and vlad's code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void to_binary( unsigned int v, string& b )
{
	if( v == 0 ) return;
	b += v%2 ? '1' : '0';
	to_binary( v/2, b );
}

std::string itob( unsigned int v )
{
	if(0 == v)                  // Edit: Hack to fix the
		return string("0"); // 0 case...
	std::string binary;
	binary.reserve( std::numeric_limits<unsigned int>::digits );
	to_binary( v, binary );
	return string( binary.rbegin(), binary.rend() );
}


Note that in this case, the return sequence strips away any spare string capacity.

Andy
Last edited on
@andywestken


Your function returns an empty string in case when v is equal to 0. By the way 0 is a valid number
Also there is no any sence to call string( binary.rbegin(), binary.rend() ) for a recursive function..

So in my opinion your realization is not satisfactory.
I have done it a similar way to Andy and an error comes up saying "cast from const chat to int looses perception":

1
2
3
4
5
6
7
8
string binary = "";
for (int i = 0; input != 0; i++) {
  int remain = input%2 + (int)"";
  ostringstream s;
  s << remain;
  binary = s.str() + binary;
  input = input/2;
}
So in my opinion your realization is not satisfactory.

Well, maybe I should have put a smiley -- it was only a "whimscial" solution. I would use the standard while loop-plus swap in real life.

The point of previous feeble attempt was to avoid construction and destruction of strings during the iteration.

Andy

PS And I have put in a fix hack to fix the 0 case.
Last edited on
By the way what is the difference between ostringstream, istringstream and stringstream? I googled some examples earlier and they used different ones, is there a preferred stream for this conversion?
Last edited on
"cast from const chat to int looses perception":

I apologise for confusing the issue: I was saying you shouldn't use either (int)"" or ostringstream. You just need this:

1
2
3
4
5
6
string binary = "";
for (int i = 0; input != 0; i++) {
  int remain = input%2;
  binary = (char)(remain + '0') + binary;
  input = input/2;
}


As (a) the ascii code for '1' is one bigger than that for '0', and (b) remain is either 0 or 1, the (char)(remain + '0') will always evaluate to either (the char) '0' or '1', which can be added to the binary string.

But this version doesn't handle the 0 case: it input is 0, the for-loop neer runs. To ensure your loop runs once before terminating, you just need to swap to a do-while-loop:

1
2
3
4
5
6
7
8
string binary = "";
do {
  int remain = input%2; // no (int)""
  ostringstream s;
  s << remain;
  binary = s.str() + binary;
  input = input/2;
} while(input != 0);


This version handles the 0 case correctly, too.

Andy

PS By "perception", do you mean the same as "possible loss of data", which is what my compiler says)

PPS And regarding:
is there a preferred stream for this conversion?

Yes, to convert to a string you need an ostringstream.

o is for output, i is for input, the one with neither o nor i is both input and output.

You only need to output to the string stream to convert your string, so you should you use the output stream.

While it's not a good idea in this case, as each binary digit is either a '0' or '1' (which fits in a char) this code does do the same job using ostringstream and a string (but more slowly):

1
2
3
4
5
6
7
8
string binary = "";
for (int i = 0; input != 0; i++) {
  int remain = input%2; // no (int)""
  ostringstream s;
  s << remain;
  binary = s.str() + binary;
  input = input/2;
}

Last edited on
When i don't include (int)"" in my code an the compiler gets an error saying i have an undefined reference on about every line. e.g.
undefined reference to "std::basic_string<char, std::char_traits<char>, std::allocator<char> >::size() const"
or
undefined reference to `std::basic_istream<char, std::char_traits<char> >::operator>>(int&)'
do you know why this is happening?

"cast from const char to int looses perception" i thought may just mean that the conversion can't be done that way?
Last edited on
What is your code now?

Andy
I have started again and am trying to use bit shifting. the whole assignment is to convert a decimal number to hexadecimal uintvars (base 128 - http://en.wikipedia.org/wiki/Variable-length_quantity). At the moment my code looks like this (Note: this code isn't well thought through and isn't finished):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string>
#include <array>

using namespace std;

int main(int argc, char *argv[]){
        unsigned int input;
        cin >> input;
        cout << input << ":\t";

        int binary[1000];
        int count = 0;

        for(int i = 1000; input >= 0; i--) {
                int remain = input%2;
                input /= 2;
                binary[i] = remain;
                count++;

                if (count == 7) {
                        binary = binary * 0x7F;
                } else if ((count%7 == 0) && (count != 7)) {
                        binary = binary * 0xFF;
                }
        }
        cout << setbase(16);
        cout << bianry;
        return 0;
}
Last edited on
Pages: 12