program skip over getline - c++

I am suppose to create a program such that when 'y' is entered it will execute the code in the first do-while loop. however, when 'y' is entered it just skips over the chunk of codes!
Enter a phone symbols:
a
2
Continue (Y/y): y
Enter a phone symbols:
Continue (Y/y):
Is there anyway I can solve this without using cin.ignore as it changes the layout. Thanks in advance!
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <iomanip>
#include <cstring>
const int MAX = 100;
using namespace std;
int getInt(char);
bool isValidChar(char);
int main()
{
int num;
int j = 0;
char name, conti;
char alpha[MAX];
do {
cout << "Enter a phone symbols: " << endl;
cin.getline(alpha, MAX);
// cin.ignore(100, '\n');
while (alpha[j] != '\0')
{
name = alpha[j];
if (isValidChar(name) == true)
{
num = getInt(name);
if (num == -1)
{
cout << "-";
}
else
{
cout << num;
}
}
else
{
cout << " - Invalid Char " << name << " found - rejected";
}
j++;
} // end while
cout << endl;
do {
cout << "\nContinue (Y/y): ";
cin >> conti;
cout << "\n" << endl;
conti = tolower(conti);
if (conti == 'n')
{
exit(0);
}
} while (conti != 'n' && conti != 'y');
} while (conti == 'y');
}
int getInt(char input)
{
int result;
char value;
value = tolower(input);
if ((value >= 'a' && value <= 'c'))
{
result = 2;
}
else if ((value >= 'd' && value <= 'f'))
{
result = 3;
}
else if ((value >= 'g' && value <= 'i'))
{
result = 4;
}
else if ((value >= 'j' && value <= 'l'))
{
result = 5;
}
else if ((value >= 'm' && value <= 'o'))
{
result = 6;
}
else if ((value >= 'p' && value <= 's'))
{
result = 7;
}
else if ((value >= 't' && value <= 'v'))
{
result = 8;
}
else if ((value >= 'w' && value <= 'z'))
{
result = 9;
}
else if (value == ' ')
{
result = -1;
}
return result;
}
bool isValidChar(char value)
{
if (isalpha(value) || value == ' ')
{
return true;
}
else
{
return false;
}
}

What do you mean as: Is there anyway I can solve this without using cin.ignore as it changes the layout.?
Your layout is contolled, basicly by this line:
cout << "\nContinue (Y/y): ";
cin >> conti;
cout << "\n" << endl; // <-- this one
conti = tolower(conti);
If you supress it, there will be no empty line. Otherwise, if you change it to
cout << endl;
Just one empty line.

Related

C++ Vigenere and Caesar cipher in the same programming with switch case

