Bool must be always returning NULL(if statement ignoring true or false) - c++11

I need to know why I am always returning NULL in the following context(for example no matter if I say "Yes", or "No", for any of the questions I am getting null( I assume because the question process repeats when it runs) even though I say no in main. I'm trying to get it to do this: for all invalid answers I return null, if null start over the question process, if answer was valid I return either true or false, if true continue, if false quit program.
bool question1()
{
string answer2;
cout << "Are you 18 or older and have a valid Driver's License? Yes or No: ";
getline( cin, answer2);
transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower);
cout << endl;
if( answer2 == "yes")
{
cout << "Alright! " << endl << "You are set for registration. Please fill out the registration form. ";
return true;
}
else if( answer2 == "no")
{
cout << "Do you know someone else who is 18 or older that can register? Yes or No ";
getline( cin, answer2);
transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower);
if( answer2 == "yes")
{
cout << "Good, then please continue the process in their place. Please fill out the registration form";
return true;
}
else if( answer2 == "no")
{
cout << "Please come back later when you have the appropriate personel";
return false;
}
else
{
cout << "The answer given was invalid. Please give a valid answer. " << endl << endl ;
return NULL;
}
}
else
{
cout << "The answer given was invalid. Please give a valid answer. " << endl << endl;
return NULL;
}
void registerPerson( array< string, nameSize > namesOfPeople, array< string, idSize > idlen)
{
string pName;
string dLicense;
static int i = 0;
static int b = 0;
static int c = 0;
unsigned int x = 1;
cout << endl << endl << "REGISTRATION FORM:" << endl << endl << "------------------" << endl;
cout << "Please" << endl << "enter the following: \n \n";
cout << "Name: ";
getline( cin, pName );
for ( int j = i; j<=800; ++ j )
{
namesOfPeople[j] = pName;
cout << namesOfPeople[j];
i = i + 1;
break;
}
cout << endl;
while( x = 1)
{
cout << "Driver\'s Licence Number( Must be 9 characters long, no dashesh ): ";
cin >> dLicense;
if ( dLicense.length() < 9 || dLicense.length()> 9 )
{
cout << "The entered number was invalid. Please try again";
}
else
{
for ( int a = i; c<=800; ++ a )
{
idlen[a] = dLicense;
cout << idlen[a];
c = c + 1;
break;
}
}
}
}
}
{
int main()
array< string, nameSize > names = {};
array< string, idSize > ids = {};
carShare mycarShare1;
carShare mycarShare2;
mycarShare2.welcomeMessage();
mycarShare2.question1();
if( mycarShare1.question1() == NULL)
{
mycarShare1.question1();
}
else if( mycarShare1.question1() == true)
{
mycarShare1.registerPerson(names, ids);
}
else
{
return 0;
}
system( "PAUSE" );
return 0;
}

