c++ validate input value before add it to array - c++

My target is to validate input value before add it into array. Current code used:
int main()
{
int temp;
int arr[5];
for(int i = 0; i < 5; i++)
{
// validate here
cin >> arr[i];
}
return 0;
}
and my validation method:
int validateInput(string prompt)
{
int val;
while (true)
{
cin.clear();
cin.sync();
cout << prompt;
cin >> val;
if (cin.good() && val >= -50 && val <= 50)
{
break;
}
else
cin.clear();
cout << "Invalid input! number must be between -50 and 50" << endl;
}
return val;
}
How is that possible?

Your validateInput should just deal with validation: it should answer "is x valid or not valid?"
bool validateInput(int x)
{
return val >= -50 && val <= 50;
}
When reading from stdin, use validateInput and branch accordingly:
for(int i = 0; i < 5; i++)
{
int temp;
cin >> temp;
if(cin.good() && validateInput(temp))
{
arr[i] = temp;
}
else
{
cout << "Invalid input! number must be between -50 and 50" << endl;
// handle invalid input
}
}
If you want to further abstract the idea of "only reading valid numbers from std::cin", you can use an higher-order function:
template <typename TFValid, typename TFInvalid, typename TFInvalidIO>
decltype(auto) processInput(TFValid&& f_valid, TFInvalid&& f_invalid, TFInvalidIO&& f_invalid_io)
{
int temp;
cin >> temp;
if(!cin.good())
{
// Invalid IO.
return std::forward<TFInvalidIO>(f_invalid_io)();
}
if(validateInput(temp))
{
// Valid IO and datum.
return std::forward<TFValid>(f_valid)(temp);
}
// Valid IO, but invalid datum.
return std::forward<TFInvalid>(f_invalid)(temp);
}
Usage:
for(int i = 0; i < 5; i++)
{
processInput([&](int x){ arr[i] = x; },
[](int x){ cout << x << " is invalid"; },
[]{ cout << "Error reading from cin"; });
}
If you want more genericity you can also pass validateInput and the type of input as an additional parameters.

Vittorio's answer above is spot on. For completeness, if you want exactly 5 elements:
#include <string>
#include <iostream>
using namespace std;
bool validateInput(int inValue)
{
return inValue >= -50 && inValue <= 50;
}
int main()
{
int _arr[5];
int _currentIdx = 0;
int _tmp;
while (_currentIdx < 5)
{
cin >> _tmp;
if (validateInput(_tmp))
{
_arr[_currentIdx] = _tmp;
_currentIdx++;
}
else
{
cout << "Invalid input! number must be between -50 and 50" << endl;
}
}
}

replace
cin >> temp;
with
arr[i] = validateInput("some str");

Related

Why is my program not working when I enter a charge number that matches the number in my array

Why is my program not working when I enter a charge number that matches the number in my array. Please Refer to the function
#include <iostream>
#include <cmath>
using namespace std;
string returnWord(int arr[], int SZ)
{
int nums = 0;
string answer;
cout << "Please enter a charge number: ";
cin >> nums;
for (int i = 0; i < SZ; i++) {
if (nums == arr[i]) {
answer = "This is Valid";
}
else {
answer = "This is Invalid"; // When I enter the valid number this is what prints out
}
}
return (answer);
}
int main()
{
const int SZ = 18;
int nums[SZ] = { 5658845, 4520125, 7895122, 8777541, 8451277, 1302850,
8080152, 4562555, 5552012, 5050522, 7825877, 1250255,
1005231, 6545231, 3852085, 7576651, 7881200, 4581002 };
string something = returnWord(nums, SZ);
cout << something << " ";
}
My program when ran will not properly print out "This is valid", even when I enter the correct number from my array. I don't understand why this is happening.
It will only print This is Valid if the last number in the array is valid because you continue the loop through the whole array and assign answer in each step.
You should return from the function early if the value you check is valid or return that it's invalid after the loop.
Example:
std::string returnWord(int arr[], size_t SZ) {
cout << "Please enter a charge number: ";
if (int nums; cin >> nums) {
for (size_t i = 0; i < SZ; i++) {
if (nums == arr[i]) {
return "This is Valid"; // return directly when it's found valid
}
}
}
return "This is Invalid"; // the whole array is checked, it was invalid
}
This for loop with the inner if statement
for (int i = 0; i < SZ; i++) {
if (nums == arr[i]) {
answer = "This is Valid";
}
else {
answer = "This is Invalid"; // When I enter the valid number this is what prints out
}
}
is logically incorrect. It can be interrupted at once when the current element of the array is not equal to the searched number.
Rewrite the loop for example the following way
std::string returnWord( const int arr[], size_t SZ )
{
int nums = 0;
std::cout << "Please enter a charge number: ";
std::cin >> nums;
size_t i = 0;
while ( i != SZ && nums != arr[i] ) ++i;
return i == SZ ? "This is Invalid" : "This is Valid";
}

