Converting chars to byte representation using C++ - c++

What would be the most efficient yet simplest way to convert a char to its unsigned binary representation (bytes where the MSB is 0)? I have a method set up like this:
string AsciiToBinary(char value) {
string binary = "";
int code = value;
while (code > 0) {
if ((code % 2) == 1) {
binary.append("1", 1);
} else {
binary.append("0", 1);
}
code = code / 2;
}
return binary;
}
I am assuming that setting an int to a char sets the char's ASCII value to the int. However, my results do not match the ASCII table. I am implementing this function as follows:
char head = stack.pop();
int code = head; // do not need to parse
string binary;
while (!stack.isEmpty()) {
binary = AsciiToBinary(code);
outfile << binary << endl;
binary.clear();
head = stack.pop();
code = head;
}
I have stored all of the chars in a stack.
Thank you for info and direction.

std::string::append() adds the character onto the end of the string. So you are putting the bits on in the reverse order: the LSB is the first character and vice versa. Try this: binary.insert (0, 1, (code % 2 == 1) ? '1' : '0');

This method works well and is editable for all those interested and learning C++:
using namespace std; // bad for updates
#include <string>
string AsciiToBinary(char value) {
string binary = "";
unsigned int code = value;
unsigned int chk = value;
while (code > 0) {
if ((code & 1) == 1) {
binary.append("1", 1);
} else {
binary.append("0", 1);
}
code = code / 2;
}
reverse(binary.begin(), binary.end());
if (chk < 64) {
binary.insert(0, "00");
} else {
binary.insert(0, "0");
}
return binary;
}

Related

no instance of overloaded function "stoi" matches the argument list