I'd probably change it to handle invalid input within question1() itself. An easy way to start the question over again is letting question1 call itself again on invalid input until it gets a valid one like here (I put comments at all the changed places.):
bool question1()
{
string answer2;
cout << "Are you 18 or older and have a valid Driver's License? Yes or No: ";
getline( cin, answer2);
transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower);
cout << endl;
if( answer2 == "yes")
{
cout << "Alright! " << endl << "You are set for registration. Please fill out the registration form. ";
return true;
}
else if( answer2 == "no")
{
cout << "Do you know someone else who is 18 or older that can register? Yes or No ";
getline( cin, answer2);
transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower);
if( answer2 == "yes")
{
cout << "Good, then please continue the process in their place. Please fill out the registration form";
return true;
}
else if( answer2 == "no")
{
cout << "Please come back later when you have the appropriate personel";
return false;
}
else
{
cout << "The answer given was invalid. Please give a valid answer. " << endl << endl ;
return question1(); // call itself again on invalid input.
}
}
else
{
cout << "The answer given was invalid. Please give a valid answer. " << endl << endl;
return question1(); // call itself again on invalid input.
}
}
int main()
{
array< string, nameSize > names = {};
array< string, idSize > ids = {};
carShare mycarShare1;
carShare mycarShare2;
mycarShare2.welcomeMessage();
bool answer = mycarShare2.question1();
/* if( answer == NULL) we don't need this anymore if we handle errors inside question1()
{
mycarShare1.question1();
}
*/
if( answer == true) // notice the change to if instead of else if here.
{
mycarShare1.registerPerson(names, ids);
}
else
{
return 0;
}
system( "PAUSE" );
return 0;
}
Another way to do the same without recursion would be a do... while loop, here's a version of only question1() with a loop:
bool question1()
{
string answer2; // has to be declared before the loop.
do
{
cout << "Are you 18 or older and have a valid Driver's License? Yes or No: ";
getline( cin, answer2);
transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower);
cout << endl;
if( answer2 == "yes")
{
cout << "Alright! " << endl << "You are set for registration. Please fill out the registration form. ";
return true;
}
else if( answer2 == "no")
{
cout << "Do you know someone else who is 18 or older that can register? Yes or No ";
getline( cin, answer2);
transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower);
if( answer2 == "yes")
{
cout << "Good, then please continue the process in their place. Please fill out the registration form";
return true;
}
else if( answer2 == "no")
{
cout << "Please come back later when you have the appropriate personel";
return false;
}
}
}while(answer2 != "yes" && answer2 != "no"); // loop as long as the input is invalid.
}
=====================================
Edit:
As clarification to it printing multiple times, here's the culprit in your original code:
mycarShare2.question1();
if( mycarShare1.question1() == NULL)
{
mycarShare1.question1();
}
else if( mycarShare1.question1() == true)
{
mycarShare1.registerPerson(names, ids);
}
else
{
return 0;
}
mycarShare2.question1() is a function call, you were calling your function 3 times in that part. What you'd want was probably saving it in a bool variable and only test in the if/else statements after that, like this:
bool answer = mycarShare2.question1();
if( answer == NULL)
{
mycarShare1.question1();
}
else if( answer == true)
{
mycarShare1.registerPerson(names, ids);
}
else
{
return 0;
}
Note: this is just to show it the way you probably expected it to be executed in your original code and not a solution. As said bool can only be true or false and the check for NULL isn't needed at all. (See my solutions above.)

Related

C++ .txt read in issues. getline reading full file