stuck at calling some methods in C++ to create a menu

I have a class ComplexesSet which represent a set of complexes numbers. I have to use this class to write a program which reads the complex numbers from keyboard and create a menu like that: press 1 to add a number in the set, press 2 to delete a number from set and press 0 to exit the program.
This is my program:
HEADER FILE
#pragma once
#include <iostream>
using namespace std;
#define DIMMAX 10;
class Complex {
int re, im;
public:
Complex() {
re = im = 0;
}
Complex(int re, int im) {
this->re = re;
this->im = im;
}
void display() {
cout << " (" << re << ", " << im << " ) ";
}
int equal(Complex c2); // check the equality between 2 complex numbers.
void read(); // reads a complex number
};
class ComplexesSet {
Complex* v; // the complex numbera array
int dim; // the maximum dimension of the array
int n; // the current number of complex numbers in the set
public:
ComplexesSet();
ComplexesSet(int d);
~ComplexesSet();
void addNumber(Complex); // add a number in set
void deleteNumber(Complex); // delete a number from set
void displaySet(); // display the set
};
METHODS FILE
#include "multime.h"
#include <iostream>
using namespace std;
int Complex::equal(Complex c2) {
if (this->re == c2.re && this->im == c2.im) {
return 1;
}
else {
return 0;
}
}
void Complex::read() {
cout << "Enter the real part: ";
cin >> this->re;
cout << "Enter the imaginary part: ";
cin >> this->im;
cout << endl;
}
ComplexesSet::ComplexesSet() {
cout << "Set of complexes numbers: ";
dim = DIMMAX;
v = new Complex[dim];
n = 0;
}
ComplexesSet::ComplexesSet(int d) {
cout << "ComplexesSet(" << d << ")";
dim = d;
v = new Complex[dim];
n = 0;
}
ComplexesSet::~ComplexesSet() {
cout << "~ComplexesSet" << endl;
if (v) {
delete[] v;
}
v = nullptr;
dim = -1;
n = -1;
}
void ComplexesSet::addNumber(Complex num) {
int ok = 0;
if (n < dim) {
for (int i = 0; i < n; i++) {
if (v[i].equal(num)) {
ok = 1;
i = n + 1;
}
}
if (ok) {
cout << "This element is already in the set.";
}
else {
v[n] = num;
n++;
}
}
else {
cout << "The set is full.";
}
}
void ComplexesSet::deleteNumber(Complex num) {
int i;
if (n != 0) {
for (i = 0; i < n; i++) {
if (v[i].equal(num)) {
break;
}
else {
cout << "This element does not exists.";
}
}
if (i < n) {
n = n - 1;
for (int j = i; j < n; j++) {
v[j] = v[j + 1];
}
}
}
else {
cout << "The set is empty.";
}
}
void ComplexesSet::displaySet() {
cout << "\n The set: {";
if (n) {
for (int i = 0; i < n; i++) {
v[i].display();
}
}
cout << "}.\n\n";
}
MAIN FILE:
#include "multime.h"
#include <iostream>
using namespace std;
int main() {
ComplexesSet m;
Complex num;
int option;
int x;
do {
cout << endl << "1 - ADD A NUMBER\n 2 - DELETE A NUMBER\n 0 - EXIT THE PROGRAM";
cin >> option;
switch (option) {
case 1:
cout << endl << "Enter the number you want to add: ";
num.read();
//? How to call addNumber method from ComplexesSet class?
// m.displaySet ?;
break;
case 2:
cout << endl << "Enter the number you want to delete: ";
num.read();
//? How to call deleteNumber method from ComplexesSet class?
// m.displaySet ?;
break;
}
} while (option >= 1 && option <= 2);
system("pause");
return 0;
}
I got stuck in the main file. How to call the addNumber and deleteNumber methods in order to add and delete a complex number from the set? Also, after pressing "1" or "2", after I read the number, I need to display the set.

