Difference in bitset<10> and bitset<2>(input[i]) , need explanation - c++

I just learned some simple encryption today and wrote a simple program to convert my text to 10-bit binary. Im not sure if i'm doing it correctly, but the commented section of the code and the actual code has 2 different 10-bit outputs. I am confused. Can someone explain it to me in layman terms?
#include <iostream>
#include <string>
#include <bitset>
#include "md5.h"
using namespace std;
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
string input ="";
cout << "Please enter a string:\n>";
getline(cin, input);
cout << "You entered: " << input << endl;
cout << "md5 of " << input << ": " << md5("input") << endl;
cout << "Binary is: ";
// cout << bitset<10>(input[1]);
for (int i=0; i<5; i++)
cout << bitset<2>(input[i]);
cout << endl;
return 0;
}

tl;dr : A char is 8 bits, and the string operator[] returns the different chars, as such you accessed different chars and took the first two bits of those. The solution comes in treating a char as exactly that: 8 bits. By doing some clever bit manipulation, we can achieve the desired effect.
The problem
While I still have not completely understood, what you were trying to do, I can answer what a problem could be with this code:
By calling
cout<<bitset<10>(input[1]);
you are reading the 10 bits starting from the second character ( input[0] would start from the first character).
Now, the loop does something entirely different:
for (int i=0; i<5; i++)
cout << bitset<2>(input[i]);
It uses the i-th character of the string and constructs a bitset from it.
The reference of the bitset constructor tells us this means the char is converted to an unsigned long long, which is then converted to a bitset.
Okay, so let's see how that works with a simple input string like
std::string input = "aaaaa";
The first character of this string is 'a', which gives you the 8 bits of '01100001' (ASCII table), and thus the 10 bit bitset that is constructed from that turns out to print
0001100001
where we see a clear padding for the bits to the left (more significant).
On the other hand, if you go through the characters with your loop, you access each character and take only 2 of the bits.
In our case of the character 'a'='01100001', these bits are '01'. So then your program would output 01 five times.
Now, the way to fix it is to actually think more about the bits you are actually accessing.
A possible solution
Do you want to get the first ten bits of the character string in any case?
In that case, you'd want to write something like:
std::bitset<10>(input[0]);
//Will pad the first two bits of the bitset as '0'
or
for(int i=0;i<5;++i){
char referenced = input[i/4];
std::bitset<2>((referenced>>(6-(i%4)*2)));
}
The loop code was redesigned to read the whole string sequentially into 2 bit bitsets.
So since in a char there are 8 bits, we can read 4 of those sets out of a single char -> that is the reason for the "referenced".
The bitshift in the lower part of the loop makes it so it starts with a shift of 6, then 4, then 2, then 0, and then resets to 6 for the next char, etc...
(That way, we can extract the 2 relevant bits out of each 8bit char)
This type of loop will actually read through all parts of your string and do the correct constructions.
A last remark
To construct a bitset directly from your string, you would have to use the raw memory in bits and from that construct the bitset.
You could construct 8 bit bitsets from each char and append those to each other, or create a string from each 8 bit bitset, concatenate those and then use the final string of 1 and 0 to construct a large bitset of arbitrary size.
I hope it helped.

Related

How to convert char(or string, other type) -> bits?