first of all, forgive my code for being ugly. The tons of ideas I've been given to try to fix this code have jumbled it up after all the potential solutions that haven't worked. Basically, I'm coding a Hearthstone rip-off that reads in two .txt files with card information and battles them to see which player wins. The issue is that when I'm trying to save the player's name (the first line in the files), it saves the whole file instead of just the first line. When I have managed to fix that, the for loop used to save the information for the card objects (format: card name, card power, card health) does not get saved properly for some reason. Any help would be appreciated, I've been trying to fix this for two days and nothing has fully solved the problem. I'll attach the read in files first before the code.
Disclaimer: It's a lot of lines and I'm sorry about that. Also I think the problem could be that my Mac is not saving the .txt in a format that has the right line endings. I'm using XCode as my IDE. Thank you so much to whomever is willing to help!
File1:
The Innkeeper
3
Tunnel Trogg
1
3
Neptulon
7
7
Fire Elemental
6
5
File2:
Malfurion
3
Leper Gnome
2
1
Aviana
5
5
Cenarius
5
8
Main:
#include "Player.h"
using namespace std;
int main()
{
cout << "Please enter file name of the first player: " << endl;
string inFile = "";
getline(cin, inFile);
Player* p1 = new Player(inFile);
cout << "Now enter the file name of the second player: " << endl;
getline(cin, inFile);
Player* p2 = new Player(inFile);
p1->battle(*p2);
delete p1;
delete p2;
return 0;
}
Player Header:
#include "Card.h"
#include <fstream>
#ifndef Player_h
#define Player_h
using namespace std;
class Player
{
private:
string playerName;
int numCards;
Card ** cards;
int wins = 0;
public:
Player(std::string inFile);
void battle(Player p2);
Card* getCard(int counter);
~Player();
};
#endif /* Player_h */
Card Header:
#include <string>
#include <iostream>
#ifndef Card_h
#define Card_h
using namespace std;
class Card
{
public:
Card();
string getName();
int getPower();
int getHealth();
void setName(string newName);
void setPower(int newPower);
void setHealth(int newHealth);
Card* duel(Card&);
friend ostream& operator<<(ostream& o, Card& c);
friend bool operator==(Card& p1Card, Card& p2Card);
private:
string name;
int power;
int health;
};
#endif /* Card_h */
Player Source:
#include "Player.h"
using namespace std;
Player::Player(string inFile)
{
ifstream in(inFile, ios::in);\
if (!in)
{
cerr << "There was a problem opening the file. Sorry, try again!" << endl;
return;
}
getline(in, playerName);
cout << playerName << endl;
in>>numCards;
playerName = "";
numCards = 0;
cards = new Card* [numCards];
string tempName = "";
int tempPower = 0;
int tempHealth = 0;
for (int i = 0; i<numCards; i++)
{
in.ignore();
cards[i] = new Card();
getline(in, tempName);
cout << "in for loop: " << endl;
cout << tempName << ",";
cards[i]->setName(tempName);
in >> tempPower;
in.ignore();
cout << tempPower << ",";
cards[i]->setPower(tempPower);
in >> tempHealth;
cout << tempHealth << " done"<< endl;
cards[i]->setHealth(tempHealth);
}
}
void Player::battle(Player p2)
{
int draws = 0;
cout << "Let the battle begin!" << endl;
cout << numCards << endl;
if (wins > p2.wins)
{
cout << playerName << " wins over " << p2.playerName << ", " << wins << " to " << p2.wins;
if (draws == 0)
{
cout << " and no ties." << endl;
}
else
{
cout << " and " << draws << " ties." << endl;
}
}
else if (p2.wins > wins)
{
cout << p2.playerName << " wins over " << playerName << ", " << p2.wins << " to " << wins;
if (draws == 0)
{
cout << " and no ties." << endl;
}
else
{
cout << " and " << draws << " ties." << endl;
}
}
else if (p2.wins == wins)
{
cout << "It is a draw between " << playerName << " and " << p2.playerName << ", with " << wins << " for each and ";
if (draws == 0)
{
cout << "no ties." << endl;
}
else
{
cout << draws << " ties." << endl;
}
}
cout << "Here are the detailed results:" << endl;
for (int i = 0; i < numCards; i++)
{
cout << *cards[i] << " vs. " << *p2.cards[i] << " - ";
if (*cards[i] == *p2.cards[i])
{
cout << "It is a draw." << endl;
}
else if (cards[i]->duel(*p2.cards[i]) == NULL)
{
cout << "It is a draw." << endl;
}
else if (*cards[i]->duel(*p2.cards[i]) == *p2.cards[i])
{
cout << p2.cards[i]->getName() << "wins for " << p2.playerName << "." << endl;
}
else if (*cards[i]->duel(*p2.cards[i]) == *cards[i])
{
cout << cards[i]->getName() << "wins for " << playerName << "." << endl;
}
}
}
Player::~Player()
{
if (cards != NULL)
{
for (int i = 0; i < numCards; i++)
{
if (cards[i] != nullptr)
{
delete cards[i];
cards[i] = NULL;
}
};
}
}
Card Source:
#include "Card.h"
using namespace std;
Card::Card()
{
name = "";
power = 0;
health = 0;
}
string Card::getName()
{
return name;
}
int Card::getPower()
{
return power;
}
int Card::getHealth()
{
return health;
}
void Card::setName(string newName)
{
name = newName;
}
void Card::setPower(int newPower)
{
power = newPower;
}
void Card::setHealth(int newHealth)
{
health = newHealth;
}
Card* Card::duel(Card& otherCard)
{
if ((otherCard.getHealth() - this->getPower() <=0) && (getHealth() - otherCard.getPower() <= 0))
{
return NULL;
}
else if ((otherCard.getHealth() - this->getPower() >0) && (getHealth() - otherCard.getPower() >0))
{
return NULL;
}
else if (otherCard.getHealth() - this->getPower() <=0)
{
return this;
}
else if (this->getHealth() - otherCard.getPower() <=0)
{
return &otherCard;
}
return NULL;
}
ostream& operator<<(ostream& o, Card& c)
{
o << c.getName() << " (" << c.power << ", " << c.health << ") " << endl;
return o;
}
bool operator==(Card& p1Card, Card& p2Card)
{
if (p1Card.health == p2Card.health &&
p1Card.power == p2Card.power &&
p1Card.name == p2Card.name)
{
return true;
}
else
{
return false;
}
}
Your code is almost right. It can read the Player's name and the card numbers, but your codes showed below:
in>>numCards;
playerName = "";
numCards = 0;
cards = new Card* [numCards];
at first, it read the num of card and store it to numCards, it is right.
next, you clear the value of the numCards, then, you lost the num of the Card, so the codes followed it are executed with numCards == 0
You can just comment the line numCards = 0, and your code is executed right.

