Cleanest way to avoid writing same condition twice - c++

Lets say I have a loop that inputs a value from user, and if the value is equal to zero, it breaks.
Is there a way to do this without writing the same condition twice?
for example:
int x;
do
{
std::cin >> x;
if (x)
{
//code
}
} while(x);
What is the cleanest way to do this?

It's probably cleanest to write a little function to read the value, and return a boolean to indicate whether you read a non-zero value, then use that function:
bool read(int &x) {
std::cin >> x;
return std::cin && (x != 0);
}
while (read(x)) {
// code to process x
}

When you write the code exactly as you described it with words it get's simpler:
int x;
while(std::cin >> x) // I have a loop that inputs a value from user, and ...
{
if(x == 0) // if the value is equal to zero, ...
{
break; // it breaks.
}
// do something with x ...
}
The reason for having std::cin >> x; as condition is to stop reading when invalid input is entered or the stream ends.

The most laconic way (and note how it tests the integrity of the input stream) is
while (int x; std::cin >> x && x){
// code
}
Another approach, which gives you a bit more scope for introducing code for the fail condition, is
for (;;){ // infinite loop idiom
int x;
if (std::cin >> x && x){
// code
continue; // i.e. go round again
}
// ToDo - code here?
break;
};
is one way. This is not to everyone's taste although the break; before the end of the loop body gives some comfort that the loop is not really infinite.
It also has the advantage that the scope of x is not leaked to the outer scope.

Verbatim "a loop that inputs a value from user, and if the value is equal to zero, it breaks."
while (true)
{
std::cin >> x;
if (x == 0)
break;
...
}

How about:
int x;
while (std::cin >> x, x) {
std::cout << x*5 << std::endl;
}
No ifs, no breaks, the x is already evaluated to be non-zero by the while condition.

Related

One line user input assignment in C++

I am learning C++ and was wondering if there is an equivalent to assigning a user input to a variable in one line, like you can do in C# for example:
string foo = Console.ReadLine();
I was hoping that one of these would work, but they don't.
const string foo = cin >> foo;
cin >> const string foo;
Ideally the variable should be a constant, but that's not necessarily a requirement.
Are there ways of one lining it in C++ or will I just have to learn to live with this?
double foo = 0;
cin >> foo;
As apple apple says you can write your own functions
double console_read_double()
{
double x = 0.0;
cin >> x;
return x;
}
int main()
{
double y = console_read_double();
double z = console_read_double();
...
}
However one advantage of the C++ way is that you can chain calls to input functions
int main()
{
double y, z;
cin >> y >> z;
...
}
You can't do that with a function call that returns the value read.
Another advantage is that you can test the success or failure of the operation with a single line of code
int main()
{
double y, z;
if (cin >> y >> z)
{
// success
}
else
{
// handle error
}
}
Sorry but there is no way in C++ to do this in one line. Unless you do this when you are using an if statement:
if(double b = 0; std::cin >> b)
{
// Code
}
otherwise you will have to live with:
double b = 0;
std::cin >> b;
Or you can just make a function like this:
auto init_and_input()
{
double b = 0;
std::cin >> b;
return b;
}
and then:
int main()
{
auto x = init_and_input();
}
So your answer is not really if you include the function.
In addition to what has been stated, and in the ultra specific scenario where you need to get only one character, standard library provide the function get() that reads and return one character in a stream. This allows you to initialize your variable with the read value, therefore you could also define it as a const.
#include <iostream>
int main()
{
const char some_char = std::cin.get();
// Do whatever with some_char
return 0;
}
Note that even if it is theoretically valid C++, this doesn't looks like any kind of good practice, and it might be preferable in almost every case to just stick to another, most common, way to read your stream.

How can I pass std::cin as an argument for a function?

