How to simply validate correctly in c++? [duplicate] - c++

This question already has answers here:
How to check if the input number integer not float?
(3 answers)
How to check if the input is a valid integer without any other chars?
(7 answers)
How to test whether stringstream operator>> has parsed a bad type and skip it
(5 answers)
Closed 4 years ago.
I am new to c++ - and I am having trouble to validate user that the input must be a integer, and I just want the basic - simpler way, for me to understand. (Just basic way) to validate the input of the user How can I make it to work prior to my code below. Thank you for you're help and you're time. For example: if I get prompt to enter positive number and Input the letter x that means it will show "Invalid entry".. thank you!
Here is my code:
Updated
if (cin >> x && x < 0) {
} else {
cout << "Invalid entry, Try again." << endl;
cin.clear();
while (cin.get() != '\n');
}
#include <iostream>
#include <fstream> // for file stream.
using namespace std;
int main() {
// Variables
int x, reversedNumber, remainder;
// Creating String variables and setting them to empty string.
string even = "", odd = "";
// Creating a file.
ofstream out;
out.open("outDataFile.txt");
// creating a character variable
// for the user input if they want to use the program again.
char ch;
do {
// Even number.
even = "";
// Odd number.
odd = "";
// Reversed number
reversedNumber = 0;
// Prompt the user to enter a positive integer.
cout << "\nEnter a positive integer and press <Enter> ";
// Validate user input.
while (cin >> x || x < 1) {
// Clear out the cin results.
cin.clear();
// Display user that it is not a positive integer.
cout << "Invalid entry, Try again. ";
}
// Display Results to the screen
cout << "the original number is " << x << "\n";
// Display results in the text file.
out << "the original number is " << x << "\n";
// Display number reversed.
cout << "the number reversed ";
// Display number reversed in text file.
out << "the number reversed ";
//Reversing the integer.
while (x != 0) {
remainder = x % 10;
reversedNumber = reversedNumber * 10 + remainder;
// Display on screen
cout << remainder << " ";
// Display in text file.
out << remainder << " ";
x /= 10;
}
// Display the results on screen and in the text file.
cout << "\n";
out << "\n";
// Reading the reverse numbers result.
while (reversedNumber != 0) {
remainder = reversedNumber % 10;
// Checking if the number is even or odd.
if (remainder % 2 == 0) {
// even = even * 10 + remainder;
} else {
// odd = odd * 10 + remainder;
}
reversedNumber /= 10;
}
//Displaying the even numbers.
if (even != "") {
cout << "the even digits are " << even << "\n";
out << "the even digits are " << even << "\n";
}
// If it is not even then display..
else {
cout << "There are no even digits \n";
out << "There are no even digits \n";
}
//Display the odd results.
if (odd != "") {
cout << "the odd digits are " << odd << "\n";
out << "the odd digits are " << odd << "\n";
}
// If its not odd then display.
else {
cout << "There are no odd digits \n";
out << "There are no odd digits \n";
}
// just a divider to divide the results inside text file.
out << "----------------- \n";
// Prompt the user if they want to use the program again.
cout << "\nDo you like to continue/repeat? (Y/N):";
// get the input from user.
cin >> ch;
if ((ch == 'Y') || (ch == 'y')) {
} else {
cout << "\nGoodbye!" << endl;
}
} while (ch == 'y' || ch == 'Y');
// close the text file.
out.close();
return 0;
}

You could read a string from cin and check each character to make sure that when passed to isdigit() it returns true.
std::string x;
std::cin >> x;
for(char c : x){ //for each char c in string x
if(!isdigit(c)) //Invalid
}

Related

To confirm only 1 and 0 exist in the Binary

