"if" and "else if" commands are not working in c++ - c++

I am in the process of making a chat bot and i am just experimenting at this point. but my "if" commands are not working and when i enter "moodToday" it just skips right to the else command.
(capitalization of "moodToday" is not the error)
any and all help would be appreciated
#include <fstream>
#include <cmath>
using namespace std;
int main() {
char name[50], moodToday[50];
cout << "A few things you should know at this time..." << endl << "1. I can't process last names." << endl << "2. I can't process acronyms." << endl;
system("pause");
cout << endl << endl << "What is your name?" << endl;
cin >> name;
cout << "Hello " << name << "." << endl << "How are you today?" << endl;
cin >> moodToday;
//can't figure this out...
if ((moodToday == "sad") || (moodToday == "bad") || (moodToday == "horrible")) {
cout << "That's not good." << endl << "Why are you feeling " << moodToday << "today?" << endl;
}
else if (moodToday == "good") {
cout << "Great!" << endl;
}
else {
cout << "I'm sorry, I don't undrestand that feeling." << endl;
}
system("pause");
return 0;
}

To compare character arrays that contain strings you should use standard C functions like std::strcmp declared in header <cstring>. For example
#include <cstring>
//...
if ( std::strcmp( moodToday, "sad" ) == 0 ) std::cout << "They are equal << std::endl;
Otherwise in statements like this
if ((moodToday == "sad") ) /*...*/
there are compared two pointers: the pointer to the first character of the array moodToday and the pointer to the first character of the string literal "sad" because arrays used in expressions with rare exceptions are converted to pointers to their first characters.
Take into account that the usage of the operator >> with character arrays is unsafe
cin >> moodToday;
Use instead member function getline like this
cin.getline( moodToday, sizeof( moodToday ) );
Or instead of the character arrays you could use standard class std::string.
Consider a ppossibility to convert all letters of the entered string to the case of the string literal before comparing them. You can do this using standard C functions tolower and toupper declared in header <cctype>.

If you're doing C++, then you should be using std::string and not the old C-style buffers.
#include <string>
int main() {
std::string name, moodToday;
}
C++ strings are significantly better than C strings since they don't have buffer overflow problems and are easily compared with ==.
Also, as a tip, try to avoid using namespace std; since that can cause namespace conflicts. As annoying as it can be to type std:: all the time it does make it clear where that class or template originated from and who's responsible for it code-wise. That way your own classes and templates are obvious.

Use strcmp instead of == operators.
If you defined moodToday as a string object, then == would work.

Similar to problems in java with comparing object addresses what you are doing is comparing memory addresses. Thus you want to use strcmp(str1, "literal")==0 to see if they are equal.
#import <cstring>
if(strcmp(str1, "literal") == 0) dothis();

Related

How to limit user input in C++ for strings & characters?

