if statements based on user input - c++

I am trying to use different if statements based on user input. However it only seems to use the final set. any help would be great thanks.
char type[20];
double weight;
double feed;
cout<< "Enter horse type: ";
cin>>type;
cout << "Enter the horse weight in whole pounds: ";
cin>>weight;
cout<<"Horse type: "<<type<<endl;
cout<<"Horse weight: "<<weight<<endl;
This is my if statements.
{
if (type=="Light");
if (weight >= 840 && weight <=1200)
feed = (3.0);
else if (weight< 840)
feed = (3.3);
else if (weight > 1200)
feed = (2.5);
}
{
if (type=="Large");
if (weight >= 1100 && weight <=1300)
feed=(3.0);
else if (weight < 1100)
feed=(3.3);
else if (weight > 1300)
feed= (2.5);
}
{
if (type=="Draft");
if (weight >= 1500&& weight <=2200)
feed = (3.0);
else if (weight< 1500)
feed = (3.3);
else if (weight >2200)
feed= (2.5);
}
cout<<"Feed Amount "<<feed<<" pounds"<<endl;
Thanks again for any help

You can't compare C-style strings (character arrays) using ==. That compares the addresses of the arrays, not their contents.
Use std::string instead. Replace the first line with
std::string type;
You also need to fix the if statements:
if (type == "Whatever") // no ;
{
// do stuff
}

