binary string to ascii value conversion for beginners

Alright so I know there's a few discussions about this on the forum but the help and solutions are beyond my abilities. I'm a beginning c++ student and have been given the task to convert a string of characters to the binary representation, then, I need to be able to convert a binary string to the ascii character values. I got the first part just fine but I'm stuck on converting from binary to ascii values. All the discussions about this that I've read involve pointers, arrays, and/or user defined functions and we haven't learned covered any of those options yet.
So, is there a way do do this with knowledge only of loops, libraries, and defining variables? I've looked through two c++ books, the cplusplus forums, and the whole list in the reference section and I'm just not figuring out how to do such a task. I think I sort of get arrays from help I received figuring out the first part but I guess I don't get them enough. If, I could get some hints, clues, or any nudges in the right direction on how to do this with my limited knowledge I'll be forever grateful. Thank you in advance and here's the code I have so far. Feel free to critique me if I've done anything in unnecessary ways. :)

#include <iostream>
#include <string>
#include <bitset>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <climits>

using namespace std;

int main()
{

cout << endl;
cout << "ΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩ" << endl;

string char_in;

cout << "Enter a string of characters: ";
getline(cin, char_in);

cout << endl;

cout << char_in << endl;
for (size_t i = 0; i < char_in.size(); ++i)
{
cout << bitset<8>(char_in[i]);
}

cout << endl << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl;

string bin_in;

cout << "Enter a string of binary: ";
getline(cin, bin_in);

cout << bin_in << endl; //Checking that the input worked.

/* What will make this work!? I know I probably need a for loop. I've tried everything from the forum and it's all beyond my capabilities at this point. */

cout << "ΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩ" << endl;
cout << endl;

return 0;

}
You can use bitset for this as well:

This converts it to a number:
http://www.cplusplus.com/reference/bitset/bitset/to_ulong/

This sets the bits:
http://www.cplusplus.com/reference/bitset/bitset/operator%5B%5D/

like so:
1
2
3
4
5
6
bitset<32> bs; // To convert it with to_ulong() only 32 bits are allowed
for(int i = 0; ...; ++i)
{
  if(bin_in[i] == '1')
    bs[i] = 1;
}


The problem is that the bits are entered in reverse oder. So either you reverse the string:

http://www.cplusplus.com/reference/algorithm/reverse/?kw=reverse

or you calculate the index like so: if(bin_in[bin_in.size() - 1 - i] == '1')
There is a bitset constructor which takes string directly: bitset<32> bs(bin_in);.
No reversing needed.
http://www.cplusplus.com/reference/bitset/bitset/bitset/
Hi thanks guys, with your help I finally got an output other than zero! :)
Still have a problem with the printing of the ascii values though. So I tried that sample code from coder777. I tried the alternative way of calculating the index with the "if(bin_in[bin_in.size() - 1 - i] == '1')" but the string still seems to print in reverse, it's still in binary, and it only prints one byte with a bunch of extra zeros. I also tried MiiniPaa's suggestion but that seemed to blow things up. The compiler didn't like that at all.
So, since I got all the extra zeros from the bitset<32> stuff I tried bitset<8> since it's my understanding that each ascii character is represented by a byte. But the compiler got mad at me for that too. I'm currently reading about the reverse in the algorithm library and I'm about to try it here in a second. But as for my other continuing issues, if I could get another hint that would be wonderful. Thanks again and here's a snippet of the new portion of code with the output I got. The snippet is where my commented out section is in the code I posted above.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
string bin_in;
    bitset<32> bs;
    
    cout << "Enter a string of binary: ";
    cin >> bin_in;
    
    cout << endl;
    
    for(int i = 0; i < 8; ++i)
    {
        if(bin_in[bin_in.size() - 1 - i] == '1')
            bs[i] = 1;
    }
    cout << bs << endl; // How do I get it to print the ascii charcters? 


output:

ΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩ
Enter a string of characters: C++ is making me sad. :(

C++ is making me sad:(\357. :(
010000110010101100101011001000000110100101110011001000000110110101100001011010110110100101101110011001110010000001101101011001010010000001110011011000010110010000111010001010001110111110011100100000101110111110011100100000101110111110011100100000101110111100101110001000000011101000101000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Enter a string of binary: 010000110010101100101011001000000110100101110011001000000110110101100001011010110110100101101110011001110010000001101101011001010010000001110011011000010110010000111010001010001110111110011100100000101110111110011100100000101110111110011100100000101110111100101110001000000011101000101000

00000000000000000000000000101000
ΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩΩ

Program ended with exit code: 0


So yea, there its is, I'm going to work on getting that last output reversed but I'm still kinda lost on the getting the original message back from the binary. Thanks you all. :)
Read bitstring 8 characters at a time, then convert it to number and cast to char:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bitset>
#include <iostream>
#include <sstream>
#include <string>

int main()
{

    std::string line;
    std::cout << "Enter binary string: ";
    std::getline(std::cin, line);
    std::istringstream in(line);
    std::bitset<8> bs;
    while(in >> bs)
        std::cout << char(bs.to_ulong());
}
Enter binary string: 01000011001010110010101100100000
C++
Oh your the best! That works perfectly. I'm so happy now. I had gone through attempts involving 20 times more code than that with nothing but failure to show for it and all it took was 7 lines and an extra header. Thank you so much!
Ok there's one more thing I'm trying to do. I was trying to add a for loop around the binary to ascii portion of the code to produce an error if the user failed to enter only 1's and 0's, and then re-prompt the user for the binary input. My for loop failed on me. By putting that block of code in the for loop it for some reason uninitialized the variables within it. What I did was for (1 = 0; 1 < ?; ++i) but as the ? shows I couldn't figure out which variable to stick in there. I then decided an if/then would be easier but i'm not sure about the part where I would say:
If ((bin_in != 1)||(bin_in != 0))
{
cout << "error, print only 1's or 0's: ";
getline(cin, bin_in);
}

However it seems it's not that simple or I'm missing something important that I can't seem to see. Or should I do the if statement nested within a for loop, or are my initializations just wrong?

*Update* I tried
while ((bin_in != 1)||(bin_in != 0))
{
cout << "Error, an invalid input has been entered. Enter only 1's and 0's: ";
}
but I get a semantic error that I don't understand, invalid operands to a binary expression.
Last edited on
You need to loop over allcharacters in string and check if each of it is 0 or 1.
Thee is a standard algorithm which does exactly that:
http://en.cppreference.com/w/cpp/algorithm/all_any_none_of
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <algorithm>
#include <bitset>
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    std::string line;
    std::cout << "Enter binary string: ";
    bool correct = false;
    while ( !correct ) {
        std::getline(std::cin, line);
        correct = std::all_of(line.begin(), line.end(), [](char c)
                              { return c == '1' || c == '0'; });
        if( !correct )
            std::cout << "error, print only 1's or 0's: ";
    }
    std::istringstream in(line);
    std::bitset<8> bs;
    while(in >> bs)
        std::cout << char(bs.to_ulong());
}
That's fantastic, eternal thanks to you. :)
Uh oh! I ran into a weird problem. So I had done my code in Xcode. It works flawlessly. But then I copy and pasted it into vim on my schools server to turn it in and the compiler won't compile it. The errors are as follows:

strings.cpp: In function ‘int main()’:
strings.cpp:45: error: expected primary-expression before ‘[’ token
strings.cpp:45: error: expected primary-expression before ‘]’ token
strings.cpp:45: error: expected primary-expression before ‘char’
strings.cpp:45: error: ‘all_of’ was not declared in this scope

my line 45 corresponds to your line 14. I took out the [] before char and it sill wants a primary expression before char and all_of is still not declared in the scope, so, I put it back in. I read up on the all_of function and your line 14 is 100% correct based on the reference section here in cplusplus.com. None of my peers or TA's can figure out why there's problem. Any thoughts? I'm completely baffled.
all_of() exists from C++11 on as well as the lambda [] function. Either your compiler is too old or you need to switch on the flag for this.
Bummer, so my guess is that my compiler is too old. Is there a similar function that works the same way or will I have to go about this a different way?
You can update your compiler (or just turn on the switch to work with C++11)

Otherwise, you can try to find any symbol which is not 1 or 0.
http://en.cppreference.com/w/cpp/string/basic_string/find_first_not_of
Might help you.
Alright, I'm attempting everything I can in order to avoid having to change my code. So in reading up on things, I saw a recommendation to use clang++ instead of g++ to compile not sure if I did it right but by doing, clang++ strings.cpp -o strings, I only got one error on the previously mentioned line. It also says that it's expecting an expression before [](char bit). Is there anything I can try to put before the []? I just don't know what I could put there that would make sense since the reference section doesn't precede the [] with anything in it's example.
Also, as an update to the previous compiler issues, I have to build my code in vim on my schools server which is also where the compiler resides. I'm assuming they would have to upgrade the compiler as I probably don't have permission to do such things. But if I could and for future reference how would I go about upgrading the compiler or where can I find instructions for that. I looked around but didn't really find anything that I understood. And one last question. Turning on a "switch" was mentioned, again how is that done and/or are there good instructions for that somewhere, and would the switch work for me since I'm on my schools server?
Sorry for my never-ending questions, I got through physics but CS might be the end of me. :)
I only got one error on the previously mentioned line
Because you did not told clang to use c++11 too. Changing compiler will not help if you won't configure them properly.