Printing the searched line

I want to search for a name from a list of names and if its found I should return the whole info of that person else not found. I dont know why my code is not working. I can print the info of the person, eg:
Input:
3
Steve 9812761810 017
Wayne 8299915781 102
Ronnie 9161462903 120
Wayne
Output:
Wayne 8299915781 102
#include <iostream>
#include <string.h>
using namespace std;
int main() {
string name[100];
long long number[100];
int year[100], i, n, check = 0;
string inp;
cin >> n;
for (i = 0; i < n; i++) {
cin >> name[i] >> number[i] >> year[i];
}
cin >> inp;
for (i = 0; i < n; i++) {
if (inp == name[i]) {
check = 1;
}
}
if (check == 0)
cout << "Info Not found";
else
cout << "The Entered Name is found";
for (i = 0; i < n; i++)
cout << name[i] << number[i] << year[i];
return 0;
}
After reading an integer from the input stream, you should use cin.ignore(); before reading any strings from the input stream.
cin.ignore(); ignores the "new line" character.
Your modified code:
#include <iostream>
#include <string.h>
using namespace std;
int main() {
string name[100];
long long number[100];
int year[100], i, n, check = 0;
string inp;
cin >> n;
cin.ignore();
for (i = 0; i < n; i++) {
cin >> name[i] >> number[i] >> year[i];
cin.ignore();
}
cin >> inp;
for (i = 0; i < n; i++) {
if (inp == name[i]) {
check = 1;
}
}
if (check == 0)
cout << "Info Not found";
else
cout << "The Entered Name is found";
for (i = 0; i < n; i++)
cout << name[i] << number[i] << year[i];
return 0;
}
Read more here: Using getline(cin, s) after cin
At the end of the program, you are ignoring the value of check and just printing everything in your list regardless of whether the entered name was actually found or not.
Try something more like this instead:
#include <iostream>
#include <string>
using namespace std;
int main() {
string name[100];
long long number[100];
int year[100], i, n, idx = -1;
string inp;
cin >> n;
for (i = 0; i < n; i++) {
cin >> name[i] >> number[i] >> year[i];
}
cin >> inp;
for (i = 0; i < n; i++) {
if (inp == name[i]) {
idx = i;
break;
}
}
if (idx == -1)
cout << "Info Not found";
else {
cout << "The Entered Name is found: ";
cout << name[idx] << " " << number[idx] << " " << year[idx];
}
return 0;
}
You might also consider using a struct to organize your data better, eg:
#include <iostream>
#include <string>
using namespace std;
struct myData {
string name;
long long number;
int year;
};
istream& operator>>(istream &is, myData &data) {
is >> data.name >> data.number >> data.year;
return is;
}
ostream& operator<<(ostream &os, const myData &data) {
os << data.name << " " << data.number << " " << data.year;
return os;
}
int main() {
myData data[100];
int i, n, idx = -1;
string inp;
cin >> n;
for (i = 0; i < n; i++) {
cin >> data[i];
}
cin >> inp;
for (i = 0; i < n; i++) {
if (inp == data[i].name) {
idx = i;
break;
}
}
if (idx == -1)
cout << "Info Not found";
else
cout << "The Entered Name is found: " << data[idx];
return 0;
}

C++ how to use any_of for finding duplicate number in function?