Where you have:
{
if (type=="Light");
should be:
if ( type == "Light" )
{
and the same for Draft and Large. What you are actually doing is taking no action regardless of the if, and always executing the following code.
Also ( as noted by Mike Seymour ) change char type[20]; to std::string type;. If you really must stick to char, then you will also need to change your comparison.
If your compiler supports C++14 then:
if ( type == "Light"s )
Otherwise:
if ( type == std::string("Light") )
For any of these cases you need #include <string> at the top of your file.

Related

Compare strings using ==

Code, as shown below, can be complied.
Problem: It always says "Invalid Employee id" even when I enter the correct employee id.
Please tell me why and how to do this correctly.
#include <iostream>
#include <iomanip>
using namespace std;
char select, js;
char empid[4];
double bSalary, bonus, tot=0.0;
int main()
{
do
{
cout<<"Employee id: ";
cin>>empid;
if(empid=="M001" || empid=="A004" || empid == "M002") //these are employee ids
{
cout<<"Job Status: ";
cin>>js;
if(js=='P' || js=='C')
{
cout<<"Basic Salary: ";
cin>>bSalary;
if(bSalary>75000 && js=='P')
{
bonus = bSalary*(20.0/100.0);
tot = tot + bonus + bSalary;
}
else if(bSalary>75000 && js=='C')
{
bonus = bSalary*(15.0/100.0);
tot = tot + bonus + bSalary;
}
else
tot = tot+bonus+bSalary;
}
else
cout<<"Invalid Job Status"<<endl;
}
else
cout<<"Invalid Employee no"<<endl;
cout<<"Do you want to continue: ";
cin>>select;
cout<<endl;
}while(select=='y'||select=='Y');
cout<<"Total cost: "<<setprecision(2)<<setiosflags(ios::fixed)<<tot<<endl;
return 0;
}
Note: It is going to the else clause all the time.
It's this:
char empid[4];
This is too small as there's no room for a NUL terminator after the id. You could just change it to 5, but then if someone deliberately or accidentally typed a longer string your program may crash (it's called a buffer overrun, and in some situations can allow whoever provides input to hack the account running the program).
Further, == doesn't work for character arrays: you have to use e.g.:
if (strcmp(empid, "M001") == 0 || strcmp(empid, "A004") == 0 || ...
You would be much better off using a std::string, which will grow to accommodate the actual input (including a NUL terminator though that's not counted in a string's .size()), and works intuitively with ==.
Separately, your...
tot = tot+bonus+bSalary;
...is broken, as bonus may be uninitialised you mustn't read from it in an expression. You can simply remove bonus from the addition above, if it's meant to be 0 for the relevant employees.
You can't compare C strings with == or !=. As you can see that empid here is just a pointer so == will compare the base addresses of those strings not the strings themselves.
You need to use strcmp and include
#include <cstring>
.
.
.
if(strcmp(empid,"M001")==0 || ...)
Empid is not a string. C++ doesn't have a built-in == overload to compare char arrays.
You can make your own == operator. But don't bother. Declare empid as a string and watch magic happen.
string empid;
Changing the size of the char array to take care of NULL char will not work here.
char empid[5]
"==" operator do not work properly with char arrays. please change the condition to below:
if (0 == (strcmp(empid, "M001")) || (0 == (strcmp(empid, "A004"))) || (0 ==
(strcmp(empid, "M002"))))
EDIT:people above has already answered your question. My answer is redundant now.

C++ const char if-statement

So I'm trying to get this program that will say good or bad depending on your answer and I didn't want to have a really long if and else if statement with a bunch of strings so I put a bunch of possible answers in two chars and I want it to answer depending on what you say. The program only replies to the good answers saying good even if you enter in one of the bad answers.
const char* good[5] = {
"good", "great", "amazing", "amazing!", "fantastic"
};
const char* bad[5] = {
"bad", "bad pal", "bad eugene", "not good", "not good pal"
};
string input01 = "";
int main() {
cout << "Hello" << endl;
system("PAUSE");
system("CLS");
cout << "How are you doing today?" << endl;
cin >> input01;
transform(input01.begin(), input01.end(), input01.begin(), ::tolower);
if (input01 == good[0 > 5] || good[0 < 5]){
system("CLS");
cout << "good" << endl;
system("pause");
}
else if (input01 == bad[0 > 5] || bad[0 < 5]){
system("CLS");
cout << "bad" << endl;
system("pause");
}
}
This: if (input01 == good[0 > 5] || good[0 < 5]) probably doesn't do what you expect (because I can't imagine wanting what it really does).
0 > 5 is evaluated as a test of whether 0 is greater than 5. Since it's obviously not, that produces false. Since it's being used in a context where an integer is needed, that's converted to 0, so that part of the expression becomes if (input01 == good[0].
Likewise, 0 < 5 tests whether 0 is less than 5 (which it obviously is) so the result is true, which converts to 1, so that part of the expression is good[1]. Since that in turn is being used as a Boolean expression, it's treated as equivalent to good[1] != 0.
So what you have overall is if (input01 == good[0] || good[1] != 0).
That seems close enough to useless that I'm pretty sure it's not what you wanted. In particular, good[1] is a pointer. A pointer will compare equal to 0 if and only if it's a null pointer. Since it's initialized to point at something, it's not a null pointer, so that part of the expression will always evaluated as true.
of course, your other if statement is about equally useless.
If you want to check whether input01 is equal to any of the items in good, you might (for one example) use std::find:
if (std::find(std::begin(good), std::end(good), input01) == std::end(good))
// input01 was not present in `good`.
To make that work correctly, you'll want to use std::strings though:
std::vector<std::string> good{"good", "great", "amazing", "amazing!", "fantastic"};
It's kind of pointless for only 5 items, but if you lists of good and bad words are likely to get really large, you'd probably be better off sorting them, then using std::binary_search, or else using std::unordered_set instead.
Try:
if ((strcmp(input.c_str(), good[0]) == 0) ||
(strcmp(input.c_str(), good[1]) == 0) ||
...
(strcmp(input.c_str(), good[4]) == 0))
Or better switch the keywords to strings,
const string good[5] = {
"good", "great", "amazing", "amazing!", "fantastic"
};
and then
if ((input == good[0]) ||
(input == good[1]) ||
...
(input == good[4]))
Or even better, pack the keywords into a set
const set<string> good{"good", "great", "amazing", "amazing!", "fantastic"};
and then
if (good.find(input) != good.end())
Why don't you just check if the input01 is in your array. You should be able to use the find() function to do this. Something like
if(std::find(std::begin(good), std::end(good), input01) != std::end(good))){do something}
You may not need the std:: references