In c++,
I don't understand about this experience. I need your help.
in this topic, answers saying use to_string.
but they say 'to_string' is converting bitset to string and cpp reference do too.
So, I wonder the way converting something data(char or string (maybe ASCII, can convert unicode?).
{It means the statement can be divided bit and can be processed it}
The question "How to convert char to bits?"
then answers say "use to_string in bitset"
and I want to get each bit of my input.
Can I cleave and analyze bits of many types and process them? If I can this, how to?
#include <iostream>
#include <bitset>
#include <string>
using namespace std;
int main() {
char letter;
cout << "letter: " << endl;
cin >> letter;
cout << bitset<8>(letter).to_string() << endl;
bitset<8> letterbit(letter);
int lettertest[8];
for (int i = 0; i < 8; ++i) {
lettertest[i] = letterbit.test(i);
}
cout << "letter bit: ";
for (int i = 0; i < 8; ++i) {
cout << lettertest[i];
}
cout << endl;
int test = letterbit.test(0);
}
When executing this code, I get result I want.
But I don't understand 'to_string'.
An important point is using of "to_string"
{to_string is function converting bitset to string(including in name),
then Is there function converting string to bitset???
Actually, in my code, use the function with a letter -> convert string to bitset(at fitst, it is result I want)}
help me understand this action.
Q: What is a bitset?
https://www.cplusplus.com/reference/bitset/bitset/
A bitset stores bits (elements with only two possible values: 0 or 1,
true or false, ...).
The class emulates an array of bool elements, but optimized for space
allocation: generally, each element occupies only one bit (which, on
most systems, is eight times less than the smallest elemental type:
char).
In other words, a "bitset" is a binary object (like an "int", a "char", a "double", etc.).
Q: What is bitset<>.to_string()?
Bitsets have the feature of being able to be constructed from and
converted to both integer values and binary strings (see its
constructor and members to_ulong and to_string). They can also be
directly inserted and extracted from streams in binary format (see
applicable operators).
In other words, to_string() allows you to convert the binary bitset to text.
Q: How to to I convert convert char(or string, other type) -> bits?
A: Per the above, simply use bitset<>.to_ulong()
Here is an example:
https://en.cppreference.com/w/cpp/utility/bitset/to_string
Code:
#include <iostream>
#include <bitset>
int main()
{
std::bitset<8> b(42);
std::cout << b.to_string() << '\n'
<< b.to_string('*') << '\n'
<< b.to_string('O', 'X') << '\n';
}
Output:
00101010
**1*1*1*
OOXOXOXO

shifting the binary numbers in c++

#include <iostream>
int main()
{
using namespace std;
int number, result;
cout << "Enter a number: ";
cin >> number;
result = number << 1;
cout << "Result after bitshifting: " << result << endl;
}
If the user inputs 12, the program outputs 24.
In a binary representation, 12 is 0b1100. However, the result the program prints is 24 in decimal, not 8 (0b1000).
Why does this happen? How may I get the result I except?
Why does the program output 24?
You are right, 12 is 0b1100 in its binary representation. That being said, it also is 0b001100 if you want. In this case, bitshifting to the left gives you 0b011000, which is 24. The program produces the excepted result.
Where does this stop?
You are using an int variable. Its size is typically 4 bytes (32 bits) when targeting 32-bit. However, it is a bad idea to rely on int's size. Use stdint.h when you need specific sizes variables.
A word of warning for bitshifting over signed types
Using the << bitshift operator over negative values is undefined behavior. >>'s behaviour over negative values is implementation-defined. In your case, I would recommend you to use an unsigned int (or just unsigned which is the same), because int is signed.
How to get the result you except?
If you know the size (in bits) of the number the user inputs, you can use a bitmask using the & (bitwise AND) operator. e.g.
result = (number << 1) & 0b1111; // 0xF would also do the same

C++ read and edit jpg file using ifstream

I'm trying to work on a simple image encryption project and I have a few questions I want to ask.
Should I store each byte of data from ifstream into a character like I did in my code?
Each byte printed is a weird symbol (which is correct), but why does adding 10(an int) to that always results in a number when printed?
int main() {
vector <char> data; // Stores each byte from image.jpg
ifstream fileIn("image.jpg", ios::binary);
int i = 0; // Used for accessing each item in data vector
while (fileIn){
//Add each character from the image file into the vector
data.push_back(fileIn.get());
cout << "Original: " << data[i] << endl; // Print each character from image.jgp
cout << "Result after adding: " << data[i] + 10 << endl; // This line is where I need help with
i++;
system("pause");
}
fileIn.close();
system("pause");
return 0;
}
Output:
Original: å
Result after adding: -112
Original: Æ
Result after adding: -100
Original:
Result after adding: 12
As you can see, adding 10 always results in a number. How do I increment these values correctly so that I can change it back later?
Thank you for any help.
When you do an arithmetic operation (like addition) with a value of a type that is smaller than int (like char in your case) then that value will be promoted to int and the operation is done using two int values.
So the expression data[i] + 10 is equivalent to static_cast<int>(data[i]) + 10.
Read more about integral promotion and arithmetic operator conversions.
As for how to solve your problem, first you have to make sure that the result of the operation actually fits in a char. What if the byte you have read is 127 and you add 10? Then the result is out of bounds of a signed char (which seems to be what you have).
If the result is not out of bounds, then you can just cast it:
char result = static_cast<char>(data[i] + 10);
As a small side-note, if you're reading binary data you are not really reading characters, so I suggest using a fixed-with integer type like int8_t or uint8_t instead of char. On supported platforms (which is just about all these days) they are just aliases for signed char and unsigned char (respectively) but using the aliases is more informative for the readers of your code.

Binary numbers with leading zeros

I've been working on an assignment where I've to use bitwise operators to (OR, AND, or NOT )
the Program has a fixed 4X4 matrix and the user suppose to enter a query to the program ANDing two BINARY numbers, ORing them ...etc
the problem is the "zero leading" binary numbers for example:0111 are shown with value 73
even when I manage to cout it with setfill() and setw()
I can't perform the bitwise operation on the actual binary value!
N.B: I've tried strings instead of ints but the bitwise operation still doesn't apply.
For Example:
if I want to AND two binary values let's say
int x=1100 and int y=0100 in another int z
z=x&y;
the result suppose to be 0100
But the result that appears is 64
which also the result that appears if I tried to print y to the screen
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
int Matrix[4][4]={{1,1,0,0},{1,1,0,1},{1,1,0,1},{0,1,0,0}};
string Doc[4]={"Doc1","Doc2","Doc3","Doc4"};
string Term[4]={"T1","T2","T3","T4"};
cout << "THE MATRIX IS:"<<endl;
for(int i=0;i<4;i++)
{
cout<<"\t"<<Doc[i];
}
cout<<"\n";
for(int row=0; row<4;row++)
{
cout<<Term[row]<<"\t";
for(int col=0;col<4;col++)
{
cout<<Matrix[row][col]<<"\t";
}
cout<<endl;
}
int term1=1100;
cout<<"\nTerm1= "<<term1;
int term2=1101;
cout<<"\nTerm2= "<<term2;
int term3=1101;
cout<<"\nTerm3= "<<term3;
int term4=0100;
cout<<"\nTerm4= "<<setfill('0')<<setw(4)<<term4;
int Q=term1&term4;
cout<<"\n Term1 and Term4 ="<<Q;
system("pause");
return 0;
}
When you write 0111 in your code the compiler will assume it's octal since octal numbers start with zero. If you wrote 111 it would be decimal.
C++14 added binary literal prefix so you can write 0b111 to get what you want.
Your question still not clear. You have said you have 4x4 matrix, what type of matrix or 2D array is it? So maybe you can elaborate more.
Regarding dealing with binaries, what students usually confuse about, is that if you are using integer variables, you can use bitwise manipulation over these variables and the result will still be read as an integer format. And if you happen to seek seeing what is happening during the bitwise manipulation and visualize the process, you can always use bitset object as follow.
#include <iostream>
#include <bitset>
int main() {
int a = 7, b = a>>3, c = a<<2;
std::cout << "a = " << std::bitset<8>(a) << std::endl;
std::cout << "b = " << std::bitset<8>(b) << std::endl;
std::cout << "c = " << std::bitset<8>(c) << std::endl;
}
Which should print
00000111
00000000
00011100
So play around with your variables and then visualize them as binaries using bitset is the best way to teach you how HEX, OCT, DEC, and BIN representation works.
And by the way if you are reading 73 as an integer, then this memory address stores 0100 1001 as binary if it's unsigned, and 111 as Octal which is base 8 number representation. See http://coderstoolbox.net/number/
Best of luck