I wanted to use only 1 and 0 for the binary. But instead the answer keep giving me the 2nd option with whatever number I typed. I had tried where did I programmed wrongly but unfortunately I still can't find it. So I hoped that I could get some help here.
#include<iostream>
#include<cmath>
using namespace std;
int DualzahlZuDezimal(long long n)
{
int dez = 0;
int i = 0, rem;
while (n != 0)
{
rem = n % 10;
n /= 10;
dez += rem * pow(2, i);
++i;
}
return dez;
}
string a;
int main()
{
long long n;
int dez;
cout << "Test Ein- und Ausgabe : \n";
cout << "----------------------- \n";
cout << "Eingabe einer Dualzahl : ";
cin >> n;
if ((n == '1') && (n == '0'))
{
cout << "Dual : " << n << endl;
cout << "Dezimal : " << DualzahlZuDezimal(n) << endl;
cout << "cin ok ? : ja-ok" << endl;
return 0;
}
else
{
cout << "Dual : 0" << endl;
cout << "Dezimal : 0" << endl;
cout << "cin ok ? : nein-nicht ok" << endl;
return 0;
}
}
If I understand this right, you want the user to enter a binary number, like 10001101001, and you will show the decimal equivalent (1129 in this case).
There are 2 general ways to do that yourself:
You can read the value as a number, as you do, and then apply your conversion
process, except that you check that rem is either 0 (in which case you do
nothing), or 1 (in which case you add the power of 2). If it's another value,
you report the error, and return 0.
You can read the value as a std::string instead. Then you can use
std::find_first_not_of()
to check for contents other than 0 or 1:
if (n.find_first_not_of("01") != string::npos) { /* complain */ }
but then you need to do the conversion based on characters.
But the best approach is not to reinvent the wheel and instead let the standard library handle it for you via stol():
#include <cstddef>
#include <iostream>
#include <string>
using namespace std;
int
main()
{
string text;
cout << "Enter a binary number: " << flush;
cin >> text;
size_t endpos = 0;
long decimal_number = stol(text, &endpos, 2); // base 2 == binary
if (endpos != text.size()) {
cerr << "'" << text << "' is not a valid binary number!" << endl;
return 1;
}
else {
cerr << "binary number: " << text << endl;
cerr << "decimal number: " << decimal_number << endl;
return 0;
}
}
Keep in mind that input from the console is text. If you need to check that the text matches a particular format (in this case, consists entirely of 1's and 0's), the simplest approach is to look at that text:
std::string input;
std::cin >> input;
bool input_is_valid = true;
for (int i = 0; input_is_valid && i < input.length(); ++i) {
if (input[i] != '0' && input[i] != '1')
input_is_valid = false;
}
then, if the input is valid, convert the text to a numeric value:
long long n = std::stoll(input);

How do I my Program to stop Replicating if wrong input

My program will repeat output: "You are currently on the 2 floor out of 5
The sum of the codes is: 7 and the product of the codes is: 12
Try again before he catches onto you!"
Based on how many wrong characters are added how can I fix this? I have inserted the cin.clear and cin.ignore but it will repeat the part above.
i.e. if I type wasds it will repeat 5x. Any other notes are also appreciated.
#include <iostream>
#include <ctime>
using namespace std;
int PlayerLevel = 0;
int MaxLevel = 5;
bool GamePlay ()
{
srand(time(NULL));
int PlayerGuessA, PlayerGuessB, PlayerGuessC;
int CodeA = rand() % PlayerLevel + PlayerLevel;
int CodeB = rand() % PlayerLevel + PlayerLevel;
int CodeC = rand() % PlayerLevel + PlayerLevel;
int SumofCodes = CodeA + CodeB + CodeC;
int ProductofCodes = CodeA * CodeB * CodeC;
cout << "You are currently on the " << PlayerLevel << " floor out of 5" << endl;
cout << "The sum of the codes is: " << SumofCodes << " and the product of the codes is: " << ProductofCodes << endl;
cin >> PlayerGuessA >> PlayerGuessB >> PlayerGuessC;
int PlayerProduct = PlayerGuessA * PlayerGuessB * PlayerGuessC;
int PlayerSum = PlayerGuessA + PlayerGuessB + PlayerGuessC;
if (PlayerProduct == ProductofCodes && SumofCodes == PlayerSum) {
cout << "Great Job you got this!!!\n" << endl;
++PlayerLevel;
return true;
}
else
{
cout << "Try again before he catches onto you!\n" << endl;
return false;
}
}
int GameStart()
{
string Introduction = "Welcome to your worst nightmare. You are trapped in a murderer's house. You are on the 5th floor and need to get to the first floor to escape.\n";
string Instructions = "He has each door locked behind a security system that requires a 3 number code to disarm it.\nEnter the codes and move foward. Each level will the code will be harder to figure out.\n";
string PlayerStart;
cout << Introduction << endl;
cout << Instructions << endl;
cout << "Would you like to escape? Yes or No" << endl;
cin >> PlayerStart;
if (!(PlayerStart != "Yes" && PlayerStart != "yes")) {
++PlayerLevel;
}
return 0;
}
int main ()
{
if (PlayerLevel == 0) {
GameStart();
}
while (PlayerLevel <= MaxLevel)
{
bool bLevelComplete = GamePlay();
cin.clear ();
cin.ignore();
}
cout << "You Made it out! Now run before he finds out!" << endl;
return 0;
}
When the type of the input doesn't match the type of the variable that it is being extracted to, cin sets the fail bit. Once this happens, all subsequent reads fail until the stream is reset. The offending characters are still left in the buffer, so that needs to be cleared out as well.
Your usage of cin.clear() and cin.ignore() meant that the fail bit was getting reset, but only one offending character was being removed (cin.ignore() ignores one character by default). This is why you saw the output repeating x times for x erroneous characters.
You could do something like this:
while (PlayerLevel <= MaxLevel)
{
bool bLevelComplete = GamePlay();
if (cin.fail())
{
//Input extraction failed, need to reset stream and clear buffer until newline
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
}
}

