The boost units library provides useful compile time "units of measure" type checking. It also provides stream io operations to serialize units. However, I am struggling with the string parsing bit.
For example, the following lines:
boost::units::quantity<boost::units::si::force> f(2.0 * boost::units::si::newton);
std::cout << "Force = " << f << std::endl;
produce the output:
Force = 2.0 N
Can someone point me to an example that parses these standard serialization back to boost units?
// f.parse_string("2.0 N"); or using stream operators??
Thanks!
It's not directly supported by the library.
There's an example that could give some inspiration: http://www.boost.org/doc/libs/1_56_0/doc/html/boost_units/Examples.html#boost_units.Examples.RuntimeUnits
This example shows how to implement an interface that allow different
units at runtime while still maintaining type safety for internal
calculations.
namespace {
using namespace boost::units;
using imperial::foot_base_unit;
std::map<std::string, quantity<si::length> > known_units;
}
quantity<si::length> calculate(const quantity<si::length>& t)
{
return(boost::units::hypot(t, 2.0 * si::meters));
}
int main()
{
known_units["meter"] = 1.0 * si::meters;
known_units["centimeter"] = .01 * si::meters;
known_units["foot"] =
conversion_factor(foot_base_unit::unit_type(), si::meter) * si::meter;
std::string output_type("meter");
std::string input;
while((std::cout << "> ") && (std::cin >> input))
{
if(!input.empty() && input[0] == '#')
{
std::getline(std::cin, input);
}
else if(input == "exit")
{
break;
}
else if(input == "help")
{
std::cout << "type \"exit\" to exit\n"
"type \"return 'unit'\" to set the return units\n"
"type \"'number' 'unit'\" to do a simple calculation"
<< std::endl;
}
else if(input == "return")
{
if(std::cin >> input)
{
if(known_units.find(input) != known_units.end())
{
output_type = input;
std::cout << "Done." << std::endl;
}
else
{
std::cout << "Unknown unit \"" << input << "\""
<< std::endl;
}
}
else
{
break;
}
}
else
{
try
{
double value = boost::lexical_cast<double>(input);
if(std::cin >> input)
{
if(known_units.find(input) != known_units.end())
{
std::cout << static_cast<double>(
calculate(value * known_units[input]) /
known_units[output_type])
<< ' ' << output_type << std::endl;
}
else
{
std::cout << "Unknown unit \"" << input << "\""
<< std::endl;
}
}
else
{
break;
}
}
catch(...)
{
std::cout << "Input error" << std::endl;
}
}
}
}
Related
I'm making a terminal-like program (to calculate currency) with custom commands as input but I have a problem.
Every time I implement a new command, I have to add a new else if statement. This wouldn't be a problem but for a terminal-like program there can be a lot of commands.
Here is my code:
#include <iostream>
#include <string>
#include <Windows.h>
#include <math.h>
float user_balance = 0.0f;
float eur_in_czk = 24.0f; //ammount of czk in single euro
std::string currency = "czk";
bool czk_to_eur_enabled = true;
bool eur_to_czk_enabled = false;
//------------------START method definition---------------------------------------------------------
void czk_to_eur()
{
if (czk_to_eur_enabled) //to prevent using twice in a row
{
user_balance /= eur_in_czk;
user_balance = floorf(user_balance * 100) / 100; //limit to two decimal numbers
currency = "eur";
czk_to_eur_enabled = false;
eur_to_czk_enabled = true;
}
else
{
std::cout << "Your savings are already converted to " << currency << "!" << std::endl;
}
}
void eur_to_czk()
{
if (eur_to_czk_enabled) //to prevent using twice in a row
{
user_balance *= eur_in_czk;
user_balance = floorf(user_balance * 100) / 100; //limit to two decimal numbers
currency = "czk";
eur_to_czk_enabled = false;
czk_to_eur_enabled = true;
}
else
{
std::cout << "Your savings are already converted to " << currency << "!" << std::endl;
}
}
void set_balance(float new_balance)
{
user_balance = new_balance;
}
void add_balance(float new_balance)
{
user_balance += new_balance;
}
//------------------END method definition-----------------------------------------------------------
int main()
{
bool main_loop = true; //main loop enabler
float input_money;
std::string user_command = "";
std::cout << "This is currency converter v1.0 (czk to eur and back)\n\n\n" << std::endl;
while (main_loop) //main loop for currency converter
{
std::cout << "Input: ";
std::cin >> user_command;
std::cout << std::endl;
if ((user_command == "setbal") || (user_command == "SETBAL"))
{
std::cout << "Your balance is " << user_balance << " " << currency << ".\n";
std::cout << "Please enter desired value (" << currency << "): ";
std::cin >> input_money;
set_balance(input_money);
std::cout << "\n" << std::endl;
}
else if ((user_command == "addbal") || (user_command == "ADDBAL"))
{
std::cout << "Your balance is " << user_balance << " " << currency << ".\n";
std::cout << "Please enter desired value (" << currency << "): ";
std::cin >> input_money;
add_balance(input_money);
std::cout << "\n" << std::endl;
}
else if ((user_command == "balance") || (user_command == "BALANCE"))
{
std::cout << "Your balance is " << user_balance << " " << currency << "." << std::endl;
}
else if ((user_command == "curstat") || (user_command == "CURSTAT"))
{
std::cout << "Currency status is " << eur_in_czk << " czk in 1 eur." << std::endl;
}
else if ((user_command == "toeur") || (user_command == "TOEUR"))
{
czk_to_eur();
}
else if ((user_command == "toczk") || (user_command == "TOCZK"))
{
eur_to_czk();
}
else if ((user_command == "cheuv") || (user_command == "CHEUV"))
{
std::cout << "Change eur value (" << eur_in_czk << "): ";
std::cin >> eur_in_czk;
std::cout << std::endl;
}
else if ((user_command == "help") || (user_command == "HELP"))
{
std::cout << "SETBAL Sets balance.\n"
<< "ADDBAL Adds balance.\n"
<< "BALANCE Shows current balance.\n"
<< "CURSTAT Shows currency status.\n"
<< "TOEUR Converts czk to eur.\n"
<< "TOCZK Converts eur to czk.\n"
<< "CHEUV Changes eur currency value.\n"
<< "CLS Cleans terminal history.\n"
<< "EXIT Exits program.\n" << std::endl;
}
else if ((user_command == "cls") || (user_command == "CLS"))
{
system("CLS"); //funtion from Windows.h library
}
else if ((user_command == "exit") || (user_command == "EXIT"))
{
main_loop = false;
}
else
{
std::cout << "'" << user_command << "'"
<< "is not recognized as an internal or external command!\n";
std::cout << "Type 'HELP' to see available commands.\n" << std::endl;
}
}
return 0;
}
The bottom part of the code in while cycle is where the problem is.
Everything works fine but I would like to know, if there is any other way. And switch to my knowledge does not support string values as condition/dependency. (also I'm currently not using any custom classes and/or custom header files because this is just experiment.)
Is there any other way to do it?
Normally I would suggest using a std::map with a string as the key and a function as the value so that you could search the map for a command and then invoke the function associated with it. However, since that's already been mentioned in the comments I figured I'd get all fancy and provide a totally wack solution you probably shouldn't use.
This wack solution allows you to use string literals in a switch/case statement. This is possible by taking advantage of a feature of modern C++ called user defined literals that allow you to produce objects of user-defined type by defining a user-defined suffix much in the same way you append U to a integer literal to specify an unsigned value.
The first thing we'll do is define a user defined literal that produces a hash value that is calculated at compile time. Since this generates a hash value from the string it is possible to encounter collisions but that's dependant on the quality of the hash algorithm used. For our example we're going to use something simple. This following snippet defines a string literal with the suffix _C that generates our hash.
constexpr uint32_t djb2Hash(const char* str, int index = 0)
{
return !str[index]
? 0x1505
: (djb2Hash(str, index + 1) * 0x21) ^ str[index];
}
// Create a literal type for short-hand case strings
constexpr uint32_t operator"" _C(const char str[], size_t /*size*/)
{
return djb2Hash(str);
}
Now every time the compiler sees a string literal in the format of "Hello World"_C it will produce a hash value and use that in place of the string.
Now we'll apply this to your existing code. First we'll separate the code that takes the user command from cin and make the given command all lower case.
std::string get_command()
{
std::cout << "Input: ";
std::string user_command;
std::cin >> user_command;
std::cout << std::endl;
std::transform(
user_command.begin(),
user_command.end(),
user_command.begin(),
[](char ch) { return static_cast<char>(std::tolower(ch)); });
return user_command;
}
There now that we can get an all lowercase command from the user we need to process that so we'll take your original set of if/else statements and turn them into a simple switch/case statement instead. Now since we can't actually use string literals in the switch/case statement we'll have to fudge a little bit and generate the hash value of the users command for the switch part of the code. We'll also take all of your commands and add the _C suffix to them so that the compiler automatically generates our hash values for us.
int main()
{
bool main_loop = true; //main loop enabler
std::cout << "This is currency converter v1.0 (czk to eur and back)\n\n\n" << std::endl;
while (main_loop) //main loop for currency converter
{
const auto user_command(get_command());
switch(djb2Hash(user_command.c_str()))
{
case "setbal"_C:
std::cout << "Set balance command\n";
break;
case "addbal"_C:
std::cout << "Add balance command\n";
break;
case "balance"_C:
std::cout << "Get balance command\n";
break;
case "curstat"_C:
std::cout << "Get current status command\n";
break;
case "help"_C:
std::cout << "Get help command\n";
break;
case "exit"_C:
main_loop = false;
break;
default:
std::cout
<< "'" << user_command << "'"
<< "is not recognized as an internal or external command!\n"
<< "Type 'HELP' to see available commands.\n" << std::endl;
}
}
}
And there you have it. A totally wack solution! Now keep in mind that we're not really using strings in the switch/case statement, we're just hiding most of the details of generating hash values which are then used.
I learned about the try/catch block awhile ago. From what I understand, this is used to handle "Real" errors like runtime errors. Instead, I used it to handle incorrect sign in attempts here, even though it's not really needed:
void signIn(std::vector<User>& userVect, int& index, bool& isLoggedIn)
{
std::string userNameSearchKey;
std::string pass;
int passwordRetry = 0;
int userRetry = 0;
bool keepSearching = true;
bool userFound = false;
while (!userFound && userRetry < 3 && userNameSearchKey != "b")
{
try
{
if (userRetry >= 3)
{
throw 2;
}
std::cout << "\nEnter a username, or 'b' to go back" << std::endl;
std::cout << "Username: ";
std::cin >> userNameSearchKey;
if (userNameSearchKey == "b")
{
break;
}
std::cout << "Password: ";
std::cin >> pass;
for (int i = 0; i < userVect.size(); i++)
{
if (userNameSearchKey == userVect[i].getUserName())
{
userFound = true;
if (pass == userVect[i].getPassword())
{
std::cout << "\nWelcome " << userVect[i].getUserName(); // Welcomes the user
index = i; // When this function ends
isLoggedIn = true;
}
else
{
throw 1;
}
}
}
if (!userFound && userNameSearchKey != "b")
{
throw 1;
}
}
catch(int x)
{
if (x == 1)
{
std::cout << "\nError " << x << ": Incorrect username or password." << std::endl;
userRetry++;
if (userRetry >= 3)
{
std::cout << "Too many incorrect attempts. Going back to the main menu." << std::endl;
}
}
}
}
}
Please keep in mind that the code is just an illustration of the point I'm making: The function works fine and it does its job, but I could also get the same effect without try/catch and throw. Is it more idiomatic to reserve exception handling for actual errors?
This question already has answers here:
C++ printing boolean, what is displayed?
(2 answers)
Closed 3 years ago.
Sorry if this is obvious but I'm very new to c++, thanks in advance
#include <iostream>
bool conduct_it_support(bool on_off_attempt) {
std::cout << "Have you tried turning it off and on again? (true / false)\n";
std::cin >> on_off_attempt;
if(on_off_attempt == false) {
return false;
}
else {
return true;
}
return on_off_attempt;
}
int main() {
bool attempt;
conduct_it_support(attempt); {
std::cout << "so it was " << attempt << "?\n";
}
}
I excpect this to be either: "so it was true/false?"
Sorry if this is obvious but I'm very new to c++, thanks in advance
By default the stream class(s) will serialize bool as 0 or 1. They will also read 0 or 1 when de-serializing.
To make it print the string(s) true or false you need to use a stream modifier std::boolalpha to change the behavior of the stream to print (or read) the text version of boolean values.
See below:
#include <iostream>
#include <iomanip>
int main ()
{
bool a = false;
bool b = true;
std::cout << std::boolalpha << a << " : " << b << '\n';
std::cout << std::noboolalpha << a << " : " << b << '\n';
// If you want to read a bool as 0 or 1
bool check;
if (std::cin >> std::noboolalpha >> check) {
std::cout << "Read Worked: Got: " << check << "\n";
}
else
{
std::cout << "Read Failed\n";
}
// PS. If the above read failed.
// The next read will also fail as the stream is in a bad
// state. So make the above test work before using this code.
// If you want to read a bool as true or false
bool check;
if (std::cin >> std::boolalpha >> check) {
std::cout << "Read Worked: Got: " << check << "\n";
}
else
{
std::cout << "Read Failed\n";
}
}
This code is working fine:
bool conduct_it_support(bool init) {
bool on_off_attempt=init;
char selectVal[10] = "000000000";
std::cout << "Have you tried turning it off and on again? (true / false)\n";
std::cin >> selectVal;
if(selectVal == "false") {
on_off_attempt=false;
}
else {
on_off_attempt=true;
}
return on_off_attempt;
}
int main()
{
bool attempt;
attempt = conduct_it_support(attempt); {
std::cout << "so it was " << attempt << "?\n";
}
Try this code here.
I have a board game that has spaces (has numeral values 1,2,3, etc.) starting from 1 and 16 pieces of pawns; four for each player.
I want to show the result of my board game at some point. I tried the method below but that will make my code extremely long.
i have 16 pieces and 100 spaces that i have to repeat that code with 100 space that would take forever. the code below is just for one space (the first space)
Any idea how to show my result in a short way? Thanks in advance!
Here is my old-fashioned way:
//space 1
if (bpiece1->value == 1)
{
cout << " bpiece1";
}
else if (bpiece2->value == 1)
{
cout << " bpiece2";
}
else if (bpiece3->value == 1)
{
cout << " bpiece3";
}
else if (bpiece4->value == 1)
{
cout << " bpiece4";
}
else if (gpiece1->value == 1)
{
cout << " gpiece1";
}
else if (gpiece2->value == 1)
{
cout << " gpiece2";
}
else if (gpiece3->value == 1)
{
cout << " gpiece3";
}
else if (gpiece4->value == 1)
{
cout << " gpiece4";
}
else if (ypiece1->value == 1)
{
cout << " ypiece1";
}
else if (ypiece2->value == 1)
{
cout << " ypiece2";
}
else if (ypiece3->value == 1)
{
cout << " ypiece3";
}
else if (y4->value == 1)
{
cout << " y4";
}
else if (rpiece1->value == 1)
{
cout << " rpiece1";
}
else if (rpiece2->value == 1)
{
cout << " rpiece2";
}
else if (rpiece3->value == 1)
{
cout << " rpiece3";
}
else if (rpiece4->value == 1)
{
cout << " rpiece4";
}
else
{
cout << " 01";
}
C++ is an object-oriented language. Therefore, we start by creating a class that stores your board and implements all functions on it. Like
//Board.h
#include <array>
using std::array;
enum class Figure { None, Pawn };
class Board {
private:
array<array<Figure, 8>, 8> fields; //8x8 if it was a chess board
public:
void print() const;
};
//Board.cpp
#include "Board.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
inline string to_string(const Figure figure){
switch(figure){
case Figure::None:
return " ";
case Figure::Pawn:
return "p";
}
//throw error here
return "";
}
void Board::print() const {
for(size_t i = 0; i < fields.size(); i++){
for(size_t j = 0; j < fields[i].size(); j++){
cout << to_string(fields[i][j]);
}
cout << endl;
}
cout << endl;
}
If this is new to you, you should really read the basic tutorials first and make sure that you understand each line I wrote in the end.
Important here is: Representation, represenation, representation. Don't think in "1 is a pawn", think in "a pawn is a pawn". Everything that has a function which you can think of should probably be a class, a structure or an enum.
Ok, after failing to read a polynomial, I'm trying first a basic approach to this.
So i have class polinom with function read and print:
#ifndef _polinom_h
#define _polinom_h
#include <iostream>
#include <list>
#include <cstdlib>
#include <conio.h>
using namespace std;
class polinom
{
class term
{
public:
double coef;
int pow;
term(){
coef = 0;
pow = 0;
}
};
list<term> poly;
list<term>::iterator i;
public:
void read(int id)
{
term t;
double coef = 1;
int pow = 0;
int nr_term = 1;
cout << "P" << id << ":\n";
while (coef != 0) {
cout << "Term" << nr_term << ": ";
cout << "coef = ";
cin >> coef;
if (coef == 0) break;
cout << " grade = ";
cin >> pow;
t.coef = coef;
t.pow = pow;
if (t.coef != 0) poly.push_back(t);
nr_term++;
}
}
void print(char var)
{
for (i=poly.begin() ; i != poly.end(); i++ ) { //going through the entire list to retrieve the terms and print them
if (poly.size() < 2) {
if (i->pow == 0) //if the last term's power is 0 we print only it's coefficient
cout << i->coef;
else if (i->pow == 1) {
if (i->coef == 1)
cout << var;
else if (i->coef == -1)
cout << "-" << var;
else
cout << i->coef << var;
}
else
cout << i->coef << var << "^" << i->pow; //otherwise we print both
}
else {
if (i == poly.end()) { // if we reached the last term
if (i->pow == 0) //if the last term's power is 0 we print only it's coefficient
cout << i->coef;
else if (i->pow == 1)
cout << i->coef << var;
else
cout << i->coef << var << "^" << i->pow; //otherwise we print both
}
else {
if (i->coef > 0) {
if (i->pow == 1)//if the coef value is positive
cout << i->coef << var << " + "; //we also add the '+' sign
else
cout << cout << i->coef << var << "^" << i->pow << " + ";
}
else {
if (i->pow == 1)//if the coef value is positive
cout << i->coef << var << " + "; //we also add the '+' sign
else
cout << cout << i->coef << var << "^" << i->pow << " + ";
}
}
}
}
}
};
#endif
Well, it works when reading only one term but when reading more the printed coefficients are some random values and also after the last term it print '+' or '-' when it shouldn't.
So any idea what's wrong?
Thanks!
FINAL UPDATE
Ok, i made it work perfectly by modifying Bill's code so thanks a lot Bill and everyone else who commented or answered!
Here's the final print function:
void print(char var)
{
list<term>::iterator endCheckIter;
for (i=poly.begin() ; i != poly.end(); i++ )
{
//going through the entire list to retrieve the terms and print them
endCheckIter = i;
++endCheckIter;
if (i->pow == 0)
cout << i->coef;
else if (i->pow == 1)
cout << i->coef << var;
else
cout << i->coef << var << "^" << i->pow;
if (endCheckIter != poly.end()) {
if (endCheckIter->coef > 0)
cout << " + ";
else {
cout << " - ";
endCheckIter->coef *= -1;
}
}
}
}
if (i == poly.end()) { // if we reached the last term
This comment shows your error. For any given collection of items, items.end() returns the entry after the last item.
For instance, say I have a 5-item std::vector:
[0] [1] [2] [3] [4]
Then begin() points to:
[0] [1] [2] [3] [4]
/\
And end() points to:
[0] [1] [2] [3] [4] []
/\
Your for loop, it looks like:
for (i=poly.begin() ; i != poly.end(); i++ )
Note that comparing i to poly.end() happens before iter is used. As soon as i == poly.end(), you're done.
Your code inside of if (i == poly.end()) { will never be executed because this can never be true.
You can test for the end using the following:
// get access to the advance function
#include <iterator>
....
std::list<term>::iterator endCheckIter = i;
std::advance(endCheckIter, 1);
if (endCheckIter == poly.end())
{
...
}
But a simpler way might be:
std::list<term>::iterator endCheckIter = i;
++endCheckIter;
if (endCheckIter == poly.end())
{
...
}
Edit:
I'm not sure why you're getting garbage. Add in your missing braces and handle the non-end case, and everything works here:
void print(char var)
{
list<term>::iterator endCheckIter;
for (i=poly.begin() ; i != poly.end(); i++ )
{ // <- MISSING BRACE
//going through the entire list to retrieve the terms and print them
endCheckIter = i;
++endCheckIter;
cout << i->coef << var << "^" << i->pow; // <- MISSING OUTPUT
if (endCheckIter != poly.end()) {
if (i->coef > 0)
cout << " + ";
else
cout << " - ";
}
} // <- MISSING BRACE
}
Okay, now that Vlad has decided how he's going to do it, here's how I'd do it:
#ifndef _polinom_h
#define _polinom_h
#include <iostream>
#include <list>
#include <cstdlib>
#include <cmath>
#include "infix_iterator.h"
using namespace std;
char var;
class polinom {
class term {
double coef;
int power;
ostream &write(ostream &os) const {
// At least to me, the logic is easier to follow if we
// handle one piece at a time.
// It may be longer, but I think it's easier to understand.
// First, if the coefficient is negative, subtract the term instead of adding it.
if (coef < 0)
// backspace over the "+ " and print '- ' in its place.
os << "\b\b- ";
// Then print the absolute value of the coefficient (if needed).
if (fabs(coef) != 1)
os << fabs(coef);
// Then print the var (if needed)
if (power != 0)
os << var;
// then print the power (if needed)
if (abs(power) > 1)
os << "^" << power;
// And we're done.
return os;
}
// support inserting a term into a stream.
friend std::ostream &operator<<(std::ostream &os, term const &t) {
return t.write(os);
}
public:
term(double c=0.0, int p=0) : coef(c), power(p) {}
bool read(std::ostream &os, std::istream &is, int num) {
// This is only slightly modified from the originally posted question
os << "\nTerm " << num << ": coef = ";
is >> coef;
if (coef == 0.0)
return false;
if (coef != 0.0) {
os << " grade = ";
is >> power;
}
return true;
}
bool operator<(term const &other) const {
// order by descending powers.
return other.power < power;
}
};
list<term> poly;
public:
void read(int id) {
term t;
int nr_term = 1;
std::cout << "P: " << id;
// Read and save individual terms:
while (t.read(std::cout, std::cin, nr_term++))
poly.push_back(t);
}
void write(char var) {
// sort the polynomial so the highest powers come first.
poly.sort();
// save the variable name for later use.
::var = var;
// Print out all the terms:
std::copy(poly.begin(), poly.end(), infix_ostream_iterator<term>(std::cout, " + "));
}
};
#endif
Using this is pretty trivial:
#include "polynom.h"
int main() {
polinom p;
p.read(1);
p.write('x');
return 0;
}
void print(char var)
{
for (list<term>::const_iterator i = poly.begin(), e = poly.end(); i != e; ++i) {
if (i != poly.begin() || i->coef < 0) {
cout << (i->coef > 0 ? '+' : '-');
}
if (abs(i->coef) != 1) {
cout << abs(i->coef);
}
if (i->pow == 0) {
if (abs(i->coef) == 1) {
cout << 1;
}
} else {
cout << var;
if (i->pow != 1) {
cout << '^' << i->pow;
}
}
}
}