Functions not executing properly

So I'm trying to write a program that solves the "Dungeon Crawl" problem here: http://www.cplusplus.com/forum/articles/12974/. If you are too lazy to read the link (which is entirely understandable), the basic premise of the game is that a player moves on a 10x10 grid and tries to reach treasure while avoiding traps and moving enemies. Because everything is revealed to the player, it's not much of a real game, but I thought it'd be good coding practice. Sadly, I'm rusty on user input and never properly learned how to put an entire program together, which means I'm having serious problems with functions executing properly.
The main function is this:
int main()
{
int turn=0,enemyCount=0;
bool end=false;
srand (time(NULL));
node* world;
world = new node[100];
generateWorld(world);
drawWorld(world);
do {
playerMove(world);
enemiesMoves(world,enemyCount);
drawWorld(world);
end = endCheck(world);
turn++;
} while (end == false);
return 0;
}
I think this is fine as is, because it follows the simple process of gathering moves, updating the world, and then checking to see if an end condition has been reached. The problem is that numerous functions are not working as I would expect them to, and I can't figure out why they are not. This includes user input validation, updating the movement of the enemies, drawing the world, and checking if the game ended. I'll go in order.
This is the playerMove() function:
void playerMove(node* array){
int i,playerLocation,oldLocation;
bool valid=false;
char move;
for (i=0;i<100;i++){
if (array[i].player == true){
playerLocation = i;
oldLocation = playerLocation;
}
}
while(!valid){
if (cin >> move){
if (move=='w' || move=='s' || move=='a' || move=='d')
valid = true;
}
if (move=='w'){
playerLocation = oldLocation-10;
if (playerLocation < 0){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='s'){
playerLocation = oldLocation+10;
if (playerLocation > 99){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='a'){
playerLocation = oldLocation-1;
if (playerLocation % 10 == 9){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='d'){
playerLocation = oldLocation+1;
if (playerLocation % 10 == 0){
cout << "You can't swim." << endl;
valid = false;
}
}
}
array[oldLocation].player = false;
array[playerLocation].player = true;
}
It's supposed to gather player input, do nothing if the player enters a key that isn't WASD (they can only move in the four cardinal directions), reject an input if the player tries to move off the edge of the world, and update the player position. It does successfully do the latter, but it will not catch an invalid input, and if a move fails, it refuses to display the message it is supposed to.
This is the enemiesMoves function:
void enemiesMoves(node* array,int enemyCount){
int i,j=0,n,enemyLocations[enemyCount],oldLocations[enemyCount];
bool valid = false;
for (i=0;j<enemyCount;i++){
if (array[i].enemy==true){
enemyLocations[j] = i;
cout << enemyLocations[j] << endl;
j++;
}
}
for (j=0;j<enemyCount;j++){
oldLocations[j] = enemyLocations[j];
}
for (j=0;j<enemyCount;j++){
while (!valid){
n = rand() % 4 + 1;
if (n = 1){
enemyLocations[j] = oldLocations[j]-10;
if (enemyLocations[j] < 0)
valid = false;
}
else if (n = 2){
enemyLocations[j] = oldLocations[j]+10;
if (enemyLocations[j] > 100)
valid = false;
}
else if (n = 3){
enemyLocations[j] = oldLocations[j]-1;
if (enemyLocations[j] % 10 == 9)
valid = false;
}
else if (n = 1){
enemyLocations[j] = oldLocations[j]+1;
if (enemyLocations[j] % 10 == 0)
valid = false;
}
}
array[enemyLocations[j]].enemy = true;
array[oldLocations[j]].enemy = false;
}
}
It is supposed to move the enemies in a random direction, but reject the movement if the enemy moves off the world. Although I thought I properly copied over the playerMove() code to this, it refuses to update the position of the enemies; they stay in the same place turn after turn.
This is the drawWorld() function:
void drawWorld(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true)
cout << "P";
else if (array[i].trap==true)
cout << "T";
else if (array[i].enemy==true)
cout << "E";
else if (array[i].treasure==true)
cout << "X";
else if (array[i].player==true && array [i].treasure==true)
cout << "W";
else if ((array[i].player==true && array[i].trap==true) || (array[i].player==true && array[i].enemy==true))
cout << "L";
else {
cout << "O";
}
if ((i+1 % 10) == 0){
cout << endl;
}
}
cout << endl << endl;
}
It draws the world fine, except that it won't wrap the text every ten characters as it is plainly told to do. I can't fathom what I'm missing here.
Finally, this is the endCheck() function:
bool endCheck(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true && array[i].treasure==true){
cout << "You found the treasure and now enjoy a life of unmitigated opulence." << endl;
return true;
}
else if (array[i].player==true && array[i].trap==true){
cout << "You fell into a conspicuous trap and became tiger food." << endl;
return true;
}
else if (array[i].player==true && array[i].enemy==true){
cout << "You were captured alive by angry natives and enjoyed as part of their New Year's feast." << endl;
return true;
}
else
return false;
}
}
This is simply not executing at all. I can move the player onto a trap and nothing happens.
These problems are incredibly frustrating because I am simply unable to discern what is wrong with the code. I know the post is long, but if anyone could point out what's wrong it'd be greatly appreciated. Also it should be noted that I searched for answers before posting this, but because I think the problems are intrinsic to my code I was unable to find any usable answers.
You are returning at the end of first iteration. So it will check only first field and then return false (if there was no player and treasure/trap/enemy in first field).
Change your function to look like this:
bool endCheck(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true && array[i].treasure==true){
cout << "You found the treasure and now enjoy a life of unmitigated opulence." << endl;
return true;
}
else if (array[i].player==true && array[i].trap==true){
cout << "You fell into a conspicuous trap and became tiger food." << endl;
return true;
}
else if (array[i].player==true && array[i].enemy==true){
cout << "You were captured alive by angry natives and enjoyed as part of their New Year's feast." << endl;
return true;
}
}
return false;
}
You have to check all possible fields before returning false that indicates no collision.
In enemiesMoves(), you are checking if(n = 1), I'm sure you meant if(n == 1).
Do this:
....
n = rand() % 4 + 1;
if (n == 1){
.....
Also, n == 1 case is checked twice! Once in if and then in the last else if.
For the rand() function to actually generate random numbers on each run, initialize a random seed first using srand(), as follows:
/* initialize random seed: */
srand (time(NULL));
n = rand() % 4 + 1;

Simple coding to Stack

int main()
{
string sentence;
int length;
cout << "Enter the sentence now." << endl;
getline(cin, sentence);
for(int i = 0; i < sentence[i]; i++)
{
if(sentence[i]==';')
cout<<" ";
else if(sentence[i] != ' ')
{
cout << sentence[i];
}
else if(sentence[i] == ' ')
{
cout << endl;
}
}
}
I need help in this code to change into stack coding method. At least you can show me some clue how to change this code into simple stack code.
cin>>a>>b>>c>>d>>e>>f>>g;
myStack.push(g);
myStack.push(f);
myStack.push(e);
myStack.push(d);
myStack.push(c);
myStack.push(b);
myStack.push(a);
while(!myStack.empty()){
cout<<myStack.top()<<endl;
myStack.pop();
}
return 0;
}
This is an example, but its not flexible. User only can enter 7 words or maybe we can do it in array?

