I'm new to C++. I stumbled upon one tutorial problem, and I thought I'd use the few things I have learnt to solve it. I have written the code to an extent but the code exits at a point, and I really can't figure out why. I do not want to go into details about the tutorial question because I actually wish to continue with it based on how I understood it from the start, and I know prospective answerers might want to change that. The code is explanatory, I have just written few lines.
Here comes the code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
double average_each_student() {
cout << "\n>Enter your scores seperated by spaces and terminated with a period\n"
<< ">Note: scores after total number of six will be truncated.\n"
<< endl;
double sum = 0, average = 0;
int user_input, counter = 0;
const double no_of_exams = 6;
while(cin >> user_input) {
++counter;
if(counter < 5) sum += 0.15 * user_input;
else if(counter > 4 && counter < 7) sum += 0.20 * user_input;
}
return sum / no_of_exams;
}
int reg_number() {
cout << "Enter your registration number: " << endl;
int reg_numb;
cin >> reg_numb;
return reg_numb;
}
int main() {
vector<int> reg_num_list;
vector<double> student_average;
reg_num_list.push_back(reg_number());
student_average.push_back(average_each_student());
string answer;
cout << "\n\nIs that all??" << endl;
//everything ends at this point.
//process returns 0
cin >> answer;
cout << answer;
}
The code exits at cout << "\n\nIs that all??" << endl;. The rest part after that is not what I intend doing, but I'm just using that part to understand what's happening around there.
PS: I know there are other ways to improve the whole thing, but I'm writing the code based on my present knowledge and I wish to maintain the idea I'm currently implementing. I would appreciate if that doesn't change for now. I only need to know what I'm not doing right that is making the code end at that point.
The loop inside average_each_student() runs until further input for data fails and std::cin gets into failure state (i.e., it gets std::ios_base::failbit set).
As a result, input in main() immediately fails and the output of what was input just prints the unchanged string. That is, your perception of the program existing prior to the input is actually wrong: it just doesn't wait for input on a stream in fail state. Since your output doesn't add anything recognizable the output appears to do nothing although it actually prints an empty string. You can easily verify this claim by adding something, e.g.
std::cout << "read '" << answer << "'\n";
Whether it is possible to recover from the fail state on the input stream depends on how it failed. If you enter number until you indicate stream termination (using Ctrl-D or Ctrl-Z on the terminal depending on what kind of system you are using), there isn't any way to recover. If you terminate the input entering a non-number, you can use
std::cin.clear();
To clear the stream's failure stated. You might want to ignore entered characters using
std::cin.ignore(); // ignore the next character
or
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// ignore everything up to the end of the line
use cin.clear(); before cin >> answer; That will fix the problem. But you are not controlling the input. it just runs out to cin..
Related
I'm very new to C++. I started teaching myself C++ last week, and up until now, I haven't had any real problems.
I use Microsoft Visual Studio 2017, and I'm having problems with if and else statements. You see, I'm making this very limited calculator. Basically, the program gives you the 4 basic mathematical operations, and you choose which operation you want to use to calculate by entering either 1, 2, 3, or 4. Then, it runs another program which you can then calculate. (e.g.: 2 is for subtraction, if you enter 2, it will run the subtraction calculator)
Here's the code for the program.
#include "stdafx.h"
#include "iostream"
using namespace std;
int main(){
int add = 1;
int sub = 2;
int mul = 3;
int div = 4;
cout << "Extremely Limited C++ Calculator: Enter a number between one and
four to start calculating and press enter."
<< '\n'
<< "LEGEND"
<< '\n' << "1 = Addition"
<< '\n' << "2 = Subtraction"
<< "\n" << "3 = Multiplication"
<< '\n' << "4 = Division"
<< '\n' << "Operation: ";
if (cin >> add) {
system("start C:\\CalculatorApps\\addition.exe");
return 0;
}
if (cin >> sub) {
system("start C:\\CalculatorApps\\subtraction.exe");
return 0;
}
if (cin >> mul) {
system("start C:\\CalculatorApps\\multiplication.exe");
return 0;
}
if (cin >> div) {
system("start C:\\CalculatorApps\\division.exe");
return 0;
}
}
So I have the addition.exe and subtraction.exe done, but the problem is that no matter what number I enter, it will always run addition.exe. In the subtraction calculator, I experimented having the user choose if they wanted to subtract more than 2 numbers, but that also didn't end up working because it was ignoring if statements. I also at one point had an else statement on both the subtraction calculator and the main program that takes you to the calculators that displayed text reading that the number they entered was not a valid choice and to enter a valid choice, but even that was ignored by the program. Now, maybe I didn't look hard enough on the internet, but I couldn't find one that helped me out. If you know the answer, please tell me but in words that I can understand (I am new after all), or please link me to another question that has been answered that will solve my question.
Thank you in advanced!
cin is an object of class istream that represents the standard input stream. It corresponds to the cstdio stream stdin. The operator >>overload for streams return a reference to the same stream. The stream itself can be evaluated in a boolean condition to true or false through a conversion operator.
cin provides formatted stream extraction. The operation cin >> x;
where "x" is an int will fail if a non-numeric value is entered. So:
if(cin>>x)
will return false if you enter a letter rather than a digit.
As you are always entering a digit, your first statement if(cin>>sum) is always true. So, your other statements are skipped.
So I'm working on some code for a class. Yes I know the input validation I'm trying to work out is inefficient and the program is unfinished. I don't need the rest of it to work. Here's the code.
/*Write a program that allows the user to enter a payroll code.
The program should search for the payroll code in the file and then display the appropriate salary.
If the payroll code is not in the file, the program should display an appropriate message.
Use a sentinel value to end the program.*/
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main(){
int code;
ifstream PayrollFile;
int FCode;
int Salary;
char Trash;
string line;
string lineTwo;
int NumOfCodes=0;
int Subscript=0;
cout << "everything is starting";
PayrollFile.open("/Users/fnord/Desktop/Payroll.txt");
do{
lineTwo=line;
PayrollFile >> line;
NumOfCodes++;
}
while (line!=lineTwo);
PayrollFile.close();
PayrollFile.open("/Users/fnord/Desktop/Payroll.txt");
int ListOfPayrollCodes[NumOfCodes-1];
while (Subscript<NumOfCodes){
while (PayrollFile >> FCode >> Trash >> Salary) {
cout << FCode;
ListOfPayrollCodes[Subscript]=FCode;
Subscript++;
}
}
PayrollFile.close();
PayrollFile.open("/Users/fnord/Desktop/Payroll.txt");
cout << "please enter the payroll code";
cin >> code;
while (PayrollFile >> FCode >> Trash >> Salary) {
if (code==FCode) {
cout << "The salary is " << Salary << endl;
}
}
PayrollFile.close();
}
The thing I'm confused about is the fact that the compiler never seems to reach this line:
cout << "everything is starting";
As far as I can tell, there is nothing before this line that should stop the program from outputting "everything is starting" but "everything is starting" never shows up in the output.
The code builds and begins running but never stops and fails to output anything. My teacher couldn't figure this out either.
I'm running OSX10.9 and using XCode for my compiler. I've tried other compilers with the same results.
Thanks!
In these loops:
while (Subscript<NumOfCodes){
while (PayrollFile >> FCode >> Trash >> Salary) {
cout << FCode;
ListOfPayrollCodes[Subscript]=FCode;
Subscript++;
}
}
If extraction fails, PayrollFile starts converting to false, and there's no longer any way for Subscript to increase. So the outer loop never terminates.
Instead use:
while ((Subscript<NumOfCodes) && (PayrollFile >> FCode >> Trash >> Salary)) {
cout << FCode;
ListOfPayrollCodes[Subscript]=FCode;
Subscript++;
}
For your printf-debugging needs, when using cout, also use std::flush or std::endl. Otherwise the output will be buffered, and not help you learn where your program got stuck. (For actually writing out large quantities of data, you'll want to avoid flushing any more than necessary, because it kills performance.)
Use breakpoints. when you started to debug check if they are still red or turned white. if turned white you can see a note there about the situation. if its red and you cant reach it means its never getting there.
cout is a buffered stream; to force the output you should
using endl manipulator;
usinf flush() method
int ListOfPayrollCodes[NumOfCodes-1]; - // This line should not compile.You're using a variable to declare the size of an array . This is supposed to be a constant.
I'm not sure how you compile this code. Please fix a constant and see, how it sounds. I hardcoded it and commented the Numcodes increment line and I could print it.
Update: Ok, Looks like you're saying the compiler does not reach this line. That means, the code does not compile. The reason is above.
I understand that you want an array of size ListOfPayrollCodes. Use dynamic allocation as opposed to static allocation, it will work fine.
When it comes to creating a program based on a set of instructions, I do pretty well in designing the pseudo-code, implementing the actual code. What I feel like I lack is checking for users' input (whether it's valid or invalid). As I practiced programming, I created my own way for checking for validating users' input. But the code is lengthy and I feel like it's insufficient (I'll explain why). I wanted to know if there is a better way to check for users' input. And how do other programmers implement their code.
This is how I validate users' input:
if(cin.fail()) {
cout << "Invalid Input" << endl;
cout << "Now Exiting..." << endl;
return;
}
// I didn't know how to skip a line while in code
while(input < 0) {
cout << "Invalid Input" << endl;
cout << "Enter radius: " << endl;
cin >> input;
if(cin.fail()) {
cout << "Error: Invalid Input" << endl;
cout << "Now Exiting..." << endl;
return;
}
}
The reason why I exit out when cin fails to store the value into the variable separately (line 1 - 5, line 11 -15) is because if I add the cin.fail() to the while condition and attempt to input a letter, it begins a infinite loop. I did a little research and I saw you have to cin.sync(), then cin.clear(). But I still get the infinite loop.
Here is the code:
do {
cin.sync()
cin.clear();
cout << "Enter radius: ";
cin >> input;
} while(input < 0 || cin.fail());
If I'm doing something wrong, it would very helpful to see better ways to validate user's input.
I would not recommend using std::cin, since it leaves all remaining user input after the first found instance of whitespace in the input buffer. This will create problems unless you remove the remaining characters using cin.ignore(). It is generally seen as better practice to use getline(), which will get all the characters up to the newline character. If you do choose to use std::cin, you will need to use cin.ignore() to remove the remaining characters, and cin.clear() to reset cin's fail bit so the while conditional will work properly the next time through the loop.
Below is how I would solve the problem. It uses getline() to get all the characters, and a stringstream to convert the string to an int. Notice you need to clear the stringstream's fail bit just like with cin to make sure the conditional works correctly when you do ss >> result in the while conditional.
std::cout << "Enter radius: ";
getline(std::cin, input);
std::stringstream ss(input);
while(!(ss >> result)) {
std::cout << "Invalid Input" << std::endl;
std::cout << "Enter radius: ";
getline(std::cin, input);
ss.clear();
ss << input;
}
Below I'll also include some code to solve the problem using std:cin. I still recommend using getline() though. Note: std::numeric_limits::max() is used to specify how many characters to remove from the input buffer. Using this instead of your own arbitrary number is a better practice, since you can't know for certain how many characters the user will enter. cin.ignore() will remove all the characters up to the given number or until it reaches an instance of the character provided as its second parameter, which in this case is newline ('\n').
std::cout << "Enter radius: ";
std::cin >> result;
while(std::cin.fail()) {
std::cout << "Invalid Input" << std::endl;
std::cout << "Enter radius: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin >> result;
}
The problem of input validation is an easy form of parsing.
There are language-classes (in the field of formal language theory) that express the complexity of your input. Those classes are called regular, context-free, and turing-complete.
You have to consider all your possible inputs, that your program might receive and decide whether your program should accept them or not. The language classes help you to decide what kind of input validation you need.
if the language is regular (as it is in your case) you can use regular expressions to validate the input.
A context-free language for example would be a math-formula. You cannot count the number of parentheses with a regular expression. Therefore it is impossible to check ((a+b) * (c+d)) has the right amount of parentheses with a regular expression.
Up to now these are hints on what you should be doing, when programming comes more naturally to you.
For the sake of simplicity well do a very constrained regular expression like parsing by hand.
what you actually want to do in pseudo code:
do {
std::cout << "Please enter radius: ";
line = read_a_line_from(std::cin) // separated by '\n' the newline
if (false == really_read_a_line(line)) {
/* error handling for std::cin, dealing with i.e.: the fail bit */
break; /* exit the loop */
}
if (line == "exit") { // give the user an explicit exit, to quit gracefully
exit(SUCCESS); /* exit the program */
}
if (false == is_a_number(line)) {
/* we read something that isn't a number */
/* we should tell the user he should do as we asked */
continue; /* jump back to the beginning of the loop */
}
unsigned num = convert_number(line);
unsigned area = calculate_area(num); /* do something with your input */
} while (true);
exit(FAILURE);
The code here is not too specific on purpose that you see what you could be doing in places, still leaving out the actual implementation (for your exercise). Please note that a simple way of checking whether a line is actually a number is by converting. However not all things to parse should be checked for validity and processed at the same time.
See Also (especially the examples):
http://en.cppreference.com/w/cpp/string/basic_string/getline
http://en.cppreference.com/w/cpp/string/basic_string/stol
how to check if given c++ string or char* contains only digits?
do {
cin.sync()
cin.clear();
cout << "Enter radius: ";
cin >> input;
} while(input < 0 && cin.fail());
I need to read an unknown length sequence of integers and then i need to find the longest monotonic subsequence in it. The sequence ends with EOF sign and its elements are to separated with spaces.
I'm not really bothering the algorytm of finding the subsequence now I'd like to make sure that I'm reading elements of the sequence in a right way. Below is a code which is supposed to do the job but there's a bug which I don't get right now.
#include <iostream>
using namespace std;
int main()
{
int sum=0;
int a=0;
cout << "Give me a number: ";
// while (!fin.eof()) {
while (cin >> a) {
cin >> a;
sum +=a;
cout << "Sum is: " <<sum << endl;
/* Thats the place where whole magic is supposed to happen.
I'm really confused however, because after entering i.e. 2 3 4 2 4
and pressing <Enter> five times shows an answer "The sum is <proper sum>"
and the answer "The final sum is: ... " doesn't show at all.
*/
}
cout << "final sum is : " << sum;
cout << "Hello world!" << endl;
return 0;
}
I'll be very grateful if anyone could answer my questions and explain if and where I'm wrong.
I'll appreciate any help!
Well, for one, you seem to be checking on the state of fin, but you never open that file and you never read from it. I'm guessing you meant to use std::cin everywhere, or fin everywhere; I'll stick to std::cin, but fin would work the same way.
The problem is that you first check for end-of-file and then read and use the data. This means that if the read failed, you aren't told about this. Instead of
while (std::cin) {
std::cin >> a;
sum += a;
}
use
while (std::cin >> a) {
sum += a;
}
This will still perform the check, but after the read, meaning that if the read failed, you don't go into the body of the loop, and don't use the (nonsense) data.
The fin case looks much the same:
std::ifstream fin("mydata.txt");
while (fin >> a) {
sum += a;
}
Note that there's no need to explicitly check for whether you reached the end of the file; checking the state of the stream will catch that error, as well as any errors due to being unable to parse a number. If instead we did
while (fin >> a, !fin.eof())
this would correctly handle the case where you read the whole file, but loop infinitely if it contained something other than a number.
First, decide whether you're reading from the file (fin) or the program's input (std::cin). Currently, you're reading from one and checking the other for eof.
If you're reading from the file, then you'll need to open it. Otherwise, remove fin to avoid confusion.
Then you should check for eof (and other error conditions) after attempting to read, and before using the result:
while (std::cin >> a) { // or `fin`, if that's where you're reading from
// your code using 'a' here
}
More specifically, I want to make sure this type is a double (or int/float). I have searched near and far and found pretty much zero non-rigorous solutions. I want to only use code that I can fully understand, being a complete beginner at C++.
In Java, I can simply do something like this:
ArrayList<Double> data = new ArrayList<Double>();
Scanner in = new Scanner(System.in);
while (in.hasNextDouble()) {
double x = in.nextDouble();
data.add(x);
n += 1;
sum += x;
}
double average = sum / n;
C++ is clearly a different story. Here's what I tried:
vector<double> data;
while (looping)
{
cin >> x;
if (typeid(x) != typeid(float) && typeid(x) != typeid(double) &&
typeid(x) != typeid(int))
{looping = false; break;}
data.push_back(x);
n += 1;
sum += x;
}
double average = sum / n;
This doesn't work. The loop keeps going as doubles are entered, but once I enter something that's not a double the code simply stops and doesn't advance onward. I'm pretty crestfallen. Any suggestions?
User doesn't "enter a variable". She enters a string. And operator >> when supplied with a float variable tries to interpret this string as a textual representation of a floating-point number.
It may or may not succeed: in Java, failure would cause nextDouble() to throw an exception. In C++, stream operations don't throw; instead failure means that cin.good() will start to return false.
float x;
cin >> x;
while (cin.good())
{
data.push_back(x);
n += 1;
sum += x;
cin >> x;
}
if x is declared as double, your if condition would fail and hence the while loop is broken
You have several solutions here. I will post 2 of them. The first solution needs c++11 standard due to stod function. You can do this passing -std=c++11 flag to gcc or clang++. Microsoft compiler enables c++11 by default.
Solution 1. It consists of reading in a string all the time through cin >> input_string and using standard c++11 function stod. stod stands for string to double. If stod fails to parse a double, it will throw an std::invalid_argument exception.
This solution would be like this:
#include <iostream>
#include <vector>
#include <numeric>
#include <string>
#include <stdexcept>
using namespace std;
int main() {
vector<double> vec;
string input;
try {
while (getline(cin, input)) {
vec.push_back(stod(input));
}
}
catch (std::invalid_argument &) {
cout << "Invalid argument caught\n";
//Failed to parse a double
}
//If pressed Ctrl+D (in linux, which sends EOF), failbit and eofbit are set
//If it is through invalid_argument the way the loop was exit, then,
//eof and failbit are not set and cin can be used without clearing.
double average = accumulate(vec.begin(), vec.end(), 0.0)/vec.size();
cout << "EOF: " << cin.eof() << endl;
cout << "Fail: " << cin.fail() << endl;
//Clean eof and failbit to be able to use cin again
cin.clear();
cout << "EOF after cleaning: " << cin.eof() << endl;
cout << "Fail after cleaning: " << cin.fail() << endl;
cout << average << endl;
}
EDIT: I tested and when you put more than one number per line it will just get the first one without throwing std::invalid_argument. It will throw an std::invalid_argument only when you start a line when the line starts with a non-double. This is because the stod function behaves like this: stod reference.
Note that this solution only allows to read one double per line.
Solution 2. Read using cin >> input_double directly. This can fail. Please note that iostreams don't use exceptios by default in c++. You can activate them with the api, but I don't recommend you to do it because you can manage all error handling locally.
You can read any number of doubles separated by any space characters:
#include <iostream>
#include <vector>
#include <numeric>
#include <limits>
using namespace std;
int main() {
double x = 0.0;
vector<double> data;
//cin will fail to read the first non-double in the input.
//You can input as many doubles as you wish. Spaces will
//be ignored. At the first non-double, cin will fail to read
//and will exit the loop, setting istream::failbit.
//Alternatively, you can send EOF (Linux is Ctrl+D) and the loop also will finish.
while (cin >> x) {
data.push_back(x);
}
double average = accumulate(data.begin(), data.end(), 0.0)/data.size();
//If you wanted to use again cin, you should:
//1. Clear failbit. You can do like this:
cin.clear();
//2. Cleaning the remaining input. Will stop when finding end of line.
string rubbish;
geline(cin, rubbish);
//cin is usable here again if you need it and with the input clean already.
cout << average << '\n';
}
You can give something like this in the input, in one line:
1 2.4 -38.7 5.8 28.9 hello.
What will happen? The loop will consume until 28.9, stopping at hello. After that, failbit is set. We clean failbit to be able to continue reading until the end of the line. Since hello is considered "rubbish" because we wanted to read doubles, we clean it with a getline and we can use cin again without trouble.