C++ while loop reading input - c++

I submitted this program and it works perfectly, but my teacher says that there is something wrong with my while loop even though I am getting the correct answers. Any tips or help?
What happens in the while loop when the end of file is reached and the read on line 43 becomes invalid? The way your program is structured you do not see the problem, but it is there. Should restructure the while loop to account for this.
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream inputfile;
char choice;
int NumberOfIntegers = 0,
SumOfIntegers = 0,
Average = 0 ,
LargestValue,
SmallestValue,
integer;
inputfile.open("random.txt");
if(!inputfile)
{
cout << "the file could not be open" << endl;
}
inputfile >> integer;
//initialize smallest and largest
SmallestValue = integer;
LargestValue = integer;
while(inputfile)
{
NumberOfIntegers++;
SumOfIntegers = SumOfIntegers + integer;
inputfile >> integer;
if( integer > LargestValue || integer < SmallestValue)
{
if ( integer > LargestValue)
LargestValue = integer;
else
SmallestValue = integer;
}
}
if(NumberOfIntegers > 0 )
{
Average = SumOfIntegers / NumberOfIntegers;
}
//closing input file
inputfile.close();
do
{
//Display Menu
cout << "Make a selection from the list" << endl;
cout << "A. Get the largest Value" << endl;
cout << "B. Get the smallest Value" << endl;
cout << "C. Get the sum of the values" << endl;
cout << "D. Get the average of the values" << endl;
cout << "E. Get the number of values entered" << endl;
cout << "F. End this program" << endl << endl;
cout << "Enter your choice --> ";
cin >> choice;
cout << endl;
switch (choice)
{
case 'a':
case 'A': cout << "The largest value is " << LargestValue << endl;
break;
case 'b':
case 'B': cout << "The smallest value is " << SmallestValue << endl;
break;
case 'c':
case 'C': cout << "The sum of the values entered is " << SumOfIntegers << endl;
break;
case 'd':
case 'D': cout << "The average of the values entered is " << Average << endl;
break;
case 'e':
case 'E': cout << "The number of values entered is " << NumberOfIntegers << endl;
break;
case 'f':
case 'F': cout << "Program ending" << endl << endl;
cin.ignore();
cout << "\n\nPress Enter to end --> ";
cin.ignore();
return 0;
default:
cout << choice << " is an invalid value. " << endl;
}
cout << endl;
} while( choice != 'f' || choice != 'F');
return 0;
}

The "issue" I see is that you do not check the bool value of the stream after you read and before you process. To do this, you should put the read as the condition to the while loop.
if( ! inputfile >> integer )
{
// error code (no integer in file)
exit(0);
}
LargestValue = integer;
SmallestValue = integer;
NumberOfIntegers++;
SumOfIntegers = SumOfIntegers + integer;
while( inputfile >> integer )
{
NumberOfIntegers++;
SumOfIntegers = SumOfIntegers + integer;
//inputfile >> integer;
if( integer > LargestValue || integer < SmallestValue)
{
if ( integer > LargestValue)
LargestValue = integer;
else
SmallestValue = integer;
}
}
In this scenario, the result should be the same with your program because if the inputfile >> integer failed, I believe integer keeps the same value as before so it would not effect LargestValue or SmallestValue. Then you check the stream so NumberOfIntegers and SumOfIntegers won't be updated, which is correct. The only time your program would give undefined results (for LargestValue and SmallestValue) is if the file doesn't start with an integer and simply by checking the first read and handling it appropriately this will be fixed.

Related

There is a problem in this C++ program (Decimal to Bin,Oct and Hex converter)