Sentinel not working?

I'm not sure why this isn't working, but this is my error message:
Error] no match for 'operator!=' (operand types are 'std::string {aka std::basic_string}' and 'const int')
EDIT: The above issue has been resolved. But, the current issues are redundant ***, and the lack of vowel removal in a sentence rather than just the first word of a sentence.
#include <iostream>
#include <string>
using namespace std;
void removeVowel(string&); // Removes vowels from input string.
string withVowel; // Will be used to read user input.
int main ()
{
const string SENTINEL = "0"; // Sentinel value.
// Request input string unless SENTINEL is entered.
cout << "Enter a word or series of words. " << '\n';
cout << "Or, enter " << SENTINEL << " to quit. " << endl;
cin >> withVowel;
// In case of SENTINEL:
while (withVowel == SENTINEL)
{
cout << "***" << endl;
}
// Run loop.
removeVowel(withVowel);
// Display the string without vowels.
cout << "The word(s) entered reflecting only consonants: " << withVowel << endl;
return 0;
}
void removeVowel(string& withVowel)
{
int i = 0;
int length = int(withVowel.length());
while (i < length)
{
if (withVowel.at(i) == 'a' ||
withVowel.at(i) == 'A' ||
withVowel.at(i) == 'e' ||
withVowel.at(i) == 'E' ||
withVowel.at(i) == 'i' ||
withVowel.at(i) == 'I' ||
withVowel.at(i) == 'o' ||
withVowel.at(i) == 'O' ||
withVowel.at(i) == 'u' ||
withVowel.at(i) == 'U')
{
withVowel.erase(i, 1);
length = int(withVowel.length());
}
else i++;
}
// Display the string without vowels.
cout << removeVowel << endl;
}
Based on your other question, and the error message, I assume withVowel is a std::string. The error message is pretty much telling you what the problem is: you can't compare a std::string with an int.
Since you only need SENTINEL for printing and comparison, just declare it as a std::string as well:
const std::string SENTINEL = "0";
You can't compare const int with strings.
Use ctrl+z and enter to stop the input.
string word;
cout << "ctrl+z and Enter to exit\n";
while (cin >> word){
cout << word << ' ';
// other processing
}
And for your case:
cout << "Enter a word or series of words.\n";
cout << "Ctrl+z and Enter to exit\n";
while (cin >> withVowel){
removeVowel(withVowel);
cout << "The word(s) entered reflecting only consonants :" << withVowel << endl;
}

find chars/string in string from vector c++

I have a vector of strings, and I want to count all 'Ace' in the vector. Right now I can only find one...
int main()
{
std::vector<string> vec;
vec.push_back("Ace of Spades");
vec.push_back("Ace");
string value = "Ace";
int cnt = 0;
auto iter = find_if(begin(vec), end(vec), [&](const string &str)
{
return str.find(value) != str.npos;
});
if(iter == end(vec))
cout << "no found" << endl;
else
{
cout << *iter << endl;
cnt++;
cout << cnt++ << endl;
}
}
You could use std::count_if:
auto cnt = count_if(begin(vec),
end(vec),
[&](const string& str) {
return str.find(value) != std::string::npos;
});
Note that this only counts the number of strings containing "Ace", not the total number of occurrences of "Ace" in the vector's elements.
If you just want to count the number of matching elements, you could use std::count_if.
If you also need to do something with them, it would probably be best to forget about the standard library algorithms and use a ranged for like so:
int count = 0;
for (const auto& element : vec) {
if (element.find(value) != std::string::npos) {
std::cout << element << std::endl;
++count;
}
}
std::cout << count << std::endl;

Resources