convert a string to integer in c++ without losing leading zeros

hello i have a problem with converting a string of numbers to integer.
the problem is that using atoi() to convert the string to integer i loose the leading zeros.
can you please tell me a way to do that without loosing the leading zeros?
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
struct Book{
int id;
string title;
};
struct Author{
string firstName;
string lastName;
};
Author authorInfo[200];
Book bookInfo[200];
void load ( void )
{
int count = 0;
string temp;
ifstream fin;
fin.open("myfile.txt");
if (!fin.is_open())
{
cout << "Unable to open myfile.txt file\n";
exit(1);
}
while (fin.good())
{
getline(fin, temp, '#');
bookInfo[count].id = atoi(temp.c_str());
getline(fin, bookInfo[count].title, '#');
getline(fin, authorInfo[count].firstName, '#');
getline(fin, authorInfo[count].lastName, '#');
count++;
}
fin.close();
}
Ok, so I don't think you actually WANT to store the leading zeros. I think you want to DISPLAY a consistent number of digits in the output.
So, for example, to display a fixed size id with 5 digits [note that an id of 100000 will still display in 6 digits - all it does here is make sure it's always at least 5 digits, and fill it with '0' if the number is not big enough], we could do:
std::cout << std::setw(5) << std::setfill('0') << id << ...
Alternatively, as suggested in other answers, you don't want to use the ID in a form that is an integer, you could just store it as a string - unless you are going to do math on it, all that it changes is that it takes up a tiny bit more memory per book.
An integer does not have leading zeroes. Or perhaps, more correctly, it has between zero and an infinite number of them. The numbers 42, 042 and 000000042 (other than in the source code where a leading 0 indicates a different base) are all forty-two.
If you want to keep the leading zeroes, either leave it as a string or store more information somewhere as to how big the original string was. Something like this would be a good start:
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <cstdlib>
int main (void) {
// Test data.
const char *sval = "0042";
// Get original size.
int size = strlen (sval);
// Convert to int (without leading 0s).
// strtol would be better for detecting bad numbers.
int ival = atoi (sval);
// Output details.
std::cout << sval << " has size of " << size << ".\n";
std::cout << "Integer value is " << ival << ".\n";
std::cout << "Recovered value is " << std::setw(size)
<< std::setfill('0') << ival << ".\n";
return 0;
}
which outputs:
0042 has size of 4.
Integer value is 42.
Recovered value is 0042.
A = strlen(string) returns the number of characters in your string (say number of digits comprehensive of leading zeros)
B = log10(atoi(string)) + 1 returns the number of digits in your number
A - B => number of leading zeros.
Now you can format those as you prefer.
There's no such thing as "leading zeros" in a number. "Leading zeros" is a property of a specific notation, like decimal ASCII representation of a number. Once you convert that notation to a conceptually abstract numerical representation, such metric as "number of leading zeros" is no longer applicable (at least in decimal terms). It is lost without a trace.
A number is a number. It doesn't have any "zeros", leading or otherwise.
The only thing you can do is to memorize how many leading zeros you had in the original notation (or how wide was the field), and then later, when you will convert the number back to decimal ASCII representation, re-create the proper number of leading zeros using that stored information.
BTW, in your case, when the input number represents a book ID with some pre-determined formatting (like leading zeros), you might consider a different approach: don't convert your book ID to int. Keep it as a string. It is not like you are going to have to perform arithmetic operations on book IDs, is it? Most likely all you'll need is relational and equality comparisons, which can be performed on strings.
I have encountered this type of problem last month!
I think you can use the Format() method provided by Class CString:
CString::Format() formats and stores a series of characters and values in the CString. Each optional argument (if any) is converted and output according to the corresponding format specification in pszFormat or from the string resource identified by nFormatID.
For example:
CString m_NodeName;
m_NodeName.Format(_T("%.4d"),Recv[2]*100+Recv[3]);
// %.4d means the argument will be formatted as an integer,
// 4 digits wide, with unused digits filled with leading zeroes
For the detail you can find here:
http://msdn.microsoft.com/zh-cn/library/18he3sk6(v=vs.100).aspx
If you need the leading zeros, then int is not the correct data type to use. In your case you may be better off just storing the original string.
There is no way of storing an int with leading 0s.
What you may want to do instead, is have a class do it for you:
class intWithLeadingZeros {
int number;
int numberOfLeadingZeros;
intWithLeadingZeros( string val )
{
// trivial code to break down string into zeros and number
}
string toString() {
// trivial code that concatenates leading 0s and number
}
};