Assigning enum value to integer crashes program [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have created an enum with these values:
enum Car_Manufacturer
{
AUDI = 1,
CHRYSLER = 2,
FORD = 3,
HONDA = 4,
LEXUS = 5,
NISSAN = 6,
MERCEDES = 7,
PORSCHE = 8,
VOLVO = 9
};
I have the user enter a character which corresponds to the model of car they want to view. I need the character the user entered to become a integer which corresponds to the values in the enum so that I can easily search through an array to find a car of the correct make. The function I created looks like this:
int set_car_make_ch( char input )
{
int manufacturer = 0;
if( input == 'A' )
{
manufacturer = AUDI;
}
else if( input == 'C' )
{
manufacturer = CHRYSLER;
}
else if( input == 'F' )
{
manufacturer = (int)FORD;
}
else if( input == 'H' )
{
manufacturer = HONDA;
}
else if( input == 'L' )
{
manufacturer = LEXUS;
}
else if( input == 'M' )
{
manufacturer = MERCEDES;
}
else if( input == 'N' )
{
manufacturer = NISSAN;
}
else if( input == 'P' )
{
manufacturer = PORSCHE;
}
else if( input == 'V' )
{
manufacturer = VOLVO;
}
else
{
cout<<"Invalid Car Manufacturer, please edit the input file."<<endl;
exit( EXIT_FAILURE );
}
return manufacturer;
}
The program freezes and crashes when an enum value attempts to be assigned to an integer. I am using the G++ compiler. Any help with this issue would be greatly appreciated.
Please, use a lookup table or a switch statement rather than the if-else-if ladder.
Lookup Table
struct Car_Text_Enum_Entry
{
const char * name;
Car_Manufacturer enum_value;
};
const static Car_Text_Enum_Entry enum_conversion[] =
{
{"AUDI", AUDI},
{"BMW", BMW},
{"DODGE", DODGE},
//...
};
const unsigned int number_of_conversions =
sizeof(enum_conversion) / sizeof(enum_conversion[0]);
Car_Manufacturer Car_Text_To_Enum(char car_mfg_letter)
{
Car_Manufacturer manufacturer = 0;
for (unsigned int i = 0; i < number_of_conversions; ++i)
{
if (enum_conversion[i].name[0] == car_mfg_letter)
{
manufacturer = enum_conversion[i].enum_value;
break;
}
}
return manufacturer;
}
The lookup table is a lot tighter code and to added or remove manufacturers only requires changing the table, not the code.
Switch Statement
The switch statement approach will work for letters, but not for strings. For strings, use a lookup table.
Car_Manufacturer Car_Mfg_Letter_To_Enum(char car_mfg_letter)
{
Car_Manufacturer manufacturer;
switch (car_mfg_letter)
{
case 'A' : manufacturer = AUDI; break;
case 'B' : manufacturer = BMW; break;
case 'D' : manufacturer = DODGE; break;
case 'H' : manufacturer = HONDA; break;
// ...
}
return manufacturer;
}
The switch statement approach is still more readable and easier to maintain than the if-else-if ladder. However, it will not work with strings (a.k.a. multiple letters).
Maps
However, if you have learned about std::map, you can use it also:
typedef std::map<char, Car_Manufacturer> Car_Mfg_Container;
Car_Mfg_Container car_mfg_association;
// Initialization:
car_mfg_association['A'] = AUDI;
car_mfg_association['B'] = BMW;
//...
Car_Manufacturer Car_Mfg_Letter_To_Enum(char car_mfg_letter)
{
return car_mfg_association[car_mfg_letter];
}
Unlike the static, constant, lookup table, the std::map must be initialized during runtime.
So, please, don't use if-else-if ladders for things that can be looked up in a table.
Also, with enumerations, you only need to assign a value to the first item.
You have not explained what (if any...) error message you are getting or how you are using this function, but it's generally not a good idea to rely implicit or C style casting from enum to int when you have better tools available in C++:
Try this: Declare your variable as type Car_Manufacturer:
Car_Manufacturer manufacturer{};
If for some reason you must use int try this:
manufacturer = static_cast < int >(FORD);
If there is something else wrong, instead of just crashing because you're doing an explicit, C style cast, you should get a reasonable error message from static_cast.
The best way to avoid such issues entirely is to use C11's Scoped enumerations, which are strongly typed and cannot simply be cast as integers.
(As an aside, as #ThomasMatthews has explained, use switch, not if/else if when you have an enum, char or int.)

input string validation without external libraries for c++

I need to validate one input string from a user. Eventually it will need to break down into two coordinates. ie a4 c3. And once they are coordinates they need to be broken out into 4 separate ints. a=0 b=1, etc. They must also follow the following stipulations:
If an end-of-input signal is reached the program quits.
Otherwise, all non-alphanumeric characters are discarded from the input.
If what remains is the single letter 'Q'
Then the program quits.
If what remains consists of 4 characters, with one letter and one digit among the first two characters and one letter and one digit among the last two characters, and if each letter-digit pair is in the legal range for our grid
Then input is acceptable.
I have completely over-thought and ruined my function. Please let me know where I can make some corrections.
I am mainly having trouble going from one string, to four chars if and only if the data is valid. Everything else I can handle.
Here is what I have so far.
void Grid::playerMove()
{
string rawMove;
string pair1 = " ";
string pair2 = " ";
bool goodInput = false;
char maxChar = 'a';
char chary1, chary2;
int x11,x22,y11,y22;
for (int i =0; i<size; i++)
{
maxChar++;
}
while(!goodInput)
{
cout<<"What two dots would you like to connect? (Q to quit) ";
cin>>rawMove;
rawMove = reduceWords(rawMove);
if (rawMove == "Q")
{
cout<<"end game";
goodInput = false;
}
else if (rawMove.size() == 4)
{
for(int j=0;j<2;j++)
{
if (pair1[j] >='a' && pair1[j] <=maxChar)
{
chary1 = pair1[j];
}
else if(pair1[j] >=0 && pairl[j]<=size+1)
{
x1 = pair1[j];
}
}
for(int k=0;k<2;k++)
{
if (pair2[k] >='a' && pair2[k] <=maxChar)
{
chary2 = pair2[k];
}
else if(pair2[k] >=0 && pair2[k]<=size+1)
{
x2 = pair2[k];
}
}
}
if(char1 != NULL && char2 != NULL && x1 !=NULL && x2 != NULL)
{
for (int m = 0; m <= size m++)
{
if (char1 == m;)
{
x1 = m;
}
}
for (int n = 0; n <= size n++)
{
if (char2 == n)
{
x2 = n;
}
}
}
}
The end goal would be to have x1, x2, y1, and y2 with their respective values.
Keep in mind I am not allowed to have any external libraries.
It's not clear what exactly you want to achieve, but here are some pointers to get you started:
The while loop will never end because you're setting goodInput to false on quit which lets the loop continue.
The code probably does not even compile? You are missing a curly closing brace..
You are initializing pair1 and pair2 to empty strings but never change them again, so they will never contain any real information about your moves
maybe what you really want is to split up rawMove into the pair1 and pair2 substrings first?
Since this is a homework - and you're supposed to learn from those (right?) - I'm not going to give you the complete answer, but rather something like a recipe:
Use std::istream::getline(char*, std::streamsize s) to read a whole line from std::cin. Make sure you allocate a buffer large enough to hold the expected input (including the terminating null character) plus some more for invalid characters. After the call, check the failbit (input was too long) and the eofbit (hit the end-of-input) of the std::cin stream and handle those cases. Construct a std::string from the buffer if there was no error or EOF has not been reached.
Write a character-classification function (e.g. call it isAlNum(char c)) that returns true if the char argument is alpha-numeric, and false otherwise.
Combine std::string::erase(), std::remove_if(), std::not1(), std::ptr_fun() and your function isAlNum() to sanitise the input string.
Write a function that validates and parses the coordinates from the sanitised input string and call it with the sanitised input string.
Wrap the whole thing in an appropriate while() loop.
This should get you started in the right direction. Of course, if you're allowed to use C++11 features and you know how to write good regular expressions, by all means, use the <regex> header instead of doing the parsing manually.

Function and selection issue in C++

I revised this post. I am new to programming and do not know if the functions are set up correctly or even how to allow the selection of packages. Below is my objective.
I have a class assignment to write a C++ program that will calculate a customers monthly internet bill. It would input a customer name, which package the customer purchased, and how many hours were used.
The Requirements are:
Input validation: to be sure the user only selects package A B or C. Display and error message if the wrong package is entered.
Calculation:
PackA for 9.95 a month with 10 hours of acess. 2 bucks per additional hour.
PackB for 14.95 a month with 20 hours of acess. 1 bucks per additional hour.
PackC for 19.95 a month with unlimited acess.
I then have to create the output as a bill.
The code I wrote so far is:
/*
James Hayek
CIS 165
Passaic County Community College
Program 04
*/
#include <iostream>
#include <iomanip>
using namespace std;
double calcBill(double packageChoosen, double hours, double basePack, char name); // This is the function prototype for calcBill
void dispBill(char packageChoosen, double hours, double basePack, char name, char bill); // This is the function prototype for dispBill
int main()
{
char packageChoosen;
double bill;
char name;
double hours;
double basePack;
cout << "Welcome To Your Personal Bill Caclculator!\n\n";
cout << "Please enter your name: \n";
cin >> name;
cout << "Please choose your package by entering A, B, or C: \n";
cin >> packageChoosen;
bill = calcBill(name, packageChoosen, hours, basePack); // call function calcBill
dispBill(name, packageChoosen, hours, basePack, bill); // call function dispBill
return 0;
} // end main
double calcBill(char packageChoosen, double hours, double basePack, char name) //This is the function for calcBill
{
if (packageChoosen == 'A' || packageChoosen == 'a' && hours <= 10)
{
bill = 9.95;
}
else if (packageChoosen == 'A' || packageChoosen == 'a' && hours > 10)
{
bill = 9.95 + (2 * hours);
}
else
{
cout << "Please choose an apropriate package";
}
return bill;
} // end main
void dispBill(double packA, double packB, double packC, char name, char bill) //This is the function for dispBill
{
cout << bill;
return;
} // end dispBill
I am not really sure where to begin, any advice would be greatly appreciated.
The && operator binds more tightly than the || operator in C++. Rather than
packageChoosen == 'A' || packageChoosen == 'a' && hours > 10
as a boolean expression, you most likely want
(packageChoosen == 'A' || packageChoosen == 'a') && hours > 10
The top expression looks either for a "package A" or a "package a with hours > 10". The bottom expression looks for a "package A or package a" and "hours > 10".
As Platinum Azure mentions in his answer, it is also possible to convert whatever character you have to lowercase, then do a single comparison against a lowercase letter.
#include <cctype>
// ...
std::tolower(packageChoosen) == 'a' && hours > 10
This makes your code a little more readable, and you don't have to worry about operator precedence.
Zeke's answer is solid; however, you could #include <cctype> and use std::tolower(packageChoosen == 'a' as part of your condition.
You need to think more in terms of OO. You're stuck in C world. I would suggest that Package would be a great candidate for an object.
As to the errors, you haven't said what they are so I can't really help you there. I'm too lazy to run a compile myself just to get what you should have already posted.
create an abstract class PackageAbstract
create a class called user
create a class called bill
create concretes class PackageA, packageB, packageC
in the user class add method :
addPackage(packageAbstract* packageAbs){}
add the member m_vector package choosen
for billing create a bill with user fedded with package...
each month you loop through users to create bills
for a real app you'll need a class custormers wich is feeded by users
...
Nice solution:
Create an abstract class Package, like so:
class Package{
public:
virtual double calculate(double hours) = 0;
}
Then subclass concrete package types from it, like so:
class PackageA : public Package{
public:
virtual double calculate(double hours){
return hours < 10 ? 9.92 : 9.95 + hours*2;
}
}
Then, you can use something like this code to calculate the bill:
Package* bill_calculators[3];
bill_calculators[0] = new PackageA();
bill_calculators[1] = new PackageB();
bill_calculators[2] = new PackageC();
char packageChosen;
cin >> packageChosen;
packageChosen = toupper(packageChosen) - 'A';
if(packageChosen >= 0 && packageChosen < 3) cout << bill_calculators[packageChosen]->calculate(hours);
else cout << "Invalid package\n";
I haven't actually compiled or tested the code, but you get the idea: create an abstract interface, implement algorithms for particular packages in subclasses, then create instances and decide which instance to use for calculation based on user input.
Btw, you'll have to #include to use the toupper() function
Cheers.