I've searched for answers on stackoverflow and am simply not getting it. A well-explained answer would be amazing.
Here's my incomplete code for a password validator. I ask for user input and then run it through a series of boolean functions to decide whether it meets the strong password criteria.
If you find any other errors(which I'm sure there is), please let me know. Thanks!
#include <iostream>
#include <ctype.h>
#include <cstring>
//DECLARING GLOBAL VARIABLES
bool isLong;
bool hasDigits;
bool hasAlphabets;
bool hasSpecial;
//FUNCTION TO CHECK IF PASSWORD IS LONG ENOUGH
bool checklen(std::string x)
{
if (x.length() > 8)
{
isLong = true;
}
else if (x.length() < 8)
{
isLong = false;
}
return isLong;
}
//FUNCTION TO CHECK IF PASSWORD HAS DIGITS
bool checkdigits(std::string x)
{
for (int i = 0; i < x.length(); i++)
{
if (isdigit(x[i]))
{
hasDigits = true;
}
else if (not isdigit(x[i]))
{
hasDigits = false;
}
}
return hasDigits;
}
//FUNCTION TO CHECK IF PASSWORD HAS ALPHABETS
bool checkalphabets(std::string x)
{
for (int i = 0; i < x.length(); i++)
{
if (isalpha(x[i]))
{
hasAlphabets = true;
}
else if (not isalpha(x[i]))
{
hasAlphabets = false;
}
}
return hasAlphabets;
}
//MAIN FUNCTION THAT RUNS THE VALIDATION AND HANDLES LOGIC
int main()
{
std::cout << "enter new password: ";
std::string password{};
std::cin >> password;
checklen(password); //trying pass the stored cin value as argument.
checkdigits(password); //trying to pass the stored cin value as argument.
checkalphabets(password); //trying to pass the stored cin value as argument.
//the functions literally use "password" as a string instead of the stored user input.
if (isLong = true)
{
if (hasDigits = true)
{
if (hasAlphabets = true)
{
std::cout << "Your password is strong";
}
}
}
else
{
std::cout << "Your password is still weak";
}
return 0;
}
#include <iostream>
#include <algorithm>
bool isLong(std::string x)
{
return x.length() > 8;
}
bool hasDigits(std::string x)
{
return std::any_of(x.begin(), x.end(), ::isdigit);
}
bool hasAlpha(std::string x)
{
return std::any_of(x.begin(), x.end(), ::isalpha);
}
bool isStrong(std::string x)
{
return isLong(x) and hasDigits(x) and hasAlpha(x);
}
int main()
{
std::string password;
std::cout << "enter new password: ";
std::cin >> password;
if (isStrong(password))
std::cout << "Your password is strong";
else
std::cout << "Your password is weak";
return 0;
}
I assume by
If you find any other errors(which I'm sure there is), please let me
know. Thanks!
you want to find the most 'efficient' program.
The most important error was that you used one equality sign instead
of two. This meant that you were simply assigning a value to a
variable in the if statements, not checking for equality.
Your checklen function returns an uninitialised boolean if
the length of the password is exactly 8.
Your checkdigits function has a logic error. The
return value depends on the last character checked - not the whole
string. If the last character was a digit, it would return true,
else it would return false, not taking in account the whole
string.
The same logic error as above was also in the checkalphabets
function.
There is no need to include an empty initialiser list for the declaration of a std::string.
The nesting of if loops is not necessary as you can simply use && operators.
Your program does not output "Your password is still weak" in the case where the password has no digits and is not alphabetical. It only outputs the above if the password is not long enough.
Global variable use is unnecessary in the program and is frowned upon when dealing with best programming practices. They are available to all functions, classes - however, if you were to define a variable of the same name, there would be a redeclaration error. (This is just one problem when using global variables.)
The code I posted above is what I would consider "optimal". It uses built-in functions to reduce code complexity and is much more consider.
If you are new to programming (which I will assume), I would recommend you try 'dry running' your code as this will help you identify the logic errors.
The syntax error of the equality signs should be picked up by a good compiler. (Or rather, logic error, as the syntax is 'valid' but 99% of the time is not what is intended.)
Inefficiencies in the program code can be reduced with experience (such as the nested if loops).
How can I pass std::cin as an argument for a function?
std::cin is an std::istream. Thus, the way to pass it to a function is like this:
void function(std::istream& stream) {
// implmentation...
}
Note: I believe you can't pass std::istreams by value. You must pass it by reference.
Then you call it like this:
function(std::cin);
Please note that you have other bugs in your program explained better in the other answer. But that's how you generally pass std::cin to a function.

Getter that loops through the variables of a struct

There's a small program that has various options, and these need some input values -- they are in a struct. Each option requires an instance of the struct, so there's an array of struct. I would like to be able to save these options at program exit and read them at program start. But the struct doesn't hold only 3 variables, and they may grow in time as my small program grows. An example of the struct:
struct S
{
int a;
float b;
std::vector<float> c;
}
The save file has as many rows as there are options, and each row contins the same sequence, but different values, which are separated by ;, the elements of the vectors with , and a terminating ;, no spaces. For the above example:
13;3.14;0.618,1.618;
7;2.718;12.3,45.6;
...
But the file can get corrupt, so reading it corrupts the variables and the program crashes. Currently, reading the numbers involves a loop (the number of options/rows is known):
float x;
char c;
std::fstream fs;
// file open, flags, etc
fs >> a >> c;
if(c != ';')
{
std::cerr << "Error! ...\n";
break;
}
fs >> b >> c;
if(c != ';')
{
std::cerr << "Error! ...\n";
break;
}
c = ','; // make sure c is not ';'
while(c != ';')
{
fs >> x >> c;
c.push_back(x);
if(c != ',')
{
std::err << "Error...\n";
break;
}
}
Instead of break it can be an abort() function, or one that starts from scratch, not the problem, but if there are 100 variables, I have to do this for everyone. That's why I was thinking of looping through them. Apparently there's no "reflection" in C++, but it could be done via some macros. Currently, I don't understand either of them, so I tried my own solution. First, I tried making a general use() function with a template, but it fails when called, with template argument deduction/substitution failed. I tried auto as the type, but also fails. I suppose it makes sense. So then I thought why not just make a set/get that handles the worst possible type and converts it, internally. This is what member functions came up:
enum { INT_A, FLOAT_B, VECTOR_C, ALL };
void set(const int &n, const float &f, const int &i = 0)
{
switch(n)
{
case INT_A: a = static_cast<int>(x); break;
case FLOAT_B: b = x; break;
case VECTOR_C: c[i] = x; break;
}
}
float get(const int &n, const int &i = 0)
{
switch(n)
{
case INT_A: return static_cast<float>(a); break;
case FLOAT_B: return b; break;
case VECTOR_C: return c[i]; break;
}
}
get() is mostly for confirming, set() is what interests me. It does seem to work, I can set up a loop to iterate and automate the process, but is this a good solution (I somehow doubt it is, but I am not advanced)? Are there better ones that do not involve external libraries?
Sorry for the delay, I simply forgot to update it. I decided to use an additional std::vector<float> that holds all the variables as float. The order is that the original std::vector<float> (c in the above example) are all, sequentially, last in the vector. The downside is that it occupies about twice as much memory, but less code. Now, I know that the vector c (and the rest in the real case scenario) have a minimum length, so I have two options:
impose the length if the additional vector to include these minimum lengths, then, when it's about writing, I need an if() deciding whether I need to write until the minimum length, or above it, something like this:
if(c.size() < minLength)
// loop to write to c[i]
else
// loop to c.push_back(...)
or I could just consider the length of the additional vector made of the number of single variables, like a and b, and considering the length of the vector (c) zero, thus, when writing, the code will reduce to a for() or while() loop with push_back().
I opted for the second, so the struct now looks like this:
struct S
{
int a;
float b;
std::vector<float> c;
std::vector<float> additional(2); // holds a and b, c islength zero
}
The writing to vector can be easily implemented in a loop. A quick show looks like this:
int n;
float x;
char c;
while(n < maxSizeOfAdditional)
{
switch(n)
{
case 1: a = static_cast<int>(additional[i]); break;
case 2: b = additional[i]; break;
case 3:
{
while(fs >> x >> c)
// loop for writing c.push_back(x)
}
}
++n;
}
I need the original types because of the rest of the code in the program, thus the need for static_cast. It works now, and there is no "reflection", nor did I need one, I just needed a way to automate the process with a loop.
Still, I don't know if it's an "orthodox" approach. For my part, it seems to have solved my problem, but I don't know how something like this would be considered. Better yet, I don't know how "the usual" way is done with programs that need to read/write variables to savefiles, variables that must reside somewhere (I just imagined them in a struct, that's all). I suppose time will tell.

Create big numbers by BCD - C++

I want to create code that will help me get numbers bigger than MAXINT. I heard about that I can use Binary Code Decimal to do this, and then every two of decimal numbers(converted to BCD) of the bigger number keep in char. But how to do this? I should give string as input, then convert somehow to BCD every single decimal number? And how can I put two converted decimal numbers to one char? I'm new in C++ and don't know how can i do it.
P.S. I don't want to use libraries which are "special" for that kind of problems.
As it turns out, this is actually quite simple. How about we try to take it to the next level?
Below is an implementation of a BCD number with infinite(or as much as memory can hold) size. It only supports positive integer numbers. I'll leave extending this to support negative numbers(or real numbers) as an exercise.
First things first: Yes, we want to get our number as a string and then build it up from that. Since it's only an integer, this is actually quite easy to do. We primarily create a helper function to aid us in identifying all the digits.
int char_to_int(const char c) {
int ret = c - '0';
if(ret > 9 || ret < 0) throw 1; // for simplicity. Use a class derived from std::exception instead.
return ret;
}
We can now try to implement input and output for our big number.
First Try
Having that helper guy, turning a string to a BCD-encoded buffer is easy. A common implementation may look like this:
int main() {
unsigned char bignum[10]; // stores at most 20 BCD digits.
std::memset(bignum, 0, sizeof(bignum));
std::string input;
std::cin >> input;
try {
if (input.size() > 20) throw 1; // Avoid problems with buffer overflow.
for (int i=1;i<=input.size();i++) {
int n = char_to_int(input[input.size()-i]);
bignum[sizeof(bignum) - (i+1)/2] |= n << (i%2)*4; // These are bitwise operations. Google them!
}
}
catch(int) {
std::cout << "ERROR: Invalid input.\n";
return 0; // Exit cleanly.
}
// bignum is now filled. Let's print it to prove.
for (int i=0;i<sizeof(bignum);i++) {
int first_digit = bignum[i] & '\x0F'; // Right side, doesn't need to shift.
int second_digit = (bignum[i] & '\xF0')>>4; // Left side, shifted.
std::cout << first_digit << second_digit;
}
}
This is not very space-efficient, however. Note that we have to store all the 20 digits, even if our number is small! What if we needed 1000 digits? What if we need 1000 numbers that may or may not have these 1000 digits? It is also error-prone: Look that we had to remmember to initialize the array, and do a bounds check before conversion to avoid a buffer overflow.
Second Try
We can improve our implementation using a std::vector:
int main() {
std::vector<unsigned char> bignum; // stores any quantity of digits.
std::string input;
std::cin >> input;
try {
// For an odd number of digits we want a trailling zero at the end.
if(input.size()%2) n.num_vec.push_back(char_to_int(input[0]));
for (unsigned i=input.size()%2;i<input.size();i+=2) {
int left = char_to_int(input[i]);
int right = char_to_int(input[i+1]);
n.num_vec.push_back(0);
n.num_vec.back() = left << 4;
n.num_vec.back() |= right;
}
}
catch(int) {
std::cout << "ERROR: Invalid input.\n";
exit(0); // Exit cleanly.
}
// bignum is now filled. Let's print it to prove.
for (unsigned i=0;i<bignum.size();++i) {
// Notice that we inverted this from the previous one! Try to think why.
int first_digit = (bignum[i] & '\xF0')>>4; // Left side, shifted.
int second_digit = bignum[i] & '\x0F'; // Right side, doesn't need to shift.
if(i || first_digit) std::cout << first_digit; // avoid printing trailling 0.
std::cout << second_digit;
}
}
Lookin' good, but that is too cumbersome. Ideally, the bignumber user shouldn't have to deal with the vector positions and all that mumbo-jumbo. We want to write code that behaves like:
int main() {
int a;
cin >> a;
cout << a;
}
And it should just work.
Third Try
Turns out this is possible! Just wrap bignum into a class, with some helpful operators:
class bignum {
std::vector<unsigned char> num_vec;
template<typename T>
friend T& operator<<(T& is, bignum& n);
template<typename T>
friend T& operator>>(T& os, bignum& n);
};
// Get input from any object that behaves like an std::istream (i.e.: std::cin)
template<typename T>
T& operator>>(T& is, bignum& n) {
std::string input;
is >> input;
n.num_vec.reserve(input.size());
if(input.size()%2) n.num_vec.push_back(char_to_int(input[0]));
for (unsigned i=input.size()%2;i<input.size();i+=2) {
int left = char_to_int(input[i]);
int right = (i+1) != input.size()?char_to_int(input[i+1]):0; // If odd number of digits, avoid getting garbage.
n.num_vec.push_back(0);
n.num_vec.back() = left << 4;
n.num_vec.back() |= right;
}
return is;
}
// Output to any object that behaves like an std::ostream (i.e.: std::cout)
template<typename T>
T& operator<<(T& os, bignum& n) {
for (unsigned i=0;i<n.num_vec.size();++i) {
int first_digit = (n.num_vec[i] & '\xF0')>>4; // Left side, shifted.
int second_digit = n.num_vec[i] & '\x0F'; // Right side, doesn't need to shift.
if(i || first_digit) os << first_digit; // avoid printing trailling 0.
os << second_digit;
}
return os;
}
Then our main function looks much more readable:
int main() {
bignum a;
try {
std::cin >> a;
}
catch(int) {
std::cout << "ERROR: Invalid input.\n";
return 0; // Exit cleanly.
}
std::cout << a;
}
Epilogue
And here we have it. Of course with no addition, multiplication, etc. operators, it isn't very useful. I'll leave them as an exercise. Code, code and code some more, and soon this will look like a piece of cake to you.
Please feel free to ask any questions. Good coding!

Taking in array of unknown size in c++

Ok I am extremely new to programming, and I am taking a c++ class. Basically for the current project I have to take in an array of unknown size, resize it, and output a bunch of statistics like average, Q1, Q3, etc. I am having trouble taking in the array from the user. I need to quit taking in variables once they enter 0. Here is what I have:
int i = 1; //When I first posted this I didn't mean to comment out the '= 1' part
do {
cin >> array[i];
if (array[i] != 0)
return true;
} while (true);
What am I doing wrong? the program stops after I enter 1 number every time no matter what number I enter.
I am using vector class btw.
Do the following:
// change int to your type
int val;
std::vector<int> vec;
while(std::cin >> val) {
if(val == 0) break;
vec.push_back(val);
}
Reason: Stating a return clause causes to exit the loop.
use of std::vector ensures the arbitrary size condition.
Update after #nonsensickle's constructive remark:
The following piece of code also ensures the only 0 terminates input process condition:
// change int to your type
int val;
std::vector<int> vec;
do {
if(std::cin >> val) {
if(val == 0) break;
vec.push_back(val);
} else { // fix broken input stream in case of bad input
std::cin.clear();
std::cin.ignore(1,'\n');
}
} while(true);
and a more sophisticated way, although overkill but what the hell :), with templates and type traits:
template <typename T>
struct zero_traits
{
static T getzero() { return T(0); }
};
template <>
struct zero_traits<std::string>
{
static std::string getzero() { return "0"; }
};
template <>
struct zero_traits<char>
{
static char getzero() { return '0'; }
};
template <typename T>
std::vector<T> read_values()
{
T val;
std::vector<T> vec;
do {
if(std::cin >> val) {
if(val == zero_traits<T>::getzero()) break;
vec.push_back(val);
} else {
std::cin.clear();
std::cin.ignore(1,'\n');
}
} while(true);
return vec;
}
int main()
{
// change int to your type
std::vector<int> vec = read_values<int>();
for(auto i : vec) std::cout << i << std::endl;
}
First of all i will never increment.
Second of all, if (array[i] != 0) will return if that array's value doesn't equal 0.
You need to read into how do { ... } while() loops work as well as what return statements do. Might as well throw in how to increment an array while you're at it.
I will not try to answer your question directly. What you have is a small logic error and a misunderstanding of the do {...} while () looping construct. What you need is to learn how to step through your code.
Let's go through your code line by line (there are only 6 lines here so it should be really easy):
int i; - Ok, so we are declaring an integer i here but are not giving it a value. As such, i can have a random value.
do { - This is where we will come back to when we evaluate the while clause. But only if the result of the while clause is true.
cin >> array[i] - Store a value that the user enters in the array at the position i. Here we ask ourselves a question, what is i? We should know its value without having to run the program. Hint: there's a problem here because of i
if (array[i] != 0) - If the number entered by the user is not zero return true (exit this function with the result true).
} while (true); - Go back to the do { line and redo all the steps until you get here. There is no condition here so it will keep happening until we exit this function.
Hint: The only exit point of your loop is at step 4.
With this, you should be able to figure out your problem. Trying to break down the problem for yourself should be your first step.
I recommend reading this blog post on debugging small programs. It should be informative.
Though code posted by others (in particular #DimitriosBouzas) will work, and is the better choice, I strongly recommend fixing your code and learning why it failed. This will help you in the long run more than #DimitriosBouzas' elegant solution.
Before answering your question.
Initialize your variables int i=0; .You assign i to be zero because arrays are zero indexed.
You have to incerement i. If do not increment it, i will point at the first "bucket" in your array the whole time. Use i++ or i = i + 1 after every iteration of the do while loop to move "forward" in your array.
You want your program to run until zero is entered so you have to write your condition like this if (array[i] == 0) return true;. This condition is true when the last number entered was zero and it will cause your method to return. It would be more elegant for you to check for it in the while clause.
Putting it all together, your code should look like this
int i=0;
do {
cin >> array[i];
if (array[i] != 0) break;
i++;
} while (i < maxSize);
//do stuff with filled array