Why bitwise OR and AND logic is not working as expected? - c++

I have the below sample code. I was always under the impression that doing Bitwise OR on enum values, will allow me to check the result (using Bitwise AND) to see which enum values are included in the result and which are not.
For example, if I do result = mouse | headphone, then I can check agaist result & mouse == mouse as condition to know if mouse is included in result or not. But it seem that whatever I & result with, say X, I always end up with X. Why?
In the below code, I thought that the if should fail since straw was not included in options, but it does not..
#include <iostream>
#include <iomanip>
using namespace std;
enum Stock
{
milk,
choclate,
tv,
cable,
mouse,
fan,
headphone,
cup,
straw,
pen,
candy,
glasses,
book,
plug
};
int main()
{
Stock options = static_cast<Stock>( static_cast<int>(mouse) | static_cast<int>(headphone)
| static_cast<int>(cup) | static_cast<int>(pen) );
if ((static_cast<int>(loptions)) & (static_cast<int>(straw)) == static_cast<int>(straw))
{
cout << "bring straw!" << endl;
}
system("PAUSE");
return 0;
}
Edit:
Even when I add unique-bit set for the enum values, it does not work. For the below code, it ignores both if() statements when I am expecting it to display "bring cup" instead:
enum Stock
{
milk = 1,
choclate = 2,
tv = 4,
cable = 8,
mouse = 16,
fan = 32,
headphone = 64,
cup = 128,
straw = 256,
pen = 512,
candy = 1024,
glasses = 2048,
book = 4096,
plug = 8192
};
int main()
{
Stock options = static_cast<Stock>(static_cast<int>(mouse) | static_cast<int>(headphone)
| static_cast<int>(cup) | static_cast<int>(pen));
if ((static_cast<int>(options)) & (static_cast<int>(straw)) == static_cast<int>(straw))
{
cout << "bring straw!" << endl;
}
if ((static_cast<int>(options)) & (static_cast<int>(cup)) == static_cast<int>(cup))
{
cout << "bring cup!" << endl;
}
system("PAUSE");
return 0;
}

To use enums as bitsets (or flags) you need to make sure the binary representation for each enum value contains exactly one bit set to 1. In other words, each enum value needs to be a power of two. Example :
enum Stock
{
milk = 1, // 0b0001
choclate = 2, // 0b0010
tv = 4, // 0b0100
cable = 8 // 0b1000
// etc.
};
Otherwise, bit-wise logical operators won't be able to differentiate between certain values and certain combinations of other values. In the original code chocolate, tv and cable have the values 1, 2 and 3 respectively. In binary, that is 01, 10 and 11. ORing chocolate and tv produces 11 (0b01 | 0b10 == 0b11) which is the same value as cable. The combination of the chocolate and tv is not distinguishable from the cable flag.
But c++ provides std::bitset. This class allows you to easily manipulate a bit set in a way similar to an array of bits. You can then just use your original enum and use each enum value as the index of a bit.

Related

C++ How do I add an integer into a variable from a array using a another array