here is my code:
#include <iostream>
#include <algorithm>
using namespace std;
void input_guess_number(int guess_number[]){
int num, check = 0;
for(int i = 0; i < 4; i++){
cout << "please enter no." << i+1 << " number (0-9) and press enter: ";
cin >> num;
if (any_of(begin(guess_number), end(guess_number), [=](int n){return n == num;})){
check = 1;
}
else{
check = 0;
}
if (check == 1){
cout << "\nyou cannot use this number. try another one!\n\n";
i--;
}
else if (num >=0 && num < 10){
guess_number[i] = num;
}
else{
cout << "\nwrong number! please choose a number from 0 to 9.\n\n";
i--;
}
}
cout << "\nYour number is: ";
for(int i = 0; i < 4; i++){
cout << guess_number[i];
}
}
int main()
{
int guess_number[4] = {100, 100, 100, 100};
input_guess_number(guess_number);
}
they works well if I put all code in the main().
now I am trying to put them to a function input_guess_number,
so that the main() will be smaller.
but something happened. they cannot work.
anyone know how to improve this? thanks.
The problem is that once you have passed the array to the function, it has decays to a pointer to its first element. You can't really use begin and end of pointers. Instead pass the size of the array (the number of elements) to the function as an extra argument and use guess_number as the start iterator and guess_number + size_of_array as the end iterator.
Or start using std::array for your arrays instead.
anyone know how to improve this? thanks.
Yes, make the length of the array deducable through a template
#include <iostream>
#include <algorithm>
using namespace std;
template<std::size_t Length>
void input_guess_number(int (&guess_number)[Length])
{
int num, check = 0;
for(int i = 0; i < Length ; i++){
cout << "please enter no." << i+1 << " number (0-9) and press enter: ";
cin >> num;
if (any_of(begin(guess_number), end(guess_number), [=](int n){return n == num;})){
check = 1;
}
else{
check = 0;
}
if (check == 1){
cout << "\nyou cannot use this number. try another one!\n\n";
i--;
}
else if (num >=0 && num < 10){
guess_number[i] = num;
}
else{
cout << "\nwrong number! please choose a number from 0 to 9.\n\n";
i--;
}
}
cout << "\nYour number is: ";
for(int i = 0; i < 4; i++){
cout << guess_number[i];
}
}
int main()
{
int guess_number[4] = {100, 100, 100, 100};
input_guess_number(guess_number);
}
for fun, here's a version which uses std::vector to accumulate the digits, and also shows which remaining digits are allowed in the prompt.
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <utility>
using namespace std;
vector<pair<int, int>> allowed_range(int min, int max, const std::vector<int>& used)
{
vector<pair<int, int>> result;
while (min != max)
{
while ((min != max) && std::find(begin(used), end(used), min) != end(used))
{
++min;
}
if (min != max)
{
pair<int, int> current = { min, min };
while ((min != max) && std::find(begin(used), end(used), min+1) == end(used))
++min;
current.second = min;
result.push_back(current);
if (min == max) break;
++min;
}
}
return result;
}
std::ostream& emit_range(std::ostream& os, const pair<int, int>& range)
{
if (range.first == range.second) {
return os << range.first;
}
else {
return os << range.first << "-" << range.second;
}
}
std::ostream& emit_ranges(std::ostream& os, const vector<pair<int, int>>& ranges)
{
auto sep = "";
for (auto& range : ranges) {
emit_range(os << sep, range);
sep = ",";
}
return os;
}
std::ostream& emit_ranges(std::ostream& os, int min, int max, const std::vector<int>& used)
{
return emit_ranges(os, allowed_range(min, max, used));
}
std::vector<int> input_guess_number(std::size_t desired_length)
{
std::vector<int> accumulator;
while (accumulator.size() < desired_length)
{
cout << "please enter no." << accumulator.size() + 1 << " number in range ";
emit_ranges(cout, 0, 9, accumulator) << " and press enter: ";
int num;
cin >> num;
if (std::find(begin(accumulator), end(accumulator), num) != end(accumulator))
{
cout << "\nyou cannot use this number. try another one!\n\n";
continue;
}
else if (num < 0 or num > 9) {
cout << "\nwrong number! please choose a number from 0 to 9.\n\n";
continue;
}
else {
accumulator.push_back(num);
}
}
return accumulator;
}
int main()
{
auto digits = input_guess_number(4);
cout << "\nYour number is: ";
std::copy(begin(digits), end(digits), ostream_iterator<int>(cout));
cout << endl;
}