I'm trying to create a small restaurant program in which I'll be practicing everything I learned in C++ so far. However I jumped into a small issue. At the beginning of the program, I prompt the user whether they want to enter the program, or leave it by choosing Y or N. If the input is anything other than that the program will tell the user is invalid.
The issue is lets say the user input one invalid character a.
The invalid output will be displayed normally and everything seems perfect.
But if the user inputs two characters, or more, the invalid output case will be printed as many as the characters input by the user. Sample below:
Output image
#include <iostream>
int main()
{
char ContinueAnswer;
std::string Employee {"Lara"};
std::cout << "\n\t\t\t---------------------------------------"
<< "\n\t\t\t| |"
<< "\n\t\t\t| Welcome to OP |"
<< "\n\t\t\t|Home to the best fast food in Orlando|"
<< "\n\t\t\t| |"
<< "\n\t\t\t--------------------------------------|" << std::endl;
do
{
std::cout << "\n\t\t\t Would you like to enter? (Y/N)"
<< "\n\t\t\t "; std::cin >> ContinueAnswer;
if(ContinueAnswer == 'y' || ContinueAnswer == 'Y')
{
system("cls");
std::cout << "\n\t\t\t My name is " << Employee << "."
<< "\n\t\t\tI will assist you as we go through the menu." << std::endl;
}
else if(ContinueAnswer == 'n' || ContinueAnswer == 'N')
{
std::cout << "\t\t\t\tGoodbye and come again!" << std::endl;
return 0;
}
else
std::cout << "\n\t\t\t\t Invalid Response" << std::endl;
}
while(ContinueAnswer != 'y' && ContinueAnswer != 'Y')
Thank you for taking time to read and for anyone who answers :)
You could simply make the user input a string:
std::string ContinueAnswer;
and compare like this:
if(ContinueAnswer == "y" || ContinueAnswer == "Y")
which will handle multi-character inputs.
If you want to handle spaces in the input as well, change the:
std::cin >> ContinueAnswer;
to:
std::getline(std::cin, ContinueAnswer);
Before addressing your question I need to point out that you should always verify that the input was successful before doing anything with it. Processing variables which were not set due to the inout failing is a rather common source of errors. For example:
if (std::cin >> ContinueAnswer) {
// do something with successfully read data
}
else {
// deal with the input failing, e.g., bail out
}
I assume you consider everything on the same line to be invalid if nine of the expected characters was read. You could read a line into an std::string. However, that could be abused to provide an extremely long line of input which would eventually crash your program. Also, reading data into a std::string just to throw it away seems ill-advised. I’d recommend ignoring all characters up to and including a newline which could be done using (you need to include <limits> for this approach):
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), ‘\n’);
The first argument is a special value indicating that there may be an arbitrary amount of character before the newline. In practice you could probably use a value like 1000 and it would be fine but it can be gamed. Of course, in a real application a dedicated limit may be used to prevent an adversary to keep the program busy for long. I tend to assume my programs are under attack to make sure I deal with unusual cases.
A quick refactor produces this:
#include <iostream>
#include <cstring>
#include <stdio.h>
int main()
{
char ContinueAnswer[256];
std::string Employee {"Lara"};
std::cout << "\n\t\t\t---------------------------------------"
<< "\n\t\t\t| |"
<< "\n\t\t\t| Welcome to OP |"
<< "\n\t\t\t|Home to the best fast food in Orlando|"
<< "\n\t\t\t| |"
<< "\n\t\t\t--------------------------------------|" << std::endl;
do
{
std::cout << "\n\t\t\t Would you like to enter? (Y/N)"
<< "\n\t\t\t "; std::cin.getline(ContinueAnswer,sizeof(ContinueAnswer));
if(strcmp(ContinueAnswer, "Y") == 0 || strcmp(ContinueAnswer, "y") == 0)
{
system("cls");
std::cout << "\n\t\t\t My name is " << Employee << "."
<< "\n\t\t\tI will assist you as we go through the menu." << std::endl;
}
else if(strcmp(ContinueAnswer, "N") == 0 || strcmp(ContinueAnswer, "n") == 0)
{
std::cout << "\t\t\t\tGoodbye and come again!" << std::endl;
return 0;
}
else
std::cout << "\n\t\t\t\t Invalid Response" << std::endl;
}
while(true);
}
The cin.getline will get all characters until a delimiter. Then, you can check for equivalence using strcmp and reject anything other than what you want. Lastly, it seems like you are wanting this to be in an infinite loop, so don't worry about checking the input at the end and just loop back.

If Function and cin

Im very new to c++ and trying to write a simple game to learn some of the basic mechanics and i'm having trouble with my code,
How do I define the function WantToPlay so that when a player enters "yes" it replies fantastic, and "no" replies boooo?
My current code gives the error that WantToPlay must be of bool type, but i'm not sure how to use a boolean function to rectify it?
Thanks!
using std::cout;
using std::cin;
using std::endl;
using std::string;
string leader;
string WantToPlay;
int main()
{
std::cout << "Dungeon Master: Welcome to my dungeon, traveller! What is your name?" << std::endl;
cin >> leader;
cout << "Dungeon Master: Well hello, " << leader << " I have a little quest for you if you're interested?" << endl;
cout << "(Please enter ""yes"" or ""no"")" << endl;
cin >> WantToPlay;
if (WantToPlay = "yes")
cout << "Fantastic!" << endl;
else if (WantToPlay = "no")
cout << "boooo" << endl;
return 0;
}
you need use the o̶p̶e̶r̶a̶t̶o̶r̶ c̶o̶m̶p̶a̶r̶a̶t̶o̶r̶ equality operator. "=="
What you are doing is assigning, not comparing.
(WantToPlay = "Yes") means assigning the string value "Yes" to the string variable WantToPlay
Since you are comparing the value of the variable with "Yes", you should use "==", because (WantToPlay == "Yes") means the string value "Yes" is the same as the value in string variable WantToPlay.
Did you know the difference between "=" and "==" ? Check your if statement, and correct it.
Tip: you can't use assignment in if condition.

Verify if string contains at least one letter