I know, the question is really complicated. Believe me, I am too. But I think a better programmer than me should know the solution. I have the following:
int cash[5] = {90000, 50000, 50000, 20000, 0};
int bankaccounts[3];
int dicenumberforeachplayer[3] = {6, 3, 9}; //Every indice is a player,
so dicenumberforeachplayer[0] is player one and so on
I have to add the highest cashnumber to the player, with the highest dicenumber, then the second player the second highest cash and so on. but I really don't know how. I am really confused, bc I am working on a project all day and I've come really far (i've written maybe 3000 lines of code) but I really hate to stop and confuse me with this problem for hours. Pls help me :((
I think, that I have to sort the player or sth like this and then I could use a for-loop for inserting the cash in every acc but I am really tired and I can't think right now XD
Modern C++ approach. There are no Magic numbers. Every thing is governed by the size of its respective array.
#include <algorithm>
#include <iostream>
int main()
{
int cash[5] = {90000, 50000, 50000, 20000, 0};
int bankaccounts[3] = {}; // added initializer to zero accounts
int dicenumberforeachplayer[3] = {6, 3, 9};
// iterate until we run out of prizes or players, whichever comes first
for (size_t cashcounter = 0;
cashcounter < std::min(std::size(dicenumberforeachplayer),
std::size(cash));
cashcounter++)
{
// find location in array of highest-rolling player
auto location = std::max_element(std::begin(dicenumberforeachplayer),
std::end(dicenumberforeachplayer));
// transform location into array index
auto index = std::distance(std::begin(dicenumberforeachplayer),
location);
//increase money in bank account for this player
bankaccounts[index] += cash[cashcounter];
// give winner impossibly low dice roll so they don't win again next time.
// Assumption: rolls cannot be negative. If they can, -1 might not be small enough
dicenumberforeachplayer[index] = -1;
}
// for display and test, print all accounts
for (const auto & val : bankaccounts)
{
std::cout << val << std::endl;
}
}
Use max_element to find the maximum and set the element to -1 then you can use the same max_element to get the next maximum element
int *max_player = max_element(dicenumberforeachplayer, dicenumberforeachplayer + 3);
int *max_money = max_element(cash, cash + 5);
bankaccount[(max_player - dicenumberforeachplayer)] += *max_money;
*max_player = *max_money = -1;

Using bitwise or operator in switch case

I have enum,
enum ENUM_MSG_TEXT_CHANGE {COLOR=0,SIZE,UNDERLINE};
void Func(int nChange)
{
bool bColor=false, bSize=false;
switch(nChange)
{
case COLOR:bColor=true;break;
case SIZE:bSize=true;break;
case COLOR|SIZE:bSize=true; bColor=true;break;
}
}
case SIZE: and case COLOR|SIZE: both gives value 1, so I am getting the error C2196: case value '1' already used. How to differentiate these two cases in switch case?
Thanks
If you want to make a bitmask, every element of your enum has to correspond to a number that is a power of 2, so it has exactly 1 bit set. If you number them otherwise, it won't work. So, the first element should be 1, then 2, then 4, then 8, then 16, and so on, so you won't get overlaps when orring them. Also, you should just test every bit individually instead of using a switch:
if (nChange & COLOR) {
bColor = true;
}
if (nChange & SIZE) {
bSize = true;
}
These two labels
case SIZE:bSize=true;break;
case COLOR|SIZE:bSize=true; bColor=true;break;
evaluates to 1 because SIZE is defined as having the value 1 and the bit-wise operator | used in the label COLOR|SIZE also yields 1.
Usually such enumerations are declared as bitmask types like
enum ENUM_MSG_TEXT_CHANGE { COLOR = 1 << 0, SIZE = 1 << 1, UNDERLINE = 1 << 2 };
In this case this label
case COLOR|SIZE:bSize=true; bColor=true;break;
will be equal to 3.
When using the binary OR (operator|) you need to assign values to the individual bits (or combinations of bits). Since COLOR has the value 0 it can't be extracted from a bitfield like you try to do.
Also, for the three enums you have, there are 8 possible combinations. To use a switch, you'd need 8 case labels.
Consider this as an alternative:
#include <iostream>
enum ENUM_MSG_TEXT_CHANGE : unsigned {
COLOR = 1U << 0U, // 0b001
SIZE = 1U << 1U, // 0b010
UNDERLINE = 1U << 2U // 0b100
};
void Func(unsigned nChange) {
// extract the set bits
bool bColor = nChange & COLOR;
bool bSize = nChange & SIZE;
bool bUnderline = nChange & UNDERLINE;
// print out what was extracted
std::cout << bUnderline << bSize << bColor << '\n';
}
int main() {
// test all combinations
for(unsigned change = 0; change <= (COLOR | SIZE | UNDERLINE); ++change) {
Func(change);
}
}
Output:
000
001
010
011
100
101
110
111

Why is my parallel array displaying random values?

I am supposed to use a parallel array to show how much a cup of coffee is based on what add-in is added. The original cup of coffee is 2 dollars. I am mostly confused with how to output the correct results. Currently, it will output saying "Order total is2". What am I missing?
// JumpinJava.cpp - This program looks up and prints the names and prices of coffee orders.
// Input: Interactive
// Output: Name and price of coffee orders or error message if add-in is not found
#include <iostream>
#include <string>
using namespace std;
int main()
{
// Declare variables.
string addIn; // Add-in ordered
const int NUM_ITEMS = 5; // Named constant
// Initialized array of add-ins
string addIns[] = {"Cream", "Cinnamon", "Chocolate", "Amaretto", "Whiskey"};
// Initialized array of add-in prices
double addInPrices[] = {.89, .25, .59, 1.50, 1.75};
bool foundIt = false; // Flag variable
int x; // Loop control variable
double orderTotal = 2.00; // All orders start with a 2.00 charge
// Get user input
cout << "Enter coffee add-in or XXX to quit: ";
cin >> addIn;
// Write the rest of the program here.
for(int i = 0; i < NUM_ITEMS; i++){
if (addIns[i] == (addIn))
foundIt = true;
if (foundIt)
{
x = orderTotal + addInPrices[i];
cout << "Order Total is" << x << endl;
}
else cout <<"Sorry, we do not carry that."<< endl;
}
return 0;
} // End of main()
In this line:
x = orderTotal + addInPrices[i];
you are setting x (an int value) to something like 2.00 + 0.25, right? Your compiler is likely warning you about a possible loss of precision here. An integer value can only contain whole numbers: 1, 2, 3, etc. If you try to set it to a floating point number like 2.25, it will be truncated (the decimal points chopped off) leaving only the integer part. So the result of x = 2.25 will be the value 2 in x, which is consistent with your output.
In your assignment template, your instructor has written this comment next to the declaration of x:
int x; // Loop control variable
It seems clear to me that the intent was for x to be what you put in the for loop, i.e. the variable controlling how many loops happen and when it ends. You are choosing to create a new variable i instead. This would also explain why x is not initialized to anything - the initialization would happen in the for-loop if you did it the intended way.
Try this: Instead of using x to store the new price, simply add the add-in price to orderTotal, so that it's always up-to-date and has the correct value. This way you do not need to use x for this at all, and can use it in the for-loop instead. You would then be printing orderTotal instead of x in your output.

Boost `interval_map` - how to customize aggregating on touch

The Boost ICL interval_set can join right-open intervals, which touch each other, during adding them to the set. For example, intervals [0,4) and [4,8) will be joined to become an interval [0,8).
This is more complicated for the interval_map - intervals, which touch each other and have different associated values, won't be joined:
#include <iostream>
#include <utility>
#include <boost/icl/interval_map.hpp>
namespace icl = boost::icl;
using IMap = icl::interval_map<int, int>;
int main()
{
IMap m;
m += std::make_pair(IMap::interval_type::right_open(0, 4), 1);
m += std::make_pair(IMap::interval_type::right_open(4, 8), 2);
std::cout << m << std::endl;
}
Output of this test program is below:
{([0,4)->1)([4,8)->2)}
I know how to customize the process of aggregating on overlap, however I need to customize another case - aggregating on touch. For example, if intervals touch each other and value of the left interval is equal to the value of the right interval minus 1, then intervals must be joined, and the resulting interval must have a value of the left interval. So, the program above should print:
{([0,8)->1)}
Is it possible to do that with currently available Boost ICL?
I can do what I want using weird manipulations with the interval_map, but I think it'd be cumbersome and non-efficient. I'd prefer to be pointed in right direction to use currently available ICL customizations, functors etc.
This is more complicated for the interval_map - intervals, which touch each other and have different associated values, won't be joined:
There's no difference, really.
I know how to customize the process of aggregating on overlap, however I need to customize another case - aggregating on touch.
You seem to imply that
m += std::make_pair(IMap::interval_type::right_open(4, 8), 2);
will insert [4, 8) -> 2.
That's simply not the case. It's a codomain combination operation, and the results depend on prior state of the map.
Of course, you can write it:
m.set({Ival::right_open(4, 8), 2});
If you need to, you can query the preceding slot, so your operation might look like:
// returns true if joined with preceding slot
bool fill_slot(IMap& m, int from, int till, int value) {
bool joined = false;
auto slot = Ival::right_open(from, till);
if (within(slot, m)) {
// There is overlap, I don't know how you want to handle this.
// You can add some logic here.
} else {
auto preceding = m(from - 1);
if (preceding && value == preceding + 1) {
joined = true;
value = preceding;
}
}
m.set({slot, value});
return joined;
}
Now you can write test cases like:
int main() {
{
IMap m;
fill_slot(m, 0, 4, 1);
fill_slot(m, 4, 8, 2);
std::cout << m << std::endl;
}
{
IMap m;
fill_slot(m, 0, 4, 1);
fill_slot(m, 4, 8, 3);
std::cout << m << std::endl;
}
{
IMap m;
fill_slot(m, 0, 4, 1);
fill_slot(m, 5, 8, 2);
std::cout << m << std::endl;
}
}
And they print Live On Coliru
{([0,8)->1)}
{([0,4)->1)([4,8)->3)}
{([0,4)->1)([5,8)->2)}

C++: Issues with manipulating a PPM file

I'm working on a program that can perform various effects and manipulations on a PPM file. However for testing reasons, it uses cin rather than an input file. It is supposed to be able to perform multiple effects at once, but I am having trouble even getting one right. I'll run a removeBlue() on a line that will work, then try again with different values and it will remove red or green instead. That sort of thing. There's a lot of code, so I'll try to include only what is necessary.
#include <vector>
#include <stdlib.h>
#include <cstdlib>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
class SimpleImageEffect
{
public:
virtual void processImage(vector<Point> &points) = 0;
};
class RemoveRed : public SimpleImageEffect
{
public:
virtual void processImage(vector<Point> &points)
{
for (Point& p : points)
{
p.setRed(0);
}
}
};
//Just an example of one of the effect classes.
//The code in them is correct, so I won't include the others unless needed.
vector<Point> parse_line(string line)
{
istringstream scanner{line};
vector<Point> result{};
int red = -1;
int green = -1;
int blue = -1;
int counter = 0;
while(scanner.good())
{
if (counter == 0)
{
counter++;
scanner >> red;
}
else if (counter == 1)
{
counter++;
scanner >> green;
}
else if (counter == 2)
{
scanner >> blue;
Point p{ red, green, blue };
result.push_back(p);
counter = 0;
}
}
return result;
}
void readFromCin()
{
string line = "";
vector<string> lines_in_file{};
int i, effect_choice;
SimpleImageEffect *effect = nullptr;
getline(cin, line);
while (line.length() > 0)
{
lines_in_file.push_back(line);
getline(cin, line);
}
for (int i = 0; i < lines_in_file.size(); i++)
{
if (lines_in_file[i] != "P3")
{
effect_choice = strToInt(lines_in_file[i]);
}
else if (lines_in_file[i] == "P3")
{
cout << lines_in_file[i] << endl;
cout << lines_in_file[i+1] << endl;
cout << lines_in_file[i+2] << endl;
}
vector<Point> points = parse_line(lines_in_file[i]);
if (effect_choice == 1) effect = new RemoveRed;
if (effect_choice == 2) effect = new RemoveGreen;
if (effect_choice == 3) effect = new RemoveBlue;
if (effect_choice == 4) effect = new NegateRed;
if (effect_choice == 5) effect = new NegateGreen;
if (effect_choice == 6) effect = new NegateBlue;
if (effect_choice == 7) effect = new AddNoise;
if (effect_choice == 8) effect = new HighContrast;
if (effect_choice == 9) effect = new ConvertToGrayscale;
effect->processImage(points);
for (auto p : points)
{
cout << p;
cout << endl;
}
}
}
int main(int argc, char** argv)
{
string menu_choice;
getline(cin, menu_choice);
if (menu_choice == "1")
{
readFromFile();
}
else
{
readFromCin();
}
return 0;
}
So for example, running it with an input of
2
1
P3
1 1
255
50 50 50
will return
P3
1 1
255
0 50 50
but if I run it with
2
3
P3
1 2
255
50 50 50
1 2 3
it returns
P3
1 2
255
0 50 50
0 2 3
I have absolutely no idea what's causing the issue, so any help at all would be greatly appreciated. Thanks.
Your algorithm logic structure smells a lot, this is what I see:
read all non empty lines into lines_in_file (looks good to me)
for EVERY line (problematic, requires additional logic in inner loop):
if not "P3", try to parse [EVERY] line as integer and set effect_choice (it's not clear from your code, what happens on lines where several integers are provided, but judging from your problem description the first integer is successfully parsed by strToInt function)
if "P3", the current line and next two are copied to output
[EVERY] line is parsed as vector of triplets of numbers
effect is set by new effect for actual value of effect_choice (for EVERY line, also you don't delete the effect at end, so you are leaking memory in per-line counts. Also your current effects look like they may be implemented as static functions of "process" function type, so you don't need to allocate each of them, just store the particular memory address of requested function. And you call it processImage, while you are processing only line, not whole image.
effect is run for current line triplets
the line triplets are outputted
loop to next line (!)
So for example for input:
2
3
P3
1 2
255
50 50 50
1 2 3
I believe (can't run it, as you didn't provide lot of code) this happens:
lines are read, and per particular line this happens:
line "2": effect_choice = 2, effect = RemoveGreen, zero triplets parsed into points, RemoveGreen::processImage() run over empty vector, empty vector printed (ie nothing).
line "3": effect_choice = 3, effect = RemoveBlue, zero triplets parsed into points, RemoveBlue::processImage() run over empty vector, empty vector printed.
line "P3": Lines: {"P3", "1 2", "255"} are printed, zero triplets parsed into points, RemoveGreen::processImage() run over empty vector, empty vector printed.
line "1 2": effect_choice = 1, effect = RemoveRed, zero triplets parsed into points, RemoveRed::processImage() run over empty vector, empty vector printed.
line "255": effect_choice = 255, zero triplets parsed into points, RemoveRed::processImage() run over empty vector, empty vector printed.
line "50 50 50": effect_choice = 50, one triplet {50, 50, 50} parsed into points, RemoveRed::processImage() run over it, modified triplet outputs {0, 50, 50}.
line "1 2 3": effect_choice = 1, effect = RemoveRed, one triplet {1, 2, 3} parsed into points, RemoveRed::processImage() run over it, modified triplet outputs {0, 2, 3}.
All of this should be clearly visible in debugger, while stepping over the code, so you probably are not debugging it, which gets downvoting the question from me, and you will pay in tremendous pain over time, as debugging without debugger is lot more difficult.
Also writing code without thinking about algorithm and code architecture makes the need of debugging lot more likely, so you wasted even more time here, by starting by writing the code.
You should have first design some algorithm and code architecture (what data are processed, how, when new memory is needed, how it will be freed, where the code need to loop, where it need to skip over, or run only once, etc).
Write only overview of how it will work into single-line comments, then split too generic comments into simpler steps until they can be implemented by few lines of C++ code, and move/modify them around until you feel the wanted algorithm will be implemented with minimal "cruft" added (most of the comments does, what is really requested, like "set red in point to zero", and any processing/preparations/moving/etc is minimized only to cases where you can't avoid it by smarter design). (for example in your current code you can read through the header of the file without looping, and start looping only after the pixel data pours in)
Then write the code, start probably with some empty function definition so you can already "run" it in debugger and verify the emptiness works, then implement the comment (or small group of them) which you feel is clear enough to be implemented and can be tested easily (no big dependency on yet-to-implement parts). Debug + test new code. If it works, try to clean up the source to remove anything not really needed, work-in-progress variable names, etc... Then verify it works in final version.
And do it again for another comment (group of), until the implementation is done.
Using unit-testing makes the write-short-code, test+debug, clean-up-source rounds even easier, especially in cases like this, where I/O are pure data, so it's easy to feed specialized test input data into test, and verify the expected output data were produced.