In the first code I did a Caesar cipher and it is working well. However, i cannot added Vigenere. There is a class and some pointers, but they do not work in the switch-case statement, so I need help.
encryption part is switch case :3
decryption part is switch case :4
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
char message[200], ch;
int i, key;
string k,output,messageV;
int menu(int answer);
int main()
{
int answer;
bool keepLooping = true;
while (keepLooping)
{
cout << "Pick a Choice from the List: \n(1)Caesar \n(2)Vigenere \n ";
cin >> answer;
if (answer == 1)
{
while(keepLooping)
{
cout << "Pick a Choice from the List: \n(1)Encryption\n(2)Decryption \n ";
cin >> answer;
if (answer == 1)
{
answer = 1;
keepLooping = false ;
}
else if(answer == 2)
{
answer = 2;
keepLooping = false;
}
else
{
keepLooping = true;
}
}
}
else if(answer == 2)
{
while(keepLooping)
{
cout << "Pick a Choice from the List: \n(1)Encryption\n(2)Decryption \n ";
cin >> answer;
if (answer == 1)
{
answer = 3;
keepLooping = false ;
}
else if(answer == 2)
{
answer = 4;
keepLooping = false;
}
else
{
keepLooping = true;
}
}
}
else
{
keepLooping = true;
}
}
menu(answer);
}
int menu(int answer)
{
switch (answer)
{
case 1://Caesar Cipher Encryption
cout << "Enter a message to encrypt: ";
cin.ignore();
cin.getline(message, 200);
cout << "Enter key: ";
cin >> key;
for(i = 0; message[i] != '\0'; ++i){
ch = message[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch + key;
if(ch > 'z'){
ch = ch - 'z' + 'a' - 1;
}
message[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch + key;
if(ch > 'Z'){
ch = ch - 'Z' + 'A' - 1;
}
message[i] = ch;
}
}
cout << "Encrypted message: " << message;
break;
case 2://Caesar Cipher Decryption
cout << "Enter a message to decrypt: ";
cin.ignore();
cin.getline(message, 200);
cout << "Enter key: ";
cin >> key;
for(i = 0; message[i] != '\0'; ++i){
ch = message[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch - key;
if(ch < 'a'){
ch = ch + 'z' - 'a' + 1;
}
message[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch - key;
if(ch > 'a'){
ch = ch + 'Z' - 'A' + 1;
}
message[i] = ch;
}
}
cout << "Decrypted message: " << message;
break;
case 3:
cout << "CASE 3";
break;
case 4:
cout << "CASE 4";
break;
default:
cout << "There is no choices." << endl;
}
return answer;
}
Vigenere part:
#include <iostream>
#include <string>
using namespace std;
class Vig {
public:
string k;
Vig(string k) {
for (int i = 0; i < k.size(); ++i) {
if (k[i] >= 'A' && k[i] <= 'Z')
this->k += k[i];
else if (k[i] >= 'a' && k[i] <= 'z')
this->k += k[i] + 'A' - 'a';
}
}
string encryption(string t) {
string output;
for (int i = 0, j = 0; i < t.length(); ++i) {
char c = t[i];
if (c >= 'a' && c <= 'z')
c += 'A' - 'a';
else if (c < 'A' || c > 'Z')
continue;
output += (c + k[j] - 2 * 'A') % 26 + 'A'; //added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ]
j = (j + 1) % k.length();
}
return output;
}
string decryption(string t) {
string output;
for (int i = 0, j = 0; i < t.length(); ++i) {
char c = t[i];
if (c >= 'a' && c <= 'z')
c += 'A' - 'a';
else if (c < 'A' || c > 'Z')
continue;
output += (c - k[j] + 26) % 26 + 'A';//added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ]
j = (j + 1) % k.length();
}
return output;
}
};
int main() {
char message[200];
string key;
cout << "Key: ";
cin >> key;
cin.ignore();
Vig v(key);
cout << "Enter a message to encrypt: ";
cin.getline(message, 200);
string ori = message;
string encrypt = v.encryption(ori);
string decrypt = v.decryption(encrypt);
cout << "Original Message: "<<ori<< endl;
cout << "Encrypted Message: " << encrypt << endl;
cout << "Decrypted Message: " << decrypt << endl;
}
My suggestion is that you try to find the common patterns in your two programs. For example you have you have to methods to encrypt and decrypt. That could be abstracted into two different classes, perhaps with a common base-class defining the interface (allowing things like polymorphism):
struct Cipher
{
virtual std::string encryption(std::string const&) = 0;
virtual std::string decryption(std::string const&) = 0;
};
class Caesar : public Cipher
{
public:
std::string encryption(std::string const& s) override
{
// TODO: Implement Caesar cipher encryption
}
std::string decryption(std::string const& s) override
{
// TODO: Implement Caesar cipher decryption
}
};
class Vigenere : public Cipher
{
public:
std::string encryption(std::string const& s) override
{
// TODO: Implement Vigenere cipher encryption
}
std::string decryption(std::string const& s) override
{
// TODO: Implement Vigenere cipher decryption
}
};
From this we could create a set of functions to use any cipher (through pointers to the base Cipher class). Lets start with selecting which cipher to use:
Cipher* select_cipher()
{
std::cout << "Please select cipher to use:\n";
std::cout << "1) Caesar\n";
std::cout << "2) Vigenere\n";
int selection;
std::cin >> selection;
if (selection == 1)
{
return new Caesar;
}
else if (selection == 2)
{
return new Vigenere;
}
else
{
return nullptr;
}
}
Now we have a cipher to use, then select what to do:
int select_method()
{
std::cout << "Do you want to encrypt or decrypt?\n";
std::cout << "1) Encrypt\n";
std::cout << "2) Decrypt\n";
int method;
std::cin >> method;
return method;
}
Now we really have everything needed to use any supported cipher and method:
int main()
{
Cipher* cipher = select_cipher();
int method = select_method();
std::string input;
std::string result;
// TODO: Read input string to encrypt or decrypt
if (method == 1)
{
result = cipher->encryption(input);
}
else if (method == 2)
{
result = cipher->decryption(input);
}
std::cout << "Result = " << result << '\n';
}
Do note that this is only a very rough outline, and there are many parts missing (like the actual encryption and decryption algorithms). These are left as an exercise for the readers.
Instead of using if ... else if ... you can of course use switch. But for these simple cases it doesn't really matter, and if ... else if ... is, IMO, easier to read.
I coded it already can you check it too, please ?
#include <iostream>
#include <string>
using namespace std;
class Vig {
public:
string k;
Vig(string k) {
for (int i = 0; i < k.size(); ++i) {
if (k[i] >= 'A' && k[i] <= 'Z')
this->k += k[i];
else if (k[i] >= 'a' && k[i] <= 'z')
this->k += k[i] + 'A' - 'a';
}
}
string Vegencryption(string t) {
string output;
for (int i = 0, j = 0; i < t.length(); ++i) {
char c = t[i];
if (c >= 'a' && c <= 'z')
c += 'A' - 'a';
else if (c < 'A' || c > 'Z')
continue;
output += (c + k[j] - 2 * 'A') % 26 + 'A'; //added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ]
j = (j + 1) % k.length();
}
return output;
}
string Vegdecryption(string t) {
string output;
for (int i = 0, j = 0; i < t.length(); ++i) {
char c = t[i];
if (c >= 'a' && c <= 'z')
c += 'A' - 'a';
else if (c < 'A' || c > 'Z')
continue;
output += (c - k[j] + 26) % 26 + 'A';//added 'A' to bring it in range of ASCII alphabet [ 65-90 | A-Z ]
j = (j + 1) % k.length();
}
return output;
}
string Cesencryption(string t, int key){
string output;
char ch;
for(int i = 0; t[i] != '\0'; ++i){
ch = t[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch + key;
if(ch > 'z'){
ch = ch - 'z' + 'a' - 1;
}
t[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch + key;
if(ch > 'Z'){
ch = ch - 'Z' + 'A' - 1;
}
t[i] = ch;
}
}
output = t;
return output;
}
string Cesdencryption(string t, int key){
string output;
char ch;
for(int i = 0; t[i] != '\0'; ++i){
ch = t[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch - key;
if(ch < 'a'){
ch = ch + 'z' - 'a' + 1;
}
t[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch - key;
if(ch > 'a'){
ch = ch + 'Z' - 'A' + 1;
}
t[i] = ch;
}
}
output = t;
return output;
}
};
int main() {
char message[200];
string key;
int choice;
cout << "Pick a Choice from the List: \n(1)Caesar \n(2)Vigenere \n ";
cin >> choice;
if(choice == 2) //Vigenere
{
cout << "Pick a Choice from the List: \n(1)Encryption\n(2)Decryption \n ";
cin >> choice;
if (choice == 1)
{
cout << "Key: ";
cin >> key;
cin.ignore();
Vig v(key);
cout << "Enter a message to encrypt: ";
cin.getline(message, 200);
string ori = message;
string encrypt = v.Vegencryption(ori);
cout << "Encrypted Message: " << encrypt << endl;
}
else if (choice == 2)
{
cout << "Key: ";
cin >> key;
cin.ignore();
Vig v(key);
cout << "Enter a message to encrypt: ";
cin.getline(message, 200);
string ori = message;
string decrypt = v.Vegdecryption(ori);
cout << "Decrypted Message: " << decrypt << endl;
}
else
{
cout << "You Exit the Program.";
}
}
else if (choice == 1) //Ceaser
{
cout << "Pick a Choice from the List: \n(1)Encryption\n(2)Decryption \n ";
cin >> choice;
if (choice == 1)
{
int key;
cout << "Enter a message to encrypt: ";
cin.ignore();
cin.getline(message, 200);
cout << "Enter key: ";
cin >> key;
Vig v(message);
string ori = message;
string decrypt = v.Cesencryption(ori,key);
cout << "Decrypted Message: " << decrypt << endl;
}
else if (choice == 2)
{
int key;
cout << "Enter a message to dencrypt: ";
cin.ignore();
cin.getline(message, 200);
cout << "Enter key: ";
cin >> key;
Vig v(message);
string ori = message;
string encryption = v.Cesdencryption(ori,key);
cout << "Decrypted Message: " << encryption << endl;
}
else
{
cout << "You Exit the Program.";
}
}
else
{
cout << "You Exit the Program.";
}
}

Extracting a vowels from an array..and storing nd printing on another array

Write a program using for loop which stores alphabets from Z-A. Extract only vowels from this array and store them into another array vowels. Now display these vowels using for loop from vowels array.
My output is not working properly. If I write my name without spaces like abdulhananhamid, then it works and shows a u a a.
I do not know how to use cin in a for loop, either.
#include<iostream>
#include<conio.h>
using namespace std;
int vowel (char x);
int main()
{
char size=100;
char x[size];
char A[5];
int n,i,;
cout<<"Enter any string\n";
cin>>x;
for (i = 0, n = 0; i<size; i++)
if (vowel(x[i]))
A[n++] = x[i];
for (n = 0;n<5;n++)
cout << A[n] << " ";
getch();
return 0;
}
int vowel(char x)
{
if(x=='a'||x=='e'||x=='i'||x=='o'||x=='u')
return 1;
else
return 0;
}
This looks like a good assignment for using std::string and std::getline.
std::string user_text;
std::cout << "Enter a string: ";
while (std::getline(std::cin, user_text)
{
const size_t length = user_text.length();
std::string vowels;
for (size_t i = 0; i < length; ++i)
{
const char c = user_text[i];
if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u'))
{
vowels += c;
}
}
std::cout << "Vowels found: " << vowels << "\n";
std::cout << "\nEnter a string: ";
}
If you must use character arrays, you should check for overflow:
unsigned int MAXIMUM_CHARACTERS = 128;
char user_text[MAXIMUM_CHARACTERS];
char vowels_found[MAXIMUM_CHARACTERS];
std::cout << "Enter a string: ";
while (std::cin.getline(&user_text[0], MAXIMUM_CHARACTERS))
{
unsigned int vowel_index = 0U;
const size_t length = strlen(user_text);
for (size_t i = 0; i < length; ++i)
{
const char c = user_text[i];
if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u'))
{
vowels_found[vowel_index++] = c;
}
}
vowels_found[vowel_index] = '\0';
std::cout << "Vowels found: " << vowels_found << "\n";
std::cout << "\nEnter a string: ";
}
A function for checking for a vowel could look like:
bool is_vowel(char c)
{
return (c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u');
}

C++ a function call is not called again after the loop iterates

Hey so I am relatively a beginner at programming. I am trying to create a very simple minesweeper game over a 2D array, the issue I am running into is after the player steps on a mine (game over) they are given the option to play again. After this the set difficulty function is supposed to be called a second time (since it is within the loop) and a new minefield is to be generate. Unfortunately none of that is happening and the program skips that process.
Here is my code:
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
int choose_difficulty(int x);
int generator();
int main()
{
//create initial variables
string Ans;
int Rounds;
int NewPosition_x = 0;
int NewPosition_y = 0;
//ask user if he wants to run the program and expect input
cout << "Would you like to play a game? Y/N" << endl;
cin >> Ans;
//based on user input the program will run or not
if (Ans == "Y" || "y") {
while (Ans == "Y" || "y")
{
//Create position variables to be checked
int Position_x;
int Position_y;
//ask user how many rounds in the game they want
cout << "How many chances do you want to give yourself?" << endl;
cin >> Rounds;
//Generate minefield could not be done as separate function since you cannot output an array
int a = choose_difficulty(a);
int mines;
int n,m;
srand (time (0));
if(a == 0) {
mines = 3;
n = 4;
m = n;
}
else if (a == 1){
mines = 5;
n = 4;
m = n;
}
else if (a == 2){
mines = 7;
n = 4;
m = n;
}
int minefield[n][m] = { };
int g, h;
for (int num = 0; num < mines; num++) {
g = rand()%n;
h = rand()%n;
minefield[g][h] = 1;
}
for (int x = 0; x < Rounds; x++)
{
//Begin Game
cout << "Where are you at to avoid the mines? (Enter a 2 numbers 0 through 3)" << endl;
cin >> NewPosition_x >> NewPosition_y;
//check if the player has entered a new position
while (NewPosition_x == Position_x && NewPosition_y == Position_y) {
cout << "You have to move somewhere, put a valid location" << endl;
cin >> NewPosition_x >> NewPosition_y;
}
//check to see if that position is valid
while ((NewPosition_x < 0 || NewPosition_x > 3) || (NewPosition_y < 0 || NewPosition_y > 3)) {
cout << "I'm sorry, but that place doesn't exist. Try somewhere else" << endl;
cin >> NewPosition_x >> NewPosition_y;
}
//Assign Player Position and check position vs mines
Position_x = NewPosition_x;
Position_y = NewPosition_y;
if (minefield[Position_y][Position_x] == 1) {
cout << "You stepped on a mine, Game Over" << endl;
cout << "You minefield was this:" << endl;
for (int i=0; i < n; i++){
for (int j=0; j < n; j++){
cout << minefield[i][j] << "\t";
}
cout << endl;
}
cout << "Would you like to play again? Y/N" << endl;
cin >> Ans;
if (Ans == "n" || Ans == "N"){
return 0;
}
}
else if ((minefield[Position_x + 1][Position_y] == 1) || (minefield[Position_x - 1][Position_y] == 1) || (minefield[Position_x][Position_y + 1] == 1) || (minefield[Position_x][Position_y - 1] == 1)) {
cout << "You're hot right now, you better watch your step. Continue to the next round" << endl;
}
else {
cout << "You're safe. Continue to the next round" << endl;
}
}
}
}
return 0;
}
int choose_difficulty(int a)
{
do{
string difficulty;
//Difficulty Selection
cout << "Choose the game difficulty: Easy, Medium, Hard" << endl;
cin >> difficulty;
if (difficulty == "easy" || difficulty == "Easy"){
a = 0;
}
else if (difficulty == "medium" || difficulty == "Medium"){
a = 1;
}
else if (difficulty == "hard" || difficulty == "Hard"){
a = 2;
}
else {
cout << "Invalid input";
a = 3;
}
}while (a == 3);
return a;
}
You should be careful on this kind of error:
//based on user input the program will run or not
if (Ans == "Y" || "y") {
while (Ans == "Y" || "y")
{
This, above, will always be true being "y" different from 0 (false).
Instead you need to check that Ans is either equal to "Y" or "y" in this way:
//based on user input the program will run or not
if (Ans == "Y" || Ans == "y") {
while (Ans == "Y" || Ans == "y")
{
Or use, as suggested in the comments, std::toupper()
UPDATE
It seems you have a problem on your buffer you should use cin.ignore() in order to clean it;

How can i get a result in my Roman numeral to decimal converter?

#include <iostream>
#include <string>
using namespace std;
class rom2dec
{
public: void roman();
int convert();
void print();
void get();
private: int M, D, C, L, X, V, I;
char romanNumeral;
};
void rom2dec::roman()
{
M = 1000;
D = 500;
C = 100;
L = 50;
X = 10;
V = 5;
I = 1;
}
int rom2dec::convert()
{
if(romanNumeral == 'I' || 'i')
{ cout << 1; }
else if(romanNumeral == 'V' || 'v')
{ cout << 5; }
else if(romanNumeral == 'X' || 'x')
{ cout << 10; }
else if(romanNumeral == 'L' || 'l')
{ cout << 50; }
else if(romanNumeral == 'C' || 'c')
{ cout << 100; }
else if(romanNumeral == 'D' || 'd')
{ cout << 500; }
else if (romanNumeral == 'M' || 'm')
{ cout << 1000; }
else if(romanNumeral != 'I' && romanNumeral != 'i' && romanNumeral != 'V' && romanNumeral != 'v' && romanNumeral != 'X' && romanNumeral != 'x' && romanNumeral != 'L' && romanNumeral != 'l' && romanNumeral != 'C' && romanNumeral != 'c' && romanNumeral != 'D' && romanNumeral != 'd' && romanNumeral != 'M' && romanNumeral != 'm')
{ cout << "Error! Not a valid value!" << endl; }
return romanNumeral;
}
void rom2dec::print()
{ cout << romanNumeral << endl; }
void rom2dec::get(){ }
int main()
{
char romanNumeral;
cout << "Please enter a number in Roman numerals to be converted: " << endl;
cin >> romanNumeral;
return 0;
}
I get no errors when I build the program, but when I debug and try to convert a Roman numeral to a decimal I get no decimal. All suggestions welcome and if there is a simpler way to write the last else if please let me know. Thanks.
There are many errors in your program:
constructor, destructor was missing in class rom2dec
main function was not calling methods to do conversion
if statements were wrong.
I have fixed the code:
#include <iostream>
#include <string>
using namespace std;
class rom2dec
{
public:
rom2dec(char x): romanNumeral(x) {};
~rom2dec() {};
void roman();
int convert();
void print();
void get();
private: int M, D, C, L, X, V, I;
char romanNumeral;
};
void rom2dec::roman()
{
M = 1000;
D = 500;
C = 100;
L = 50;
X = 10;
V = 5;
I = 1;
}
int rom2dec::convert()
{
if (romanNumeral == 'I' || romanNumeral == 'i')
{ cout << 1; }
else if (romanNumeral == 'V' || romanNumeral == 'v')
{ cout << 5; }
else if (romanNumeral == 'X' || romanNumeral == 'x')
{ cout << 10; }
else if ((romanNumeral == 'L') || romanNumeral == 'l')
{ cout << 50; }
else if (romanNumeral == 'C' || romanNumeral == 'c')
{ cout << 100; }
else if (romanNumeral == 'D' || romanNumeral == 'd')
{ cout << 500; }
else if (romanNumeral == 'M' || romanNumeral == 'm')
{ cout << 1000; }
else
{ cout << "Error! Not a valid value!" << endl; }
return romanNumeral;
}
void rom2dec::print()
{ cout << romanNumeral << endl; }
void rom2dec::get(){ }
int main()
{
char romanNumeral;
cout << "Please enter a number in Roman numerals to be converted: " << endl;
cin >> romanNumeral;
rom2dec obj(romanNumeral);
obj.convert();
return 0;
}
I gave that a little remake.
instead of a noodle-like if-else-if-else-if control-statement I used an unordered map to map the lowercase numerals to int (uppercase chars are converted to lowercase before looked up in the map).
the class itself is now an improved singleton, and works as a functor on chars.
there's now an overloaded istream operator>> that allows using the class instance as a sink for istreams (std::cin or the stringstream I used to mock user input)
To use that interactively, simply change the #if 0 to #if 1
#include <iostream>
#include <unordered_map>
#include <string>
#include <sstream>
class rom2dec
{
public:
using map_type = std::unordered_map<char,int>;
static rom2dec& instance() {
static rom2dec r2d;
return r2d;
}
int operator() (char romanNumeral) const;
void print(char romanNumeral) const;
void get(); // ?
private:
rom2dec() = default;
~rom2dec() = default;
rom2dec(const rom2dec&) = delete;
rom2dec(rom2dec&&) = delete;
rom2dec& operator=(rom2dec&&) = delete;
rom2dec& operator=(const rom2dec&) = delete;
static map_type map_;
};
rom2dec::map_type rom2dec::map_ = {
{'i', 1},
{'v', 5},
{'x', 10},
{'l', 50},
{'c', 100},
{'d', 500},
{'m', 1000}
};
int rom2dec::operator() (char romanNumeral) const
{
int rv = -1;
auto it = map_.find(std::tolower(romanNumeral));
if (it != map_.end()) {
rv = it->second;
} else {
std::cerr << "Error! '" << romanNumeral
<< "' is not a valid value!"
<< std::endl;
}
return rv;
}
void rom2dec::print(char romanNumeral) const
{
std::cout << romanNumeral << "\n";
}
void rom2dec::get() {}
std::istream& operator>>(std::istream& is, const rom2dec& r2d) {
char romanNumeral;
if (is >> romanNumeral) {
int dec = r2d(romanNumeral);
if (dec > 0)
std::cout << romanNumeral << " = " << dec << "\n";
}
return is;
}
int main()
{
auto& r2d = rom2dec::instance();
#if 0
auto& is = std::cin;
#else
std::stringstream is("C\n+\n+\nM\nM\nX\nI\nV");
#endif
do {
std::cout << "Please enter a single Roman numeral to be converted"
<< "(press <CTRL>+<D> to terminate):\n";
} while (is >> r2d);
return EXIT_SUCCESS;
}
live at Coliru's

Can anyone tell me why these functions are not giving me a result in a reasonable spectrum?

The full code I am using is listed below, it is supposed to simulate a game of craps and print details to the user and allow for betting if the user desires it. Everything functions except for the actual craps game. Instead of looping only while there is not a truth value associated to crapsResult, it finds one real value and an incomprehensible string of a single negative number. Any help would be appreciated.
int main()
{
//Declare the user input variables
int gamesPlayed = 0;
char inputPrint = ' ';
char isBetting = ' ';
int startingBet = 0;
//Declare the variables used by the program
int endingBet = 0;
int currentGame = 0;
bool crapsResult;
int gamesWon = 0;
int gamesLost = 0;
double percentWon = 0;
bool detailPrint = false;
//Prompt the user to input their variables
cout << "Enter the number of games to be played: ";
cin >> gamesPlayed;
while(gamesPlayed < 1)
{
cout << " Error: must be greater than 0" << endl;
cout << "Enter the number of games to be played: ";
cin >> gamesPlayed;
cin.clear();
cin.ignore();
}
cout << "Do you wish to print details (Y/N): ";
cin >> inputPrint;
if(inputPrint == 'y' || inputPrint == 'Y')
{
detailPrint = true;
}
cout << "Do you wish to bet (Y/N): ";
cin >> isBetting;
if(isBetting == 'y' || isBetting == 'Y')
{
cout << "Enter money to start betting with: ";
cin >> startingBet;
while(startingBet < 1)
{
cout << " Error: must be greater than 0" << endl;
cout << "Enter the number of games to be played: ";
cin >> gamesPlayed;
cin.clear();
cin.ignore();
}
}
//Seed the random number generator
srand(time(NULL));
//Set a value for ending bet
if(startingBet == 0)
{
endingBet = 1;
}
else
{
endingBet = startingBet;
}
//Call playcraps to simulate the game for as many games as the user input
for(currentGame = 1; currentGame <= gamesPlayed && endingBet > 0; currentGame += 1)
{
crapsResult = NULL;
crapsResult = playCraps(currentGame, detailPrint, isBetting, startingBet);
if(crapsResult == true)
{
gamesWon += 1;
endingBet = betting(endingBet, crapsResult);
}
if(crapsResult == false)
{
gamesLost += 1;
endingBet = betting(endingBet, crapsResult);
}
if((isBetting == 'Y' || isBetting == 'y') && (detailPrint == true))
{
cout << "Money left is $" << endingBet << endl;
}
}
//Calculate the percentage of games won
percentWon = (double(gamesWon) / double(currentGame-1)) * 100.0;
//Print the results to the user
if(isBetting == 'Y' || isBetting == 'y')
{
cout << "Money at end of games is $" << endingBet << endl;
}
cout << "The number of games played is " << currentGame - 1 << endl;
cout << "The number of games won is " << gamesWon << endl;
cout << "The number of games lost is " << gamesLost << endl;
cout << "The percent of games won is " << fixed << showpoint << setprecision(3) << percentWon << endl;
}
//Simulates the roll of a single die and returns the result
int roll()
{
int rollResult = 0;
rollResult = rand() % 6 + 1;
return rollResult;
}
//Calls roll twice and returns the sum of the two results
int roll2Dice()
{
//Declare variables for this function
int rollOne = 0;
int rollTwo = 0;
int rollSum = 0;
//Find rollOne and rollTwo
rollOne = roll();
rollTwo = roll();
//Find rollSum
rollSum = rollOne + rollTwo;
return rollSum;
}
bool playCraps(int currentGame, bool detailPrint, char isBetting, int startingBet)
{
bool crapsResult = NULL;
int currentGameStorage[100];
int currentRoll = 1;
int point = roll2Dice();
int printingNumber = 0;
currentGameStorage[0] = point;
if(point == 7 || point == 11)
{
crapsResult = true;
}
else if(point == 2 || point == 3 || point == 12)
{
crapsResult = false;
}
else
{
crapsResult = NULL;
}
while(crapsResult != true && crapsResult != false)
{
currentGameStorage[currentRoll] = roll2Dice();
if(currentGameStorage[currentRoll] == point)
{
crapsResult = true;
}
else if(currentGameStorage[currentRoll] == 7)
{
crapsResult = false;
}
currentRoll += 1;
}
if(detailPrint == true)
{
cout << "Game " << currentGame << ": ";
for(printingNumber = 0; printingNumber <= currentRoll; printingNumber += 1)
{
cout << currentGameStorage[printingNumber] << " ";
}
if(crapsResult == true)
{
cout << "win";
}
else if(crapsResult == false)
{
cout << "lose";
}
cout << endl;
}
return crapsResult;
}
int betting(int endingBet, bool crapsResult)
{
if(crapsResult == true)
{
endingBet += 1;
}
else if(crapsResult == false)
{
endingBet -= 1;
}
return endingBet;
}
Just skimmed and didn't read all of your code (so there may be other things wrong too), but this line is definitely problematic:
while(crapsResult != true && crapsResult != false)
It is logically impossible for crapsResult to simultaneously be both true and false, so that loop will never be entered.
Turix got the right bug I believe, but I would put the emphasis on a different spot:
bool crapsResult = NULL;
You are trying to use crapsResult for three different values (true, false and NULL). However, NULL usually has a integer value of 0, which translates to a boolean value of false, so your loop will never be entered.
Then a second bug comes into play: currentRoll is 1 at this time, so you try to print the contents of currentGameStorage from index 0 to 1 (inclusive), currentGameStorage[1] hasn't been assigned yet. This is why you get the cryptic numer in your output. This is a general mistake: Your code always tries to print one item too much. Use < instead of <= in the loop head to fix that:
for(printingNumber = 0; printingNumber < currentRoll; printingNumber += 1)