Turning on a "switch" was mentioned, again how is that done and/or are there good instructions for that somewhere
What is your IDE/compiler?
With GCC/clang you need to pass -std=c++11 to command line.
Um, I forget which is which with this stuff but I'm using a secure shell in Terminal on a mac. We build our code in Vim. And then we compile with g++ filename.cpp -o filename.
And then we compile with g++ filename.cpp -o filename
At least add several others mandatory flags:
1
2
3
//      ↓ Use C++11 standard
g++ -std=c++11 -Wall -Wextra filename.cpp -o filename
//                ↑   ↑  Make compiler give you a warnings on sloppy or dangerous code. 
Hi,

http://clang.llvm.org/docs/UsersManual.html


I always use the -pedantic flag :+)

There are some others that aren't on despite -Wall -Wextra -pedantic, it is worth having a detailed read of the documentation. Some that come to mind are:

1
2
3
4
-Wswitch-default
-Wswitch-enum
-Wfloat-equal
-Wfloat-conversion


Although, I seem to manage to never do these things in my code.


https://gcc.gnu.org/onlinedocs/


Hope all goes well :+)
Alrighty, so my instructor doesn't seem to want to move on from this code. So I've had to modify it a few times since I last came on here for help and I'm stumped on something new. We are supposed to have our code take command line arguments now. I've been reading everything I can on command line arguments and I just don't get it. I put "int arc, char *argv[]" in the parameters of main but I have no clue what to do now. My TA's told me how easy it was and that I just have to "access the conversion functions with argv[]." That blew my mind and I don't know and I still don't know where to begin. I'm supposed to be able to execute the file with ./filename -b "binary number" -a "characters".
How might I go about doing such a thing. As always any hints and useful bits of information are greatly appreciated.

Here's the code:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

#include <iostream>
#include <string>
#include <bitset>
#include <sstream>
#include <algorithm>

using namespace std;

void get_user_char( string &char_in ) // Char_in value passes to bin_out.
{

	cout << endl;

	// Prompt user for a string of characters.
	cout << "Enter a string of characters: ";

	// Reads the user's input and gives that value to char_in.
	getline( cin, char_in );

	cout << endl;

}

void get_user_bin( string &bin_in ) // Bin_in value passes to char_out.
{

	// Prompt user for binary string.
	cout << endl << "Enter a string of binary: " << endl;

	bool correct_input = false;

	/* While loop prompts the user to enter a binary 
	 * string until only 1's and 0's are entered.*/
	while ( !correct_input )
	{
		//  Read the users input and gives it to bin_in.
		getline( cin, bin_in );

		// all_of checks that all elements in the range are true.
		correct_input = all_of( bin_in.begin(), bin_in.end(), [](char bit){ return bit == '1' || bit == '0'; } );

		// Error promt.
		if ( !correct_input )
		{
			cout << "Error, print only 1's and 0's: ";
		}
	}

	// Return the users binary input.
	cout << endl << "You entered: " << endl << bin_in << endl;

}

string char_to_bin( string bin_out ) // Convert ASCII to binary.
{

	// Return the users ASCII input.
	cout << "You entered: " << bin_out << endl << endl;

	// A-B Conversion.
	cout << "Your input in binary is: " << endl;

	// size_t is an unsigned integral type that works with the sizeof operator.
	for ( size_t i = 0; i < bin_out.size(); ++i )
	{
		// Prints binary values of the characters. 
		cout << bitset<8>( bin_out[i] );
		// Bitset stores the characters into their bytes.
	}

	cout << endl;

	return bin_out;

}

string bin_to_char( string char_out ) // Convert binary to ASCII.
{

	// Allows the sequence of strings to be accessed directly as a string.
	istringstream in( char_out );

	// Divides the bits into bytes.
	bitset<8> bs;

	cout << endl << "Your input in ASCII is: ";

	// B-A Conversion
	// Loop extracts the bytes in the string and prints them as there ascii values.
	while ( in >> bs )
	{
		cout << char( bs.to_ulong() );
	}

	cout << endl;

	return char_out;

}

void ohm_border() // Seperates code output from other things on the flip screen. 
{

	cout << endl << "=======================================================" << endl;

}

void tilda_border() // Separates char→bin and bin→char sections of the code's outputs.
{

	cout << endl << "-------------------------------------------------------" << endl;

}

int main( int argc, char *argv[] )
{

	string input1, input2;

	ohm_border();

	get_user_char( input1 );
	char_to_bin( input1 );

	tilda_border();

	get_user_bin( input2 );
	bin_to_char( input2 );

	ohm_border();

	return 0;

}


Thanks again for any help. :)
Topic archived. No new replies allowed.