Hello Im trying to check if string contains at least one letter, but at this stage is not working. If I type 13 it would continue without giving me error,
It doesn't matter if contains number I just want at least one letter for example: Patrick1 thats okay.
This the code I'm trying :
void setName(string b) {
cout << "Please enter your name:" << endl;
getline(cin, b);
for (int i =0; i<b.size(); i++) {
if ((b[i] >= 'A' && b[i] <= 'Z') ||
(b[i] >= 'a' && b[i] <= 'z')) {
cout << "Error" << endl;
cout << "Please enter your name:" << endl;
getline(cin, b);
}
any suggestions thanks guys !
The C++ standard library have many nice algorithmic functions, for example one called std::any_of which will return true if any element in the range passed to causes a predicate to return true.
Can be used with ::isalpha like this
if (std::any_of(std::begin(b), std::end(b), ::isalpha))
{
// There is at least one alphabetic character in the string
}
Important note: The std::any_of function was introduced in C++11. Some compilers need special flags to enable C++11. Very old compilers and standard libraries might not have the function at all.
please try to avoid repeating yourself (like you did with "getline")
If you have to, rethink your algorithm ... in your case it could be something like " repeat the entry while there's no correct name entered", which can be coded exactly that way:
this way, if you want to change the code in place A, you cannot forget to also change it in place B (and all the other places you eventually copied it to) ;-)
#include <algorithm>
#include <iostream>
#include <cctype>
void setName(std::string& b) {
bool isValidName=false; // nothing entered yet
while ( !isValidName )
{
std::cout << "Please enter your name:" << std::endl;
std::getline(std::cin, b);
if (std::any_of(std::begin(b), std::end(b), ::isalpha)) {
isValidName=true; // correct name entered
}
else {
std::cout << "Error" << std::endl;
}
}
}
int main() {
std::string name;
setName(name);
std::cout << "Hello, " << name << "!" << std::endl;
return 0;
}

C++ Expected unqualified-id

I'm am a beginner in C++. I'm using Xcode to compile my code. Right now I am going over variables and doing a brief exercise on the subject. The exercise asks that I ask for the user to input their first and last name as well their age. As a additional requirement I need to use a double floating point for age so I can multiply the age into months. Below is my code:
#include <iostream>
#include <math.h>
int main()
{
std::cout << "Please enter your first name, second name, and age (then press enter).\n";
std::string first;
std::string last;
std::double age;
std::cin >> first >> last >> age;
std::cout << "Hello, " << first << " " << last << ". Your age is " << age << " and you are " << (age * 12) << " months old.";
return 0;
}
I get an error that says that the double is an expected unqualified-id. Can someone point out what I'm doing wrong and the correct way to do this?
double does not live in the std namespace. You need
double age;
You also need to include the string header for std::string. You may get it indirectly from iostream on some implementations, but you cannot rely on that: it is a fluke.
double is a built-in type. It doesn't live in any namespace and doesn't need any qualification! Just remove the std:: in front of double:
double age;
Note, you should test whether your input was actually successful:
if (std::cin >> first >> last >> age) {
// process successful input
}
else {
std::cout << "ERROR: failed to read expected input\n";
}
First of all it is a good idea to include header <string>
#include <string>
If in C# so-called built-in types in realty are aliases for classes as for example double is an alias for System.Double and you can write
System.Double age;
or
double age;
in C++ these types indeed are built in types and use keywords as doubleto specify a type
double age;
Though i do not understand why age should be double because the number of months in year is an integer value.:)
I believe the code below is about ideal for learning how to do this kind of nearly-first C++ program.
The little technical problem with your code was just that double is keyword, not a name defined by the standard library, and hence, not in namespace std.
In addition I’ve added
inclusion of the <string> header, necessary for using std::string in a portable way,
a using namespace std; directive, very handy for small exploration programs (but do not place this in the global namespace in a header file!),
checking of whether input operations succeed (also output can fail but that’s extremely rare).
The way that I check for input operation failure, using boolean "or" (the || operator), is not yet very much used in C++, but is common in some other languages. Essentially the left hand argument of || is converted to bool, since that’s what || requires. The left hand argument is the expression result of some input operation, which in general is a reference to the cin stream, and a bool value is then produced via a defined conversion that is equivalent to writing !cin.fail() (where ! is the logical "not" operation).
E.g., getline( cin, first ) || fail( ... ) reads very nicely as “getline or else fail”, and in addition to reading nicely it’s also visually distinctive, easy to recognize as a failure check.
#include <iostream>
#include <string>
#include <stdlib.h> // exit, EXIT_FAILURE
using namespace std;
// Poor man's way to handle failure, but good enough here:
bool fail( string const& message )
{
cerr << "!" << message << endl;
exit( EXIT_FAILURE );
}
int main()
{
cout << "Please enter your first name: ";
string first;
getline( cin, first )
|| fail( "Sorry, input of your first name failed." );
cout << "Please enter your last name: ";
string last;
getline( cin, first )
|| fail( "Sorry, input of your last name failed." );
cout << "Please enter your age in years: ";
double age;
cin >> age
|| fail( "Sorry, input of your age failed." );
cout << "Hello, " << first << " " << last << "." << endl;
cout
<< "Your age is " << age << " years"
<< " and you are "<< (age*12) << " months old."
<< endl;
}