How to check for non-integer input in multiple inputs

I was working on this program for a while and I can not find a way to make the cin.fail() output "Incorrect input." on 2nd,3rd,4th,... digit of the second binary number. For example "11111 a11" is detected as input fail but "11111 1a1" or "11111 1abfcds" is not detected. It seems to only check the 1st digit. Here is the program.
#include <iostream>
#include <cmath>
using namespace std;
int binary_decimal_1(int n);
int binary_decimal_2(int m);
int decimal_binary(int s);
int main()
{
int n, m, s;
cout << "Input 2 binary numbers" << endl;
cin >> n;
if (cin.fail())
{
cout << "Incorrect input." << endl;
return 0;
}
cin >> m;
if (cin.fail())
{
cout << "Incorrect input." << endl;
return 0;
}
s= binary_decimal_1(n) + binary_decimal_2(m);
cout << "Sum: " << decimal_binary(s) << endl;
return 0;
}
int decimal_binary(int s) /* Function to convert decimal sum to binary result.*/
{
int rem, i=1, binary=0;
while (s!=0)
{
rem=s%2;
s/=2;
binary+=rem*i;
i*=10;
}
return binary;
}
int binary_decimal_1(int n) /* Function to convert binary number 1 to decimal.*/
{
int decimal_1=0, i=0, rem;
while (n!=0)
{
rem = n%10;
n/=10;
decimal_1 += rem*pow(2,i);
++i;
}
return decimal_1;
}
int binary_decimal_2(int m) /* Function to convert binary number 2 to decimal.*/
{
int decimal_2=0, i=0, rem;
while (m!=0)
{
rem = m%10;
m/=10;
decimal_2 += rem*pow(2,i);
++i;
}
return decimal_2;
}
Input processing terminates on the first non-numeric character encountered.
Once you get a value to parse, use a function to validate it:
template <typename T>
bool convert_to( const std::string& s, T& value )
{
std::istringstream ss( s );
ss >> value >> std::ws;
return ss.eof();
}
--Typed off the top of my head; typos may have occurred.
I fixed my program by using strings and checking those for incorrect input, converting strings to integers and now it works.
#include <iostream>
#include <cmath>
#include <sstream>
using namespace std;
int binary_decimal_1(int n);
int binary_decimal_2(int m);
int decimal_binary(int s);
int main()
{
string n, m;
int s;
cout << "Input 2 binary numbers:" << endl;
cin >> n;
cin >> m;
bool bValidn = true; // Function to check for non numeric input in n.
for (unsigned int nIndex=0; nIndex < n.length(); nIndex++)
if (!isdigit(n[nIndex]))
{
bValidn = false;
cout << "Bad input.";
return 0;
}
bool bValidm = true; // Function to check for non numeric input in m.
for (unsigned int nIndex=0; nIndex < m.length(); nIndex++)
if (!isdigit(m[nIndex]))
{
bValidm = false;
cout << "Bad input.";
return 0;
}
// Now to convert strings into integers.
int intn;
stringstream convertn(n);
if ( !(convertn >> intn) )
intn = 0;
int intm;
stringstream convertm(m);
if ( !(convertm >> intm) )
intm = 0;
// And the hardest part.
s = binary_decimal_1(intn) + binary_decimal_2(intm);
cout << "Sum is: " << decimal_binary(s) << endl << endl;
return 0;
}
int decimal_binary(int s) // Function to convert decimal sum to binary result.
{
int rem, i=1, binary=0;
while (s!=0)
{
rem=s%2;
s/=2;
binary+=rem*i;
i*=10;
}
return binary;
}
int binary_decimal_1(int intn) // Function to convert binary number 1 to decimal.
{
int decimal_1=0, i=0, rem;
while (intn!=0)
{
rem = intn%10;
intn/=10;
decimal_1 += rem*pow(2,i);
++i;
}
return decimal_1;
}
int binary_decimal_2(int intm) // Function to convert binary number 2 to decimal.
{
int decimal_2=0, i=0, rem;
while (intm!=0)
{
rem = intm%10;
intm/=10;
decimal_2 += rem*pow(2,i);
++i;
}
return decimal_2;
}