What I am trying to do is, create a program which converts Decimal values into other Number Systems(Binary, Octal and Hexa-Decimal) and shows the original Decimal value as-well-as the converted value.
It runs fine in first run but when the outer for loop runs the program again, the previous values which were printed by inner for loop are also printed right after its output in the next run. Any Suggestions?
Try running it, and see it yourself...
source code:-
#include <iostream>
using namespace std;
int main()
{
cout << "This program will help in Decimal to other radix conversion :-" << endl;
const int i = 10;
//Declaring array to store remainder values...
int RemArray [i] = {0};
//Declaring variable to use it as index of RemArray[]...
short int R=0;
char Exit = '\0';
//To iterate the whole program...
for (;;)
{
cout << "Enter Decimal digit: ";
long long int Decimal = 0;
cin >> Decimal;
long long int TempDecimal = Decimal;
cout << "Enter Desired Radix: ";
int Radix = 0;
cin >> Radix;
long long int Quotient = 1;
long long int Remainder = 0;
cout << endl;
while (Quotient != 0)
{
//Formula for conversion...
Quotient = Decimal / Radix;
Remainder = Decimal % Radix;
cout << "Quotient: " << Quotient << " <-> " << "Remainder: ";
//Using switch case so that hexa-decimal values could also be printed...
switch (Remainder)
{
case 10:
cout << "A" << endl;
break;
case 11:
cout << "B" << endl;
break;
case 12:
cout << "C" << endl;
break;
case 13:
cout << "D" << endl;
break;
case 14:
cout << "E" << endl;
break;
case 15:
cout << "F" << endl;
break;
default:
cout << Remainder << endl;
break;
}
Decimal = Quotient;
//Using array to store remainder values...to print them all together
RemArray [R] = Remainder;
R++;
}
cout << endl;
cout << "Therefore, " << TempDecimal << " = ";
/*Output the result...But When the program runs again, values obtained here remains
on the screen and prints them too on the next run of this loop...*/
for (int NewR = R-1, z=0; (NewR >= 0) && (z < R); NewR--,z++)
{
switch (RemArray [NewR])
{
case 10:
cout << "A";
break;
case 11:
cout << "B";
break;
case 12:
cout << "C";
break;
case 13:
cout << "D";
break;
case 14:
cout << "E";
break;
case 15:
cout << "F";
break;
default:
cout << RemArray [NewR];
break;
}
}
//Asking user to iterate the program again...
cout << endl << "Want to convert another digit (y/n): ";
cin >> Exit;
cout << endl;
if (Exit == 'n')
{
break;
}
}
cout << "GoodBye !!!" << endl;
return 0;
}

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;
// ...
}

input validation for choosing an item with a char, getting errors with cin.fail

cin is really difficult for me to understand with c++.
I want to choose an item on the menu but I want it to be clean, however I am running into issues with cin.fail.
I realize cin.fail checks the datatype so I should be clear when it comes to other data types.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int number;// define an integer variable called number
float cost;// a floating point variable called cost,
char beverage;// and a character variable called beverage
bool validBeverage;
cout << fixed << showpoint << setprecision(2);
do
{
cout << endl << endl;
cout << "Hot Beverage Menu" << endl << endl;
cout << "A: Coffee $1.00" << endl;
cout << "B: Tea $ .75" << endl;
cout << "C: Hot Chocolate $1.25" << endl;
cout << "D: Cappuccino $2.50" << endl <<endl << endl;
cout << "Enter the beverage A,B,C, or D you desire" << endl;
cout << "Enter E to exit the program" << endl << endl;
do
{
cin >> beverage;// Fill in the code to read in beverage
if (cin.fail)
{
cout << "You have entered an invalid value." << endl
<< "Please enter the letter corresponding to the menu." << endl;
}
} while (cin.fail);
switch(beverage)
{
case 'a': validBeverage = true;
case 'A': validBeverage = true;
case 'b': validBeverage = true;
case 'B': validBeverage = true;
case 'c': validBeverage = true;
case 'C': validBeverage = true;
case 'd': validBeverage = true;
case 'D': validBeverage = true;
break;
default: validBeverage = false;
}// end switch beverage
if (validBeverage == true)
{
do
{
cout << "How many cups would you like?" << endl;
// Fill in the code to read in number
cin >> number;
if (cin.fail() || number <= 0)
{
cout << "You have entered an invalid value." << endl <<
"Please enter an integer greater than 0." << endl;`enter code here`
}
} while (cin.fail() || number <= 0);
}
switch (beverage)// Fill in the code to begin a switch
statement that is controlled by beverage
{
case 'a': (float)cost = number * 1.0;
cout << "The total cost is $ " << cost << endl;
break;
case 'A': (float)cost = number * 1.0;
cout << "The total cost is $ " << cost << endl;
break;
case 'b': (float)cost = number * 0.75;// Fill in the
code to give the case for tea ( $0.75 a cup)
cout << "The total cost is $ " << cost << endl;
break;
case 'B': (float) cost = number * 0.75;// Fill in the
code to give the case for hot chocolate ($1.25 a cup)
cout << "The total cost is $ " << cost << endl;
break;
case 'c': (float)cost = number * 1.25;
cout << "The total cost is $ " << cost << endl;
break;
case 'C': (float)cost = number * 1.25;
cout << "The total cost is $ " << cost << endl;
break;
case 'd': (float)cost = number * 2.50;// Fill in the
code to give the case for cappuccino ($2.50 a cup)
cout << "The total cost is $ " << cost << endl;
break;
case 'D': (float)cost = number * 2.50;// Fill in the
code to give the case for cappuccino ($2.50 a cup)
cout << "The total cost is $ " << cost << endl;
break;
case 'e':
cout << "Please come again." << endl;
break;
case 'E':
cout << " Please come again." << endl;
break;
default:cout << "Invalid Selection."; // Fill in the
code to write a message indicating an invalid selection.
cout << " Try again please" << endl;
}
}while (beverage != 'e' || beverage != 'E'); // Fill in the code to
finish the do-while statement with the condition that beverage does not
equal E or e.
// Fill in the appropriate return statement
return 0;
}
Try using: if(!cin) which checks for data type on input.

