C++ Skipping cin statement. going into infinite loop - c++

For some reason, it goes into the cin statement the first time but then skips it every other time in this code. After running it a few times, I realized it goes into the default case for some reason without even asking for the user input. Why?
Here's the code. It's a menu with a huge switch statement. The functions inside the switch statements aren't relevant here since it's just the overall loop.
int main()
{
Document* myDocs = new Document[10];
int docCount = 0;
bool menu = true;
int userInput = 0;
while ( menu == true )
{
//int userInput = 0;
userInput = 0;
cout << "----------------MENU----------------" << endl << endl;
cout << " --------(1) LOAD DOCUMENT (1)--------- " << endl << endl;
cout << "--------(2) OUTPUT DOCUMENT (2)--------" << endl << endl;
cout << " --------(3) ANALYZE DOCUMENT (3)-------- " << endl << endl;
cout << " ------(4) COMPARE TWO DOCUMENTS (4)------ " << endl << endl;
cout << " ----------(5) ENCRYPT (5)---------- " << endl << endl;
cout << "-----------(6) DECRYPT (6)----------" << endl << endl;
cout << "-------------(7) EXIT (7)--------------" << endl << endl;
cin >> userInput;
string docName;
string outputLoc;
switch (userInput)
{
case 1:
// Function
break;
case 2:
// Function
break;
case 3-8:
// Function
break;
default:
break;
}
Basically, I first enter the first userinput. Let's say I enter 1. Then it goes into case 1. But then after it gets out of case 1, it goes into an infinite loop that keeps displaying the menu. Shouldn't it stop at the cin statement? That's what I dont understand.
EDIT::
Case 1 is the primary one i'm worried about since I'm trying them 1 by and 1 and case 1 doesn't work.
This is the full code for case 1:
case 1: // Load Document
{
string inputLoc;
cout << "Please input the document name:" << endl;
cin >> docName;
myDocs[docCount].setName(docName);
myDocs[docCount].id = docCount;
cout << "Input Location: " << endl;
cin >> inputLoc;
myDocs[docCount].loadDocument(inputLoc);
docCount++;
break;
}
I'm starting to speculate there is something wrong with my loadDocument function.
Here is the code for that:
void Document::loadDocument(string name)
{
ifstream myFile(name);
int numOflines = 0;
string theLine;
char words;
while (myFile.get(words))
{
switch (words)
{
case '.':
numOflines++;
break;
case '?':
numOflines++;
break;
case '!':
numOflines++;
break;
}
}
lineCount = numOflines;
setLineCt(numOflines);
arr = new Line[lineCount];
myFile.close();
char theChar;
ifstream myFile2(name);
int key = 0;
if (myFile2.is_open())
{
for ( id = 0; id < lineCount; id++ )
{
while (myFile2>> noskipws>>theChar && theChar != '.' && theChar != '!' && theChar != '?') // Changed from || to &&
{
//myFile2>> noskipws >> theChar;
theLine[key] = theChar;
key++;
}
myFile2>>theChar;
arr[id].setStr(theLine);
}
}
}
Basically I'm trying to load the document and store the word count and line count from it. Is there something wrong in it?

Related

How do I output a compiled file from TXT text to the screen?

I am working on an assignment about "CaesarCipher". This assignment requires me to:
Write a program that will ask the user to enter the name of a file. Your program should then ask the user to enter 'encrypt' or 'decrypt'.
If the user enters anything else your program should print an error message and exit.
If they entered 'encrypt' your program should open the file and encrypt it by shifting each character (including white space) 3 values to the right.
If they entered 'decrypt' your program should open the file and decrypt it by shifting each character (including white space) 3 values to the left.
If the file fails to open your program should print an error message and exit.
The decrypted or encrypted message should be displayed on The screen and also written to an output file named "message".
Also report the frequency of the vowels (A ,E ,I , O, U, Y) in input message.
I think I'm more than halfway there, but I have no way to print the processed "c" value to the screen, and every time I try to run it I skip the middle part of the compiled text I want and print.
int main(){
//Data Abstraction
bool goodFile = true;
bool goodCommand = true;
string fileName;
string command;
string message;
ifstream inputFile;
ofstream outputFile;
int shift = 3;
int numA = 0, numE = 0, numI = 0, numO = 0, numU = 0;
char c;
// Input
cout << "Enter File Name: ";
cin >> fileName;
cout << fileName << endl;
cout << "Enter encrypt or decrypt: ";
cin >> command;
cout << command << endl;
// Open File
inputFile.open(fileName);
outputFile.open(message);
// Identify whether output Error message
if(!inputFile){
goodFile = false;
}
if(command != "encrypt" && command != "decrypt"){
goodCommand = false;
}
if (goodCommand != true){
cout << "Error: Bad Command." << endl;
}
if(goodFile != true){
cout << "Error: File did NOT open." << endl;
}
// Identify process data or not
if (goodFile == true && goodCommand == true){
if(command == "decrypt"){
shift = -3;
}
while(inputFile.get(c)){
c+= shift;
c = static_cast<char>(c+shift);
cout << c;
switch(toupper(c)){
case 'a':
break;
case 'e':
break;
case 'i':
break;
case 'o':
break;
case 'u':
break;
}
if(c == 'a'){
numA++;
}
if(c == 'e'){
numE++;
}
if(c == 'i'){
numI++;
}
if(c == 'o'){
numO++;
}
if(c == 'u'){
numU++;
}
}
outputFile << c << endl;
outputFile << "Letter Frequency" << endl;
outputFile << " A "<< numA << endl;
outputFile << " E "<< numE << endl;
outputFile << " I "<< numI << endl;
outputFile << " O "<< numO << endl;
outputFile << " U "<< numU << endl;
inputFile.close();
outputFile.close();
cout << "Letter Frequency" << endl;
cout << " A "<< numA << endl;
cout << " E "<< numE << endl;
cout << " I "<< numI << endl;
cout << " O "<< numO << endl;
cout << " U "<< numU << endl;
}
return 0;
}
I am posting this as an answer to make the code readable.
toupper(c) will convert the character c to upper case; it will never be equal to 'a', 'e', etc. Use 'A'.
You need to check for vowels in the input, so do your test before encoding/decoding. And increment the counters in the appropriate case:
while (inputFile.get(c)) {
switch (toupper(c)) {
case 'A':
numA++;
break;
case 'E':
numE++;
break;
case 'I':
numI++;
break;
case 'O':
numO++;
break;
case 'U':
numU++;
break;
}
c += shift;
cout << c;
// ...
}

Why doesn't my vending machine program work correctly?

Program should begin with asking , whether to restock or continue with the current stock. The case 1 ( restock ) works perfectly , however the second case , to continue with the previous stock , returns zeros always if any of the products is zeroed.
In the textfile I have:
Milk: 10
Eggs: 2
Water: 7
Burrito: 10
Bread: 12
exit
How can i fix that ?
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<string>
#include<sstream>
using namespace std;
string productName[5] = { "Milk", "Eggs", "Water", "Burrito", "Bread" };
//int productAmount[5] = { 5,12,10,4,7};
int productAmount[5];
int productPick;
int defaultPick;
int productBuy;
fstream productFile; //we create file
void loadFromFile()
{
productFile.open("productsfile.txt", ios::in);
if (productFile.good() == false)
{
cout << "Unable to load the file. Try again later." << endl;
productFile.close();
exit(0);
}
else
{
ifstream productFile("productsfile.txt");
if (productFile.is_open())
{
cout << "How may I help you?" << endl;
string line;
while (getline(productFile, line))
{
// using printf() in all tests for consistency
cout << line.c_str() << endl;
}
productFile.close();
}
}
}
void saveToFile() //this function saves in the text file the data we've globally declared. It is used only if you want to declare new variables.
{
productFile.open("productsfile.txt", ios::out);
for (int i = 0; i < 5; i++)
{
productFile << i + 1 << ". " << productName[i] << ": " << productAmount[i] << endl;
}
productFile << "6. Exit" << endl;
productFile.close();
}
void askIfDefault()
{
cout << "Do you want to come back to default stock?" << endl;
cout << "1. Yes " << "2. No " << endl;
cin >> defaultPick;
switch (defaultPick)
{
case 1:
for (int i = 0;i < 5;i++)
{
productAmount[i] = 10;
}
saveToFile();
loadFromFile();
break;
case 2:
loadFromFile();
break;
default:
cout << "I don't understand." << endl;
exit(0);
break;
}
}
void productCheck()
{
if (productAmount[productPick - 1] <= 0 || productAmount[productPick - 1] < productBuy)
{
cout << "Unfortunately we have no more " << productName[productPick - 1] << " in stock. Please choose other product from the list below: " << endl;
productAmount[productPick - 1] = 0;
}
else
{
productAmount[productPick - 1] -= productBuy;
}
}
void listOfProducts()
{
cout << "How may I help you?" << endl;
for (int i = 0; i < 5; i++)
{
cout << i + 1 << ". " << productName[i] << ": " << productAmount[i] << endl;
}
cout << "6. Exit" << endl;
}
void order()
{
cin >> productPick;
switch (productPick)
{
case 1:
cout << "How many bottles?" << endl;
cin >> productBuy;
{
productCheck();
saveToFile();
}
break;
case 2:
cout << "How many cartons?" << endl;
cin >> productBuy;
{
productCheck();
saveToFile();
}
break;
case 3:
cout << "How many multi-packs?" << endl;
cin >> productBuy;
{
productCheck();
saveToFile();
}
break;
case 4:
cout << "How many portions?" << endl;
cin >> productBuy;
{
productCheck();
saveToFile();
}
break;
case 5:
cout << "How many batches?" << endl;
cin >> productBuy;
{
productCheck();
saveToFile();
}
break;
case 6:
cout << "See you soon!" << endl;
saveToFile();
system("pause");
break;
case 666:
cout << "You cannot use the secret magic spells here." << endl;
saveToFile();
exit(0);
break;
default:
cout << "Please pick the existing product: " << endl;
saveToFile();
order();
break;
}
}
int main()
{
askIfDefault();
order();
cout << endl;
while (true && productPick != 6)
{
listOfProducts();
order();
saveToFile();
cout << endl;
}
return 0;
}
Maybe unless declaring one global fsteam productFile, try to declare the it inside each of both functions that are using it: 'loadFromFile()' and 'saveToFile()' respectively. At the beginning of them. It should be fine then.
Let me make a few additional suggestions about your code - because it's a bit difficult to follow:
Choose function names which reflect what the function does - and don't do anything in a function which exceeds what its name indicates. For example, if you wrote a function called ask_whether_to_restock() - that function should ask the question, and perhaps even get the answer , but not actually restock even if the answer was "yes" - nor write anything to files. Even reading information from a file is a bit excessive.
If you need to do more in a function than its name suggests - write another function for the extra work, and yet another function which calls each of the first two and combines what they do. For example, determine_whether_to_restock() could call read_current_stock_state() which reads from a file, and also print_stock_state() and, say, get_user_restocking_choice().
Try to avoid global variables. Prefer passing each function those variables which it needs to use (or references/pointers to them if necessary).
Don't Repeat Yourself (DRI): Instead of your repetitive switch(produtPick) statement - try writing something using the following:
cout << "How many " << unit_name_plural[productPick] << "?" << endl;
with an additional array of strings with "bottles", "cans", "portions" etc.

Menu list with choices

I'm trying to make a choice list in a program and now I'm stuck with what happens when user writes incorrect input.
I've tried doing it with do loop (I've looped switch statement). Also, tried to set variable key to integer and char, but both have problems. Char only takes one character and when you write more than one it starts checking every by itself. Using int I get an infinite loop of menu function when inputting incorrectly.
Also, tried using cin.fail(), which I've found here, in stackoverflow, but it didn't work out.
void menu()
{
if(!isEmpty())
{
showStack();
}
else
{
cout << "stekas tuscias!" << endl;
}
cout << "---------------------------" << endl;
cout << "1. Iterpti i steka (push)" << endl;
cout << "2. Pasalinti is steko (pop)" << endl;
cout << "3. Issaugoti steka" << endl;
cout << "4. Issaugoti steka ir uzdaryti programa" << endl;
cout << "---------------------------" << endl;
cout << "Jusu pasirinkimas: ";
char key;
cin >> key;
switch(key)
{
case '1':
{
cout << "Irasykite reiksme i konsole: ";
int data;
cin >> data;
cout << endl;
push(data);
break;
}
case '2':
{
cout << endl;
pop();
break;
}
case '3':
{
write();
cout << "--------" << endl;
cout << "Stekas issaugotas!" << endl;
cout << "--------" << endl;
menu();
break;
}
case '4':
{
write();
break;
}
default:
{
cout << "Tokio pasirinkimo nera!" << endl;
cout << endl;
key = '\0';
menu();
break;
}
}
}
My whole code if it's needed: https://pastebin.com/Xv1HE0Mh
Use a try-catch-throw block. Use decltype or typeof feature to see if the input is an integer.
I'm sure why cin.fail() or (!cin) isn't working for you. But, you can do this. And, I'm also sure this kind of question exists.
template <class T>
int check (T ch)
{
if (ch >= 'a' && ch <= 'Z') return 0;
else return 1;
}
And, then.
main ()
{
.
.
char c;
cin.get (c); //Note here!!
if (check (c)) {...}
else {...} //You can use goto.
.
}

Function Call in switch statement.

Hey guys I'm trying to work out how to call a function in my code using a switch statement. I have tried to look for many different references but no matter what nothing seems to work if somebody could please put me on the right path that would be a big help. Here's the code:
#include <iostream>
#include <string>
using namespace std;
int playGame(string word);
int main()
{
int choice;
bool menu = true;
do{
cout <<"Please select one of the following options: \n";
cout << "1: Play\n"
"2: Help\n"
"3: Config\n"
"4: Quit\n";
cout << "Enter your selection (1, 2 and 3): ";
cin >> choice;
//*****************************************************************************
// Switch menu to display the menu.
//*****************************************************************************
switch (choice)
{
case 1:
cout << "You have chosen play\n";
int playGame(string word);
break;
case 2:
cout << "You have chosen help\n";
cout << "Here is a description of the game Hangman and how it is played:\nThe word to guess is represented by a row of dashes, giving the number of letters, numbers and category. If the guessing player suggests a letter or number which occurs in the word, the other player writes it in all its correct positions";
break;
case 3:
cout << "You have chosen Quit, Goodbye.";
break;
default:
cout<< "Your selection must be between 1 and 3!\n";
}
}while(choice!=3);
getchar();
getchar();
cout << "You missed " << playGame("programming");
cout << " times to guess the word programming." << endl;
}
int playGame(string word) //returns # of misses
{
//keep track of misses
//guess is incorrect
//repeated guess of same character
//guess is correct
int misses = 0;
int exposed = 0;
string display = word;
for(int i=0; i< display.length(); i++)
display[i] ='*';
while(exposed < word.length()) {
cout << "Miss:" << misses << ":";
cout << "Enter a letter in word ";
cout << display << " : ";
char response;
cin >> response;
bool goodGuess = false;
bool duplicate = false;
for(int i=0 ; i<word.length() ; i++)
if (response == word[i])
if (display[i] == word[i]) {
cout << response << " is already in the word.\n";
duplicate = true;
break;
} else {
display[i] = word[i];
exposed++;
goodGuess = true;
}
if (duplicate)
continue;
if (!goodGuess){
misses ++;
cout << response << " is not in the word.\n";
}
}
cout << "Yes, word was " << word << "." << endl;
return misses;
}
You are not calling playGame function in switch statement,
switch (choice)
{
case 1:
cout << "You have chosen play\n";
//int playGame(string word); // this does not call playGame,
// it re-declare playGame function again
playGame("word"); // this will call playGame with word parameter
//^^^^^^^^^^^^^^^
break;
int playGame(string word);
In your switch statement might be the problem...try:
int misses = playGame(word);
You are trying to return the number of misses from your playGame method so you have to put the return data inside a variable.

how to cin text

How can I get the user to input text instead of numbers in this program.
haw can i get the cin statement to accept text? Do i have to use char?
int main()
{
using namespace std;
int x = 5;
int y = 8;
int z;
cout << "X=" << x << endl;
cout << "Y=" << y << endl;
cout << "Do you want to add these numbers?" << endl;
int a;
cin >> a;
if (a == 1) {
z = add(x, y);
}
if (a == 0) {
cout << "Okay" << endl;
return 0;
}
cout << x << "+" << y << "=" << z << endl;
return 0;
}
---EDIT---
Why won't this work?
int main()
{
using namespace std;
int x = 5;
int y = 8;
int z;
cout << "X = " << x << " Y = " << y << endl;
string text;
cout << "Do you want to add these numbers together?" << endl;
cin >> text;
switch (text) {
case yes:
z = add(x, y);
break;
case no: cout << "Okay" << endl;
default:cout << "Please enter yes or no in lower case letters" << endl;
break;
}
return 0;
}
Thank you everybody!
If you're interested, you can check out the game I made here.
http://pastebin.com/pmCEJU8E
You are helping a young programmer accomplish his dreams.
You can use std::string for that purpose. Remeber that cin reads your text until white space. If you want to read whole line use getline function from the same library.
Since you are concerned with only 1 character response from the user, as in Do you want to add these numbers? might be concatenated by a (Y/N), you should (in my opinion) use getchar() function if you have intentions to read only 1 character. This is how I would do for an error prone 1 character input handling:
bool terminate = false;
char choice;
while(terminate == false){
cout << "X=" << x << endl;
cout << "Y=" << y << endl;
cout << "Do you want to add these numbers?" << endl;
fflush(stdin);
choice = getchar();
switch(choice){
case 'Y':
case 'y':
//do stuff
terminate = true;
break;
case 'N':
case 'n':
//do stuff
terminate = true;
break;
default:
cout << "Wrong input!" << endl;
break;
}
}
As a reply to your edit
That doesn't work because you cannot pass std::string as an argument to the switch. As I told you, you should read just one character for that purpose. If you insist on using strings, do not use switch, rather go for if else blocks by using the string comparator ==.
cin >> text;
if(text == "yes"){
z = add(x, y);
}
else if(text == "no")
{
cout << "Okay" << endl;
}
else
{
cout << "Please enter yes or no in lower case letters" << endl;
}
You can use std::string.
std::string str;
std::cin>>str; //read a string
// to read a whole line
std::getline(stdin, str);