I'm trying to write a function that takes 4 characters,with the first and third characters being numbers,and the second and fourth characters being operators,the function converts the the first and third characters into integers,and calculates the output based on the operator between them (or doesn't do that,if the operator stored in the fourth character has a higher priority).
This is my attempt:
#include <iostream>
#include<string>
using namespace std;
string calculate(char ch1,char ch2,char ch3,char ch4);
int main() {
int i = 1;
string input = "4/1+1-2*2" ;
string part;
int leng;
while(1){
char cha1 = input[i - 1];
char cha2 = input[i];
char cha3 = input[i + 1];
char cha4 = input[i + 2];
part = calculate(cha1,cha2,cha3,cha4);
if (part == "NULL") {
i += 2;
}
else{ input = input.replace((i-1),3,part); }
leng = input.size();
if (i == leng - 1) {
i = 1;
}
}
}
string calculate(char ch1, char ch2, char ch3, char ch4){
int in1;
int in3;
int result;
string part;
if (ch2 == '-') {
if (ch4 == '*') {
part = 'NULL';
}
else if (ch4 == '/') {
part = "NULL";
}
else {
in1 = stoi(ch1);
in3 = stoi(ch3);
result = in1 - in3;
part = to_string(result);
}
}
else if (ch2 == '+') {
if (ch4 == '*') {
part = "NULL";
}
else if (ch4 == '/') {
part = "NULL";
}
else {
in1 = stoi(ch1);
in3 = stoi(ch3);
result = in1 + in3;
part = to_string(result);
}
}
else if (ch2 == '*') {
if (ch4 == '*') {
part = "NULL";
}
else if (ch4 == '/') {
part = "NULL";
}
else {
in1 = stoi(ch1);
in3 = stoi(ch3);
result = in1 * in3;
part = to_string(result);
}
}
else if (ch2 == '/') {
if (ch4 == '*') {
part = "NULL";
}
else if (ch4 == '/') {
part = "NULL";
}
else {
in1 = stoi(ch1);
in3 = stoi(ch3);
result = in1 * in3;
part = to_string(result);
}
}
return part;
}
The program probably won't work as intended in it's current state,but I'll worry about that later,for now I want to deal with the stoi() function,because for every line that contains this function,I get the error in the title.
I want to know what I'm doing wrong,and what this error message exactly means to avoid getting it in the future.
Thank you in advance.
std::stoi expects a std::string as argument, but you are giving it a single char.
There is no direct conversion from char to std::string, so you need to be explicit about it:
stoi(string(1, ch1));
Here string(1, ch1) creates a string of length 1 containing only the character ch1.
Alternatively, if you are sure that ch1 is a digit at that point (stoi will throw if it isn't) you can simply subtract '0', since the digits are guaranteed to be correctly ordered in the character set:
ch1 - '0'
Or rather, you probably want to pass a std::string directly to your function, instead of multiple individual chars. You can use the .substr member function to get substrings from a string.
std::stoi takes a std::string as its argument, but you are giving it a char.
You can directly convert char's to ints via a cast like this:
int num = ch1 - '0';
(You may want to write a function to do this, and use proper c++ style casts)
Or, covert the char to a string, or use strings to start with
Example:
int main() {
char ch1 = '9';
int in1 = ch1 - '0';
std::cout << in1 << "\n";
}

C++ Console : Parsing METAR data

I am working on my first web app (weather visualization) that requires some light c++ on the back end. I am using wget to download the raw text, and c++ console to parse the data and it then writes HTML. This works great so far.
METAR is basically raw weather data from a station. (Time, Date, Conditions, Temp etc). The one I am using currently is :
2018/08/10 08:09
KBAZ 100809Z AUTO 00000KT 10SM BKN012 26/23 A3002 RMK AO2 T02610233
I have been able to store each set of data into different variables. The set I am looking at with the issue is the "26/23" above, which is the temperature and dew point in Celsius.
So far I have a string called tempAndDewpoint with "26/23" stored in it... I am using substr(0,2) to return the just temperature in a new string called temperature. (since the first number is temperature). This works great.
My question is, what happens if the temperature is below 10, like 9? I could no longer use substring(0,2) because that would then return "9/" as the current temperature.
I hope to find some guidance with this that is not too complicated for me to duplicate. I wasn't even sure what to name this question as I am not sure what this issue is called. Surely it must be common?
Beware: Negative temperatures in METAR are prefixed with M. So these are valid temp groups: 5/M2 or M8/M12 (negative dew points are in fact icing points). So I would not use a custom parser here:
struct TTD {
short int t;
short int td;
bool parse(const char *tempAndDewpoint) {
const char *next;
t = parse_partial(tempAndDewpoint, &next);
if (*next != '/') return false;
td = parse_partial(next + 1, &next);
return (*next == '\0');
}
private:
static short int parse_partial(const char *beg, const char **next) {
bool neg = false;
short int val = 0;
if (*beg == 'M') {
neg = true;
beg += 1;
}
while (*beg >= '0' && *beg <= '9') {
val = val * 10 + (*beg - '0');
beg += 1;
}
*next = beg;
if (neg) val = -val;
return val;
}
};
The simple solution is to not store as a string at all. Split the string into two independent numbers. As stated in the other answer you do need to take care of "M" being a prefix for negative numbers but there is no read to parse the numbers by hand:
int parseNum(const std::string& str)
{
size_t pos;
int num;
if (!str.empty() && str.front() == 'M')
{
num = -std::stoi(str.substr(1), &pos);
if (pos != str.size() - 1)
{
throw std::invalid_argument("invalid input");
}
}
else
{
num = std::stoi(str, &pos);
if (pos != str.size())
{
throw std::invalid_argument("invalid input");
}
}
return num;
}
size_t slash = tempAndDewpoint.find("/");
if (slash == std::string::npos)
{
throw std::invalid_argument("invalid input");
}
int temp = parseNum(tempAndDewpoint.substr(0, slash));
int dew = parseNum(tempAndDewpoint.substr(slash + 1));

Reading a file bit by bit to form a Huffman Coding Tree

This problem requires me to read a header from a file, that is a bit based compress file, to extract the necessary information that I need in order to form the tree. Normally the head looks as such: "1g1o01s1 01e1h01p1r0000013\n" The 1's represents the leaf nodes and the 0's represent when we need to form a tree. There is also an extra 0 which separates the header info from the number of characters in the file. I have everything that will create the tree and print it's contents, however I am having trouble reading the information. When I execute the code one of my out puts contains a '1' in the leaf when it shouldn't. Does this mean that I am miss handling the bytes when I want to get the bits?
Here is the code from main:
while((num = ReadBit(fp, 'b')))
{
//printf("num = %c\n", num);
if(num == '1')
{
letter = ReadBit(fp, 'c');
printf("letter = %c\n\n", letter);
new_node = CreateNode(letter);
Push(&Fake, new_node);
Onecount++;
}
if(num == '0')
{
First = Pop(&Fake);
Second = Pop(&Fake);
new_node = malloc(sizeof(LEAF));
new_node-> rchild = First;
new_node-> lchild = Second;
Push(&Fake, new_node);
Zerocount++;
}
if(Onecount == Zerocount)
{
break;
}
}
Here is the code from the ReadBit funciton
int ReadBit(FILE *fp, char mode)
{
unsigned char value;
unsigned static int count = 0;
unsigned static char letter = 0;
unsigned static char byte;
unsigned static int place;
/* This is the bit mode, it will grab the first bit from the current byte and return it */
if(mode == 'b')
{
if(count == 0)
{
fread(&byte, 1, 1, fp);
}
value = (((byte & (1 << (7 - count))) == 0) ? '0' : '1');
count++;
letter = byte << count;
if(count == 8)
{
count = 0;
}
place = 8 - count;
}
/*This is "character" mode. It will grab enough bits in order to create a byte that will be a letter */
if(mode == 'c')
{
if(count == 0)
{
fread(&letter, 1, 1, fp);
}
else
{
/* This will read in a new byte and add in as many bits as we need to complete a byte from the previously saved bits */
fread(&byte, 1, 1, fp);
value = letter + (byte >> place);
}
}
return(value);
}

How to reverse a string in blocks of 2 in C++?

What I want to do is convert a string such as
"a4b2f0" into "f0b2a4"
or in more simple terms:
turning "12345678" into "78563412"
The string will always have an even number of characters so it will always divide by 2. I'm not really sure where to start.
One simple way to do that is this:
std::string input = "12345678";
std::string output = input;
std::reverse(output.begin(), output.end());
for(size_t i = 1 ; i < output.size(); i+=2)
std::swap(output[i-1], output[i]);
std::cout << output << std::endl;
Online demo
A bit better in terms of speed, as the previous one swaps elements twice, and this one swap each pair once:
std::string input = "12345678";
std::string output = input;
for(size_t i = 0, middle = output.size()/2, size = output.size(); i < middle ; i+=2 )
{
std::swap(output[i], output[size - i- 2]);
std::swap(output[i+1], output[size -i - 1]);
}
std::cout << output << std::endl;
Demo
Let's get esoteric... (not tested! :( And definitely not built to handle odd-length sequences.)
typedef <typename I>
struct backward_pair_iterator {
typedef I base_t;
base_t base;
bool parity;
backward_pair_iterator(base_t base, parity = false):
base(base), parity(parity) {
++base;
}
backward_pair_iterator operator++() {
backward_pair_iterator result(base, !parity);
if (parity) { result.base++; result.base++; }
else { result.base--; }
return result;
}
};
template <typename I>
backward_pair_iterator<I> make_bpi(I base) {
return backward_pair_iterator<I>(base);
}
std::string output(make_bpi(input.rbegin()), make_bpi(input.rend()));
static string reverse(string entry) {
if (entry.size() == 0) {
return "";
} else {
return entry.substr (entry.size() - 2, entry.size()) + reverse(entry.substr (0, entry.size() - 2));
}
}
My method uses the power of recursive programming
A simple solution is this:
string input = "12345678";
string output = "";
for(int i = input.length() - 1; i >= 0; i-2)
{
if(i -1 >= 0){
output += input[i -1];
output += input[i];
}
}
Note: You should check to see if the length of the string when mod 2 is = because otherwise this will go off the end. Do something like I did above.

Need help on Dissection C++ number 2 sting function

I found a bug on the function below. When temp = 10. It will convert temp to string '01'. instead of string'10'. I can't tell why?
Is there any better to convert Num to Str? Thanks.
completed Num2Str() as this,
static bool Num2Str(string& s, const T& value)
{
int temp = static_cast<int>(value); // When temp = 10.
s.push_back(char('0' + temp % 10));
temp /= 10;
while(temp != 0)
{
s.push_back(char('0' + temp % 10));
temp /= 10;
}
if(s.size() == 0)
{
return false;
}
if(s.find_first_not_of("0123456789") != string::npos)
{
return false;
}
return true;
}
Use std::ostringstream to convert numbers to strings.
Don't use free static functions in C++; use unnamed namespaces instead.
#include<sstream>
#include<string>
namespace {
void f()
{
int value = 42;
std::ostringstream ss;
if( ss << value ) {
std::string s = ss.str();
} else {
// failure
}
}
}
For a solution in the flavour of the existing code (although I'd prefer the existing built int to string conversion):
template<class T>
static std::string Num2Str(const T& value)
{
std::string s;
int temp = static_cast<int>(value);
if (!temp)
{
s = "0";
return s;
}
while(temp != 0)
{
s.insert(0,1,(char('0' + temp % 10)));
temp /= 10;
}
return s;
}
Need to add support for negative values, range checking, etc.
My favorite is the recursive version (mostly in C) for flipping the digits to be in the correct order.
void u2str(string& s, unsigned value){
unsigned d = value % 10;
value /= 10;
if (value > 0 )
u2str(s,value);
s.push_back('0'+d);
}
For 0, you get "0", but in all other cases you don't get leading zeros. As shown it assumes string is more efficient at appending than inserting. However, if inserting is, then you don't need the recursive trick (eg Keith's answer).
You could also use boost::lexical_cast (see http://www.boost.org/doc/libs/1_46_1/libs/conversion/lexical_cast.htm)
For example:
void log_message(const std::string &);
void log_errno(int yoko)
{
log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
}