cin.get() issue with empty line

When I run the following code and insert a new line (press enter) when prompted for
the golf structure, the second call to the function doesn't request input and finishes as if I've pressed enter again.
I've read up on : cin.get() , cin.clear() , cin.ignore(...) but nothing seems to help.
I'm pretty sure that it has nothing to do with multiple .cpp files and the header but I'm putting the code as is.
I'm using Visual Studio C++ 2010 - Express.
Thanks in advance for your help!
header file : golf.h
#ifndef GOLF_H
#define GOLF_H
const int Len = 40;
struct golf{
char fullname[Len];
int handicap;
};
int setgolf(golf & g );
void showgolf(const golf & g );
#endif
golf.cpp
#include "stdafx.h"
#include "golf.h"
#include <iostream>
#include <string>
using namespace std;
int setgolf(golf & g ){
cout << "Enter a name for the golf structure:" << endl;
if (cin.get(g.fullname,Len)) {
cin.get(); // deals with the '\n' incase the user inputs a valid string
return 1;
}
else{
return 0;
}
}
void showgolf(const golf & g ){
cout << "this golf structure contains the following information:" << endl;
cout << "name: " << g.fullname << endl ;
cout << "handicap: " << g.handicap << endl ;
}
main ()
#include "stdafx.h"
#include "golf.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
golf myGolf;
// check of int setgolf(golf & g );
int answ = setgolf(myGolf); //try to input empty string
showgolf(myGolf);
cout << "the number returned :" << answ << endl ;
answ = setgolf(myGolf); // normal string
showgolf(myGolf);
cout << "the number returned :" << answ << endl ;
return 0;
}
This problem happens when you just press enter in the first prompt. The input stream is marked as eof, an error condition flag (that's why it returns 0). The input stream then stops working.
It seems that you're using a kind of old C++, pre ISO 1998, while I don't think you need that. However, if you want to stick with your approach, then do the following: after cin.getline() (no need to return anything) write: cin.clear(); cin.sync();, as follows:
void setGolf(Golf &g)
{
cout << "Enter a name for the golf structure:" << endl;
getline( cin, g.fullname ) );
cin.clear();
cin.sync();
}
Now, about modernizing your code. First of all, you can use the standard library's class string, which is able to store a string literal, even growing if needed, without giving a maximum value of chars. This is somewhat confusing, since you are including the header string, which will include that class, but you're not using it. The use of string also comes with other advantages, such as automatically correcting the potential buffer overflow which could happen in your Golf structure. So I would change your structure to be:
struct Golf{
string fullname;
int handicap;
};
Now you can use getline(), in utility, which reads a whole line and stores it in string, doing all the magic for you. So you could change your golf.cpp file, to:
#include <utility>
//...
void setGolf(Golf &g)
{
cout << "Enter a name for the golf structure:" << endl;
getline( cin, g.fullname ) );
}
You can now also change the return type to void. It is not probable to experience an error of any kind while using getline(). Anyway, take into account that you could return bool (boolean type), which is a built-in type, with literals true and false.
I am certain that you could change your main() now, to a simpler style:
int main()
{
Golf myGolf;
setGolf(myGolf);
showGolf(myGolf);
setGolf(myGolf);
showGolf(myGolf);
return 0;
}
Finally, you could consider encapsulating your information in a class, instead of a struct, but that is a whole different issue.
Hope this helps.
You can also leave char[] instead of replacing it with string(I am still learning, so if I'm wrong please correct me). I think that when
std::cin.get(char *,Size) is not able to load characters, it's turning 2 bits on 0, fail and error, this is my solution:
std::cin.get(g.fullname, Len);
if(!std::cin)
{
std::cin.clear();
std::cin.get();
std::cout << "You inserted empty line." << std::endl;
return 0;
}