C++ Skipping cin statement. going into infinite loop

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?

C++ while loop nested if statment

Hi I am having some trouble getting the correct smallest value and the correct largest value . I know it has to do with the while loop. the rest of the program works great. I found the correct average , sum and number of integers
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream inputfile;
char choice;
int NumberOfIntegers = 0,
SumOfIntegers = 0,
Average = 0 ,
LargestValue,
SmallestValue,
integer;
inputfile.open("random.txt");
if(!inputfile)
{
cout << "the file could not be open" << endl;
}
inputfile >> integer;
//initialize smallest and largest
SmallestValue = integer;
LargestValue = integer;
while(inputfile)
{
NumberOfIntegers++;
SumOfIntegers = SumOfIntegers + integer;
inputfile >> integer;
if( integer >> LargestValue || integer << SmallestValue)
{
if ( integer >> LargestValue)
LargestValue = integer;
else
SmallestValue = integer;
}
}
if(NumberOfIntegers > 0 )
{
Average = SumOfIntegers / NumberOfIntegers;
}
do
{
//Display Menu
cout << "Make a selection from the list" << endl;
cout << "A. Get the largest Value" << endl;
cout << "B. Get the smallest Value" << endl;
cout << "C. Get the sum of the values" << endl;
cout << "D. Get the average of the values" << endl;
cout << "E. Get the number of values entered" << endl;
cout << "F. End this program" << endl << endl;
cout << "Enter your choice --> ";
cin >> choice;
cout << endl;
switch (choice)
{
case 'a':
case 'A': cout << "The largest value is " << LargestValue << endl;
break;
case 'b':
case 'B': cout << "The smallest value is " << SmallestValue << endl;
break;
case 'c':
case 'C': cout << "The sum of the values entered is " << SumOfIntegers << endl;
break;
case 'd':
case 'D': cout << "The average of the values entered is " << Average << endl;
break;
case 'e':
case 'E': cout << "The number of values entered is " << NumberOfIntegers << endl;
break;
case 'f':
case 'F': cout << "Program is now ending" << endl;
return 1;
break;
default:
cout << choice << " is an invalid value. " << endl;
}
cout << endl;
} while( choice != 'f' || choice != 'F');
return 0;
}
integer >> LargestValue
Presumably that should be integer > LargestValue. >> is a shift operation, not a comparison. The same applies to <<.
You should also make sure you initialize LargestValue to something small and SmallestValue to something large. Otherwise you may miss outliers in your data.
Make your 'largest' & 'smallest' logic blocks separate -- there's no reason or correctness in joining them.
Note that for a list with only one item, that value will be both smallest and largest. Not only is it more complicated, it is incorrect to make these conditions mutually exclusive.
Use better names for your variables. Use "item" or "value" for what you are currently reading, everything is an integer so that is effectively meaningless. I prefer a lowercase first letter for variables.. been working in Java for a while :)
Avoid declaring variables before/ or outside of where they have meaningful value too, where possible.
int value;
inputfile >> value;
if (value > largestValue) {
largestValue = value;
}
if (value > smallestValue) {
smallestValue = value;
}
Also, you need to either detect 'first' or initialize smallest/largest to +/- MaxInt to ensure that the first value will be taken up.