Sum and Average with Dynamic Array

I'll preface this by noting that I'm very new to C++ and programming in general so if I'm doing something improperly or writing code in an odd way, it's because i've only learned so much so far.
Anyways, I was given an assignment to write a program that first
Reads integers from a file of the user's choice
Outputs the sum and average of all the numbers greater than or equal to zero ,
Outputs the sum and average of all the numbers less than zero
Outputs the sum and average of all the numbers, whether positive, negative, or zero.
Then finally asks the user if they'd like to choose another file to run on again
The only catch is that I have to use a dynamic array within the code, I'm assuming in order to allow the file to hold any amount of integers.
So far, I have everything except for the implementation of the dynamic array. The code is currently programmed to only accept 10 integers (as there are no arrays in the code yet).
Here's my code:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main() {
//Variables
string inFile;
int numbers, i = 0;
double avg, neg_avg, total_sum, total_avg, sum = 0, neg_sum = 0;;
double count = 0, neg_count = 0, pos_count = 0;
char answer;
do
{
//Input Question
cout << "Enter the file name.\n";
cin >> inFile; // Input from User
ifstream fin; // Open File
fin.open(inFile);
if (fin.fail()) // Check to see if file opens properly
{
cout << "An error occurred while attempting to open the file.\n";
exit(1);
}
while (count < 10)
{
fin >> numbers;
if (numbers >= i)
{
sum += numbers;
count += 1;
pos_count += 1;
}
if (numbers < i)
{
neg_sum = neg_sum + numbers;
count = count + 1;
neg_count = neg_count + 1;
}
}
//Calculations
avg = sum / pos_count;
neg_avg = neg_sum / neg_count;
total_sum = sum + neg_sum;
total_avg = total_sum / 10.0;
//OUTPUT
cout << "The sum of all positive numbers is: " << sum << endl;
cout << "The average of all positive numbers is: " << setprecision(3) << avg << endl;
cout << "The sum of all negative numbers is: " << neg_sum << endl;
cout << "The average of all negative numbers is: " << setprecision(3) << neg_avg << endl;
cout << "The sum of all numbers is: " << total_sum << endl;
cout << "The average of all numbers is: " << setprecision(3) << total_avg << endl;
cout << "-------------------------------------------------" << endl;
cout << "Want us to read another file?\n";
cout << "Enter 'Y' or 'y' for yes, any other character for no." << endl;
cin >> answer;
} while ((answer == 'y') || (answer == 'Y'));
return 0;
}
Any help would be greatly appreciated!
Thanks in advance
UPDATE:
I've gotten this far but when I compile, the program runs continuously.Not sure what I'm doing wrong.
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main() {
//Variables
string file;
int i = 0;
double avg, neg_avg, total_sum, total_avg, sum = 0, neg_sum = 0;;
double neg_count = 0, pos_count = 0, totcount = 0;
char answer;
//Input Question
do
{
cout << "Enter the file name.\n";
cin >> file; // Input from User
ifstream fin; // Open File
fin.open(file);
if (fin.fail()) // Check to see if file opens properly
{
cout << "An error occurred while attempting to open the file.\n";
exit(1);
}
while (!fin.eof())
{
int numbers;
fin >> numbers;
int *dynamicArray;
dynamicArray = new int[numbers];
if (numbers >= i)
{
sum += numbers;
pos_count += 1;
totcount += 1;
}
if (numbers < i)
{
neg_sum = neg_sum + numbers;
neg_count = neg_count + 1;
totcount += 1;
}
//Calculations
avg = sum / pos_count;
neg_avg = neg_sum / neg_count;
total_sum = sum + neg_sum;
total_avg = total_sum / totcount;
//OUTPUT
cout << "The sum of all positive numbers is: " << sum << endl;
cout << "The average of all positive numbers is: " << setprecision(3) << avg << endl;
cout << "The sum of all negative numbers is: " << neg_sum << endl;
cout << "The average of all negative numbers is: " << setprecision(3) << neg_avg << endl;
cout << "The sum of all numbers is: " << total_sum << endl;
cout << "The average of all numbers is: " << setprecision(3) << total_avg << endl;
cout << "-------------------------------------------------" << endl;
delete [] dynamicArray;
}
fin.close();
cout << "Want us to read another file?\n";
cout << "Enter 'Y' or 'y' for yes, any other character for no." << endl;
cin >> answer;
} while ((answer == 'y') || (answer == 'Y'));
return 0;
}
UPDATE:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
using namespace std;
int main() {
//Variables
string file;
int i = 0, value = 0, e = 0;
double avg, neg_avg, total_sum, total_avg, sum = 0, neg_sum = 0;;
double neg_count = 0, pos_count = 0, totcount = 0;
char answer;
//Input Question
do
{
cout << "Enter the file name.\n";
cin >> file; // Input from User
ifstream fin; // Open File
fin.open(file);
if (fin.fail()) // Check to see if file opens properly
{
cout << "An error occurred while attempting to open the file.\n";
exit(1);
}
// <---------- This works to get the size of the file
int elements;
vector<int> eCount;
while (fin >> elements)
{
eCount.push_back(elements);
}
int size = static_cast<int> (eCount.size());
cout << "size = " << size << endl;// <-----------Test to see if working
//From this point, size of the file is held in the variable, 'size'.
int array_size = size;
int* p;
p = new int[array_size];
int location = 0;
while (!fin.eof())
{
fin >> p[location];
location++;
}
cout << "P[12] is equal to " << p[12] << endl;// <----Test to see if array is initialized
while (fin >> p[location])
{
if (p[e] >= i)
{
sum = sum + p[location];
pos_count = pos_count + 1;
totcount = totcount + 1;
}
else
{
neg_sum = neg_sum + p[location];
neg_count = neg_count + 1;
totcount = totcount + 1;
}
location++;
}
//Calculations
avg = sum / pos_count;
neg_avg = neg_sum / neg_count;
total_sum = sum + neg_sum;
total_avg = total_sum / totcount;
fin.close();
//OUTPUT
cout << "The sum of all positive numbers is: " << sum << endl;
cout << "The average of all positive numbers is: " << setprecision(3) << avg << endl;
cout << "The sum of all negative numbers is: " << neg_sum << endl;
cout << "The average of all negative numbers is: " << setprecision(3) << neg_avg << endl;
cout << "The sum of all numbers is: " << total_sum << endl;
cout << "The average of all numbers is: " << setprecision(3) << total_avg << endl;
cout << "-------------------------------------------------" << endl;
cout << "Want us to read another file?\n";
cout << "Enter 'Y' or 'y' for yes, any other character for no." << endl;
cin >> answer;
} while ((answer == 'y') || (answer == 'Y'));
return 0;
}
Thank you to everyone who's pitched in. I wish I didn't have to use a dynamic array but unfortunately I won't receive if I don't implement one. I updated my code but I can't seem to get the array working properly as it does not seem to load the input from the file properly. Anything helps!
Well, the biggest I/O problem you have is attempting to read with while (!fin.eof()). See Why !.eof() inside a loop condition is always wrong.. The biggest logic problem you are having is including the //Calculations in the same loop you are reading your integers from your file.
Since you read and integer and are keeping a running sum of the positive and negative values, there is no need for a dynamic array at all. You are currently keeping pos_count, neg_count, and totcount which are all you need to compute the respective averages when you leave your read loop.
To tidy things up a bit, let's look at your variables. While you can use double for pos_count, neg_count, and totcount, it's better to use an unsigned type for a counter. C++ provides size_t as a preferred sizetype for counts and lengths, but it's not mandatory -- it just makes sense. While you can use a separate file and answer, it is better to read each input into a std::string to ensure a single keystroke (like the user typing "Yes" instead of 'Y') doesn't leave additional characters unread in stdin. You can also use the same std::string for both your file and answer and just check the if the first character is 'y' or 'Y' to control your read another file loop.
Putting that together, your variables could simple be:
int main (void) {
std::string buffer; /* use single buffer for filename & answer */
do
{ // Variables (will be reinitialized for each file)
int number; /* you are reading one number at a time */
size_t neg_count = 0, pos_count = 0, totcount = 0;
double avg, neg_avg, total_sum, total_avg, sum = 0., neg_sum = 0.;
(note: buffer to read the answer into is the only variable that must be declared before your do {...} while(); loop to be used as the test condition at the end)
If you remember nothing else, remember to validate every input, e.g.
std::cout << "Enter the file name: ";
if (!(std::cin >> buffer)) { // VALIDATE Input from User
std::cerr << "(user canceled input)\n";
return 1;
}
While you can check if the .fail() bit is set on the stream, a more general test is if the file stream goodbit is not set, e.g.
std::ifstream fin(buffer); // open file stream
if (!fin.good()) { // Check to see if file opens properly
std::cerr << "error: file open failed - " << buffer << ".\n";
return 1;
}
(note: either way will work)
When you read in a loop, condition your loop on a successful read. Your read loop here needs to be nothing more than:
while (fin >> number) { /* control read loop with read itself */
if (number >= 0) { /* handle positive numbers */
sum += number;
pos_count += 1;
}
else { /* if it's not >= 0, it's negative */
neg_sum = neg_sum + number;
neg_count = neg_count + 1;
}
totcount += 1; /* total count incremented each time */
}
fin.close();
That will capture all the information you need from your file. Now do the average calculations, but what happens if pos_count, neg_count, or totcount == 0. Dividing by zero is generally a really, really bad thing. Always validate your denominator, e.g.
// Calculations
if (pos_count > 0)
avg = sum / pos_count;
else
avg = 0;
if (neg_count > 0)
neg_avg = neg_sum / neg_count;
else
neg_avg = 0;
total_sum = sum + neg_sum;
if (totcount > 0)
total_avg = total_sum / totcount;
else
total_avg = 0;
Now for your output. How many times do you want to call cout for one continual block of output? (hint: once)
//OUTPUT (you only need one std::cout)
std::cout << "\nThe sum of all positive numbers is: "
<< sum << std::endl
<< "The average of all positive numbers is: "
<< std::setprecision(3) << avg << std::endl
<< "The sum of all negative numbers is: "
<< neg_sum << std::endl
<< "The average of all negative numbers is: "
<< std::setprecision(3) << neg_avg << std::endl
<< "The sum of all numbers is: " << total_sum << std::endl
<< "The average of all numbers is: " << std::setprecision(3)
<< total_avg << std::endl
<< "-------------------------------------------------\n\n"
<< "Want to read another file?\n"
<< "Enter 'Y' or 'y' for yes, any other character for no.\n";
That handles all your output needs in a single call (including your prompt for 'Y' or 'y'). Now just use the same std::string to take input on whether to continue or not, e.g.
if (!(std::cin >> buffer)) {
std::cerr << "(user canceled input)\n";
return 1;
}
/* condition on 1st char in buffer */
} while ((buffer.at(0) == 'y') || (buffer.at(0) == 'Y'));
}
That's it you are done. Putting it altogether, and replacing the fragile use of std::cin >> buffer with getline (std::cin, buffer) you would have:
#include <iostream>
#include <fstream>
#include <iomanip>
int main (void) {
std::string buffer; /* use single buffer for filename & answer */
do
{ // Variables (will be reinitialized for each file)
int number; /* you are reading one number at a time */
size_t neg_count = 0, pos_count = 0, totcount = 0;
double avg, neg_avg, total_sum, total_avg, sum = 0., neg_sum = 0.;
std::cout << "Enter the file name: ";
if (!getline(std::cin, buffer)) { // VALIDATE Input from User
std::cerr << "(user canceled input)\n";
return 1;
}
std::ifstream fin(buffer); // open file stream
if (!fin.good()) { // Check to see if file opens properly
std::cerr << "error: file open failed - " << buffer << ".\n";
return 1;
}
while (fin >> number) { /* control read loop with read itself */
if (number >= 0) { /* handle positive numbers */
sum += number;
pos_count += 1;
}
else { /* if it's not >= 0, it's negative */
neg_sum = neg_sum + number;
neg_count = neg_count + 1;
}
totcount += 1; /* total count incremented each time */
}
fin.close();
// Calculations
if (pos_count > 0)
avg = sum / pos_count;
else
avg = 0;
if (neg_count > 0)
neg_avg = neg_sum / neg_count;
else
neg_avg = 0;
total_sum = sum + neg_sum;
if (totcount > 0)
total_avg = total_sum / totcount;
else
total_avg = 0;
//OUTPUT (you only need one std::cout)
std::cout << "\nThe sum of all positive numbers is: "
<< sum << std::endl
<< "The average of all positive numbers is: "
<< std::setprecision(3) << avg << std::endl
<< "The sum of all negative numbers is: "
<< neg_sum << std::endl
<< "The average of all negative numbers is: "
<< std::setprecision(3) << neg_avg << std::endl
<< "The sum of all numbers is: " << total_sum << std::endl
<< "The average of all numbers is: " << std::setprecision(3)
<< total_avg << std::endl
<< "-------------------------------------------------\n\n"
<< "Want to read another file?\n"
<< "Enter 'Y' or 'y' for yes, any other character for no.\n";
if (!getline(std::cin, buffer)) {
std::cerr << "(user canceled input)\n";
return 1;
}
/* condition on 1st char in buffer */
} while ((buffer.at(0) == 'y') || (buffer.at(0) == 'Y'));
}
(note: getline (std::cin, buffer) has been used in the code above to make the user input a bit more robust -- see the the section below the example output for the reasons)
Example Use/Output
Testing with three files, the first a 50x5 set of positive integers, then next a set of 10 integers with one negative value (-2213) and the last a file of 100 mixed positive and negative values would give:
$ ./bin/pos_neg_total
Enter the file name: dat/50x5.txt
The sum of all positive numbers is: 122180
The average of all positive numbers is: 489
The sum of all negative numbers is: 0
The average of all negative numbers is: 0
The sum of all numbers is: 1.22e+05
The average of all numbers is: 489
-------------------------------------------------
Want to read another file?
Enter 'Y' or 'y' for yes, any other character for no.
y
Enter the file name: ../../..//src-c/tmp/dat/10int_nl.txt
The sum of all positive numbers is: 2.03e+05
The average of all positive numbers is: 786
The sum of all negative numbers is: -2.21e+03
The average of all negative numbers is: -2.21e+03
The sum of all numbers is: 2.01e+05
The average of all numbers is: 774
-------------------------------------------------
Want to read another file?
Enter 'Y' or 'y' for yes, any other character for no.
Y
Enter the file name: ../../../src-c/tmp/dat/100int.txt
The sum of all positive numbers is: 1.93e+06
The average of all positive numbers is: 5.55e+03
The sum of all negative numbers is: -2.29e+05
The average of all negative numbers is: -1.76e+04
The sum of all numbers is: 1.7e+06
The average of all numbers is: 4.71e+03
-------------------------------------------------
Want to read another file?
Enter 'Y' or 'y' for yes, any other character for no.
n
There are many, many ways to put this together, and you are free to use as many variables or calls to std::cout as you like, but hopefully this will help you think further along the lines of "What does my program require?".
Using >> for User-Input is Fragile
As a final note, know that using std::cin >> string for user-input is horribly fragile as any whitespace the user types as part of the input will not be read (and it will be left unread in stdin. It is far better to use getline which will read the complete line into your string. Don't mix using the >> iostream for input with getline without accounting for any '\n' that may be left in stdin. You can then use std::cin.ignore() to clear. In your case it would simply be more robust to take all user input with getline, e.g.
if (!getline(std::cin, buffer)) { // VALIDATE Input from User
std::cerr << "(user canceled input)\n";
return 1;
}
Then filenames with whtespace would be properly handled, and if the user wanted to type "Yes I want to enter another file!" as his answer to your continue question, that would pose no problem at all. If you haven't got there yet in your class, put it in your hip-pocket. For an experiment, try replacing both user inputs with what is shown above with your original std::cin >> buffer and see what happens if you type "Yes I want to enter another file!" at the prompt :)
Let me know if you have further questions.
So why you need a vector(dynamic array) to store the integers since your code can handle the all cases by add a "break" expression on the condition of EOF.
If you really need it, below is what you need:
#include<vector>
vector<int> my_vec;

How to find out if string is only numbers, no letters

I have constructed a code that checks if the entered number is a proper divisible of 9 by getting the string length and finding the sum of each digit entered and finding if its perfectly divisible by 9.
The code works well, I just need some error checks and I have two things to try and add to it.
I need to make sure first that the inputted information is only numbers, no letters.
Also I want to find a way to make input limited from 1 to 1000.
I have this bool example that will check if it is in fact a number, but how can I make an if statement for my userNum input to check the boolean?
bool isNumber(const string &line)
{
if (line[0] == '0') return true;
return (atoi(line.c_str()));
}
#include <iostream>
#include <string>
using namespace std;
string userNum;
char userInput;
int sum, i, n;
int main()
{
tryagain:
sum = 0;
cout << "Enter number to test if it is divisible by 9: ";
cin >> userNum;
if (userNum == isNumber) {
cout << "Nah..";
return 0;
// Find sum of digits by seperating
n = userNum.length(); // Gets the sum of the string length in bytes
}
for (i = 0; i < n; i++) // Starting from 0, until num is less than the length of userNum go up one increment
sum = (sum + (userNum[i] - '0'));
if (sum % 9 == 0) {
cout << "Your number, " << userNum << " adds up to " << sum << " which is evenly divisible to 9" << endl << endl;
}
else {
cout << "Your number, " << userNum << " adds up to " << sum << " which IS NOT evenly divisible to 9" << endl << endl;
}
// Restart option begins here.
cout << "Would you like to try another number? (Y/N): ";
cin >> userInput;
if (userInput == 'y' || userInput == 'Y') {
goto tryagain;
cout << endl;
}
else if (userInput == 'n' || userInput == 'N') {
cout << endl;
cout << "Goodbye!" << endl;
}
else {
cout << endl;
cout << "You have entered an unknown input, goodbye!" << endl;
}
system("pause");
return 0;
}
You could do this in 3 ways:
Use a regular expression, with std::regex_match. The regex that you are looking for is ^[0-9]+$ which checks if a string contains only numbers. This is a possible expression but not the absolute one
Use std::stoi which tries to convert a string into an integer. Be sure to surround it with a try-catch statement to ensure that the string can be properly parsed. If you get the exception, then the string is not a number.
As Justin has pointed out in the comments, you could also try using std::isdigit and iterate over the string to check each char.
Rely on std functions and try to avoid writing code by yourself. The second approach is probably what you are looking for because, if the method does not throw an exception, you can check the range of the number.
When you face a problem for which you cannot find a solution, give a look at the list of algorithms on cppreference. Use them as much as you can because they make the code shorter, easier to read and they can give you advantages (some algorithms just need an extra parameter at the end to start a parallel execution of the method!)
for (i = 0; i < n; i++) {
if(userNum[i] < '0' || userNum[i] > '9') {
cout << "Nah..";
return 0;
}
sum = (sum + (userNum[i] - '0'));
}
Given the necessary range-check with the range being 1...1000, you do not gain anything from summing the digits and dividing the sum by 9, instead of just doing the latter on the number itself. So the numerical part could be simple i < 1, i > 1000, i % 9 == 0 checks, where i is the parsed integer.
std::stoi parses a number at the beginning of a string, so while you can use it, it does not replace checking the characters. e.g. 1, 1.2, 1a are all parsed to 1. You need a string which does not start with a number, and only then you get an std::invalid_argument exception. So you will need #Justin's suggestion too, though here I flipped it as "any_of the characters is not a digit:
std::string s;
std::cin >> s;
try {
if (std::any_of(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }))
throw std::invalid_argument(" is not all-digits");
int i = std::stoi(s);
if (i < 1) throw std::invalid_argument(" is less than 1");
if (i > 1000) throw std::invalid_argument(" is more than 1000");
if (i % 9 == 0) std::cout << i << " is divisible by 9" << std::endl;
else std::cout << i << " is not divisible by 9" << std::endl;
}
catch (std::invalid_argument ia) {
std::cout << s << ia.what() << std::endl;
}
catch (std::out_of_range oor) {
std::cout << s << " sure is not between 1 and 1000";
}
(stoi's "own" invalid_argument can not occur here, because of the pre-check for all-digits)
In the case you would want to get a number between 1 and 1010000 inclusive, then yes, you could start doing magics, like checking length of input, various patterns, and summing the digits:
(Example is tuned down to 1010 so it can be tested without getting a headache)
std::string s;
std::cin >> s;
std::string::iterator it = s.begin(), end = s.end();
int len = end - it;
try {
// if(len==0) will not happen because of the cin
if (*it == '0') {
if (len == 1) throw std::invalid_argument(" is less than 1");
throw std::invalid_argument(" starts with 0, multi-digit numbers do not do that");
}
if (len > 11) throw std::invalid_argument(" is too long for not being greater than 10^10");
if (len == 11) {
if (*it != '1'
|| std::any_of(it + 1, end, [](char c) { return c != '0'; }))
throw std::invalid_argument(" is greater than 10^10 or is not all-digits");
// well, here we know that the number is 10^10 (and is not divisible by 9)
// so this could return early
}
int sum = 0;
for (; it != end; ++it) {
if(!std::isdigit(*it)) throw std::invalid_argument(" is not all-digits");
sum += (*it) - '0';
}
if (sum % 9 == 0)std::cout << s << " is divisible by 9" << std::endl;
else std::cout << s << " is not divisible by 9" << std::endl;
}
catch (std::invalid_argument ia) {
std::cout << s << ia.what() << std::endl;
}

IF or WHILE for numerical input checker

I've been working on a program that calculates the mean of the user's inputs. I couldn't figure out yet, what to use for the input checker. I can't use arrays or strings yet. How do I check that both inputs are numerical values? And if they are not; how do I ask again for the correct input?
#include <iostream>
using namespace std;
int main()
{
// Get number from user
int input = 0;
double accumulator = 0;
double mean;
cout << "How many numbers would you like me to average together?\n";
cin >> input;
if (input >= 0){ //to check if input is a numerical value
// Compute and print the mean of the user input
int number = 1;
double x;
while (number <= input) //while corrected
{
cout << "Please type a numerical value now: \n";
cin >> x;
if (x < 0 || x > 0){ //to check if x is a numerical value
accumulator = accumulator + x;
}
else {
cout << "Input incorrect"<< endl;
}
number = number + 1;
}
mean = accumulator / input; // formula corrected
cout << "The mean of all the input values is: " << mean << endl;
cout << "The amount of numbers for the average calculation is: " << input << endl;
}
else {
cout << "Input incorrect"<< endl;
}
return 0;
}
You can use cin.fail to check for errors. Note that if user inputs a number followed by letters, lets say 123abc, then x will be stored as 123 but abc remains in the input buffer. You may wish to clear that right away so abc doesn't appear in the next loop.
while (number <= input) //while corrected
{
cout << "Please type a numerical value now: \n";
cin >> x;
bool error = cin.fail();
cin.clear();
cin.ignore(0xFFFF, '\n');
if (error)
{
cout << "Input incorrect" << endl;
continue;
}
accumulator = accumulator + x;
number = number + 1;
}
Alternatively you can initialize x. For example
double x = numeric_limits<double>::min();
cin >> x;
cin.clear();
cin.ignore(0xFFFF, '\n');
if (x == numeric_limits<double>::min())
{
cout << "Input incorrect" << endl;
continue;
}
If error occurs then x remains unchanged and you know there was an error, because it is unlikely that the user inputs a number matching numeric_limits<double>::min()
Not related to this issue, but you should also account for divide by zero error.
if (input == 0)
mean = 0;//avoid divide by zero, print special error message
else
mean = accumulator / input;