Simple C++ Inclusive Calculator Code Review - c++

C++ newbie here. Anything wrong or complicated with this code? The main question I have is whether I can use v1 and v2 inside while (val <= v2)?
#include <iostream>
int main ()
{
std::cout << "Enter two numbers: " << std::endl;
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
int sum = 0, val = v1;
while (val <= v2)
{
sum += val;
++ val;
}
std::cout << "The sum of " << v1 << " through " << v2 << " inclusive is " << sum << std::endl;
return 0;
}

Yes, you can, they're local variables in main() so they're in scope until main() returns (i. e. the whole lifetime of the program).

Of course you can. The statement inside the while-loop needs to evaluate to a boolean expression, i.e. true or false. And as you can state that either it is true that val <= v2 or not, this is perfectly fine.

Related

For loop and while loop comparison

So I did the next exercise, just with while loop:
Write a program that prompts the user for two integers.
Print each number in the range specified by those two integers.
Here is the code:
#include <iostream>
int main()
{
std::cout << "Write two numbers: " << std::endl;
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
std::cout << "The numbers between " << v1 << " and " << v2 << " are: " << std::endl;
while (v2 < v1 && ++v2 < v1)
{
std::cout << v2 << std::endl;
}
while (v1 < v2 && ++v1 < v2)
{
std::cout << v1 << std::endl;
}
}
Now I have to do it with the for loop, which I did like this:
#include <iostream>
int main()
{
std::cout << "Write two numbers: " << std::endl;
int a, b;
std::cin >> a >> b;
std::cout << "The numbers between " << a << " and " << b << " are: " << std::endl;
for (; a < b && ++a < b; a)
{
std::cout << a << std::endl;
}
for (; b < a && ++b < a; b)
{
std::cout << b << std::endl;
}
}
It looks almost the same, but it works.
My questions is: I'm I missing something about the for loop, could I do it simpler?
PD: Just for loop, I'm not in the If chapter yet, I want to go step by step on the "C++ Primer 5th edition".
for is specified in terms of while, you aren't missing anything.
for (init-statement conditionopt;
iteration-expressionopt) statement
produces code equivalent to:
{ init-statement while (condition) { statement
iteration-expression; } }
Except that
Names declared by the init-statement (if init-statement is a declaration) and names declared by condition (if condition is a
declaration) are in the same scope (which is also the scope of
statement).
continue in the statement will execute iteration-expression
Empty condition is equivalent to while(true)
from cppreference
You don't need anything in iteration-expression for(;;) is equivalent to while(true)
it would be more normal to increment in the iteration-expression, and not repeat almost the same test.
#include <iostream>
int main()
{
std::cout << "Write two numbers: " << std::endl;
int a, b;
std::cin >> a >> b;
std::cout << "The numbers between " << a << " and " << b << " are: " << std::endl;
for (; a < b; ++a)
{
std::cout << a << std::endl;
}
for (; b < a; ++b)
{
std::cout << b << std::endl;
}
}
The for loop is intended to loop between two numbers. The use of your for loops unreadable for it's intentions. Take a look at this
int end = 10;
for (int begin = 0; begin < end; ++begin){/*do something*/}
This is the standard structure of a for loop. Now for your example you will get the following
#include <algorithm>
if (a > b) std::swap(a, b);
for (int begin = a; begin <= b; ++begin){
std::cout << begin << std::endl;
}
There is no need on using something like a < b && ++a < b since a < b is contained in ++a < b condition. So just using ++a < b you will get the same results.
Now about the for you should write it like this just to make your code a bit clear:
for (; a < b; ++a)
{
std::cout << a << std::endl;
}
I am not using the initialization sentence as you have already initialized your variables, however I encorage you to initialize a in the for sentence
In general terms, the for is divided in three sections:
for (<initialization sentence>; <condition sentence>; <post-execution sentence>)
The initialization only runs when the for sentence is reached, and the loop is running while the condition is met. The post-execution it is normally used to increase or change state of the variables involved in the condition criteria. The only constraint you have is that condition must be a boolean sentence.
None of those sections should be an assigment, a common comparison or a variable increment. You could use whatever fits your requirements and met the for constraints.
To sum up, a for sentence is a 'wrapped' structure of a while. You could get the same results with both. The difference is on a cleaner image of your code and a better understanding of the algorithms.
The code in the question is somewhat confusing, because it tries to do several things at once. I'd separate them.
Instead of writing two loops, I'd just change the limits:
if (v2 < v1)
std::swap(v2, v1);
Now it's easy:
while (++v1 < v2)
std::cout << v1 << '\n';
Same thing for the for loop. After adjusting the limits, just do it:
for ( ; ++a < b; )
std::cout << a << '\n';

splitting one vector into almost-equal sub vectors then storing into another vector

I am trying to split one large user given vector into x sub vectors. Everything "seems" to work as it should but the outcome is not right.
std::vector<std::vector<std::string>> split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) {
std::cout << "initial size: " << initial_vector.size() << std::endl;
int size_for_splitting = initial_vector.size();
std::cout << "split amount: " << thread_amount << std::endl;
int r = size_for_splitting / thread_amount;
std::cout << r << " need to be in each sub-vector" << std::endl;
std::cout << "There will be: " << size_for_splitting % thread_amount << " element remaining" << std::endl;
std::vector<std::vector<std::string>> perm_vector;
for (int x = 0; x < thread_amount; x++) {
std::vector<std::string> temp_vector;
for (int a = 0; a < r; a++) {
hm++;
std::cout << hm << std::endl;
temp_vector.push_back(initial_vector[hm]);
}
perm_vector.push_back(temp_vector);
}
std::cout << "Size of vector holding the sub vectors after splitting: " << perm_vector.size() << std::endl;
std::cout << perm_vector[0][0];
return perm_vector;
Running this code will give you this:
initial size: 7
split amount: 3
2 need to be in each sub-vector
There will be: 1 element remaining
1
2
3
4
5
6
Size of vector holding the sub vectors after splitting: 3
2
the vector i pass in is called test holds strings and is like so:
test.push_back("1");
test.push_back("2");
test.push_back("3");
test.push_back("4");
test.push_back("5");
test.push_back("6");
test.push_back("7");
Everything up until the last print statement seems to work. So perm_vector should hold 3 sub vectors containing every element in the main user given vector. When you print perm_vector[0][0] you would expect the output to be "1", but it is 2, also 7 should not be in the vector and 6 should be the last one but since it starts at 2, 7 is in it. the counter is defined outside of the function and it starts at 0. My question is why is it starting at 2?
I see two problems in your code:
hm is incremented before use. Furthermore, there is no point in making it global.
size_for_splitting is the result of an integer division, so the remainder is missing
I modified your code so the issues with hm are solved. I get the intended output <<1, 2>, <3, 4>, <5, 6>>, the 7 is missing as mentioned above.
#include <iostream>
#include<vector>
#include<string>
std::vector<std::vector<std::string> > split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) {
std::cout << "initial size: " << initial_vector.size() << std::endl;
int size_for_splitting = initial_vector.size();
std::cout << "split amount: " << thread_amount << std::endl;
int r = size_for_splitting / thread_amount;
std::cout << r << " need to be in each sub-vector" << std::endl;
std::cout << "There will be: " << size_for_splitting % thread_amount << " element remaining" << std::endl;
std::vector<std::vector<std::string> > perm_vector;
int hm = 0;
for (int x = 0; x < thread_amount; x++) {
std::vector<std::string> temp_vector;
for (int a = 0; a < r; a++) {
std::cout << hm << std::endl;
temp_vector.push_back(initial_vector[hm]);
hm++;
}
perm_vector.push_back(temp_vector);
}
std::cout << "Size of vector holding the sub vectors after splitting: " << perm_vector.size() << std::endl;
return perm_vector;
}
int main()
{
std::vector<std::string> test;
test.push_back("1");
test.push_back("2");
test.push_back("3");
test.push_back("4");
test.push_back("5");
test.push_back("6");
test.push_back("7");
std::vector<std::vector<std::string> > out = split_to_sub_vectors(test, 3);
}
Even if hm starts at 0, you increment it before you use it. Probably if you increment at the end of the internal for loop, you might get the output you expect. It's hard to tell the problem because I don't know what's in 'initial_vector', I assume initial_vector[0] = 1?
If you use the range-v3 library, implementing this logic becomes much easier, and less error prone:
#include <range/v3/all.hpp>
namespace rs = ranges;
namespace rv = ranges::views;
auto split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) {
auto res = initial_vector
| rv::chunk(thread_amount)
| rs::to<std::vector<std::vector<std::string>>>;
if (res.back().size() != thread_amount)
res.pop_back();
return res;
}
Here's a demo.

print multiple numbers in ascending order in C++

So I'm working on this project where I have to gather 2 integers from a user 3 times (loop), and each time I have to print the two integers in ascending order. The restriction is that you can only have two cout statements within your loop (one is asking for their input and the second is outputting the ascending order).
My only issue with that is, when I think about ascending order, I would do it like (which has two count statements):
if (m<n) {
cout << m << n << endl;
if (m>n){
cout << n << m << endl;
So far, this is what I have:
#include <iostream>
using namespace std;
int main(int,char**) {
int n, m, z;
for (n=0;n<3;n++){
cout << "Give me two numbers: ";
cin >> m;
cin >> z;
//if (m>z);
//cout << m << z << "sorted is: " << m << z << endl;
// This is where I'm getting stuck because I need two count statements to organize in ascending order as shown above
}
}
So have you considered to change which variable holds the lower number? e.g.
if(m > n){
int temp = n;
n = m;
m = temp;
}
Then you can just use one print
cout << m << " " << n << endl;
This is where I'm getting stuck because I need two count[sic]
statements to organize in ascending order as shown above
You have marked this post as C++:
Additional options to consider:
use algorithm lib:
#include <algorithm>
std::cout << std::min(m,n) << " " << std::max(m,n) << std::endl;
or use conditional / ternary operator in your cout:
std::cout << ((m<n) ? m : n) << " " << ((n<m) ? m : n) << std::endl;
References are sometimes fun ... but perhaps this challenge is too trivial.
// guess m < n
int& first = m;
int& second = n;
if(!(m<n)) { first = n; second = m; }
std::cout << first << " " << second << std::endl;
Pointers can do the same:
// guess m < n
int& first = &m;
int& second = &n;
if(!(m<n)) { first = &n; second = &m; }
std::cout << *first << " " << *second << std::endl;
or you can use
lambda expressions, or
c++ functions, or
c++ class methods
But I think each of these would be directly comparable to either of the first alternatives.

fibonacci print out issue in c++

I was trying to run the fib.exe by using this command "fib 12" so it can directly print out the result in this format:
http://pastebin.com/ytR92i8f
But with my code compiled, for instance, if I use 12 to test my program, it won' t read any number and show the result in this command "fib xx" but it will run the program and let you type the number you want in the next line and then print out the result...
I have attached the link to my main.cpp below as reference.
main.cpp : http://pastebin.com/fhUAkNQR
Because main.c can not be modify so I can only use one function to get it works.
Right now I already have the correct result.
void fibonacci(int max)
{
do
{
std::cin >> max;
}
while(max < 2 && max > 46);
std::cout << " Fibonacci Fibonacci" << std::endl;
std::cout << " N number quotient" << std::endl;
std::cout << "-------------------------------------" << std::endl;
std::cout << " 0 0 N/A" << std::endl;
std::cout << " 1 1 N/A" << std::endl;
int count = max;
int fib1 = 0, fib2 = 1;
for (int i = 2; i <= count; i++)
{
int next = fib1 + fib2;
// Add statements to print here...
std::cout << std::setw(2) << i;
std::cout << std::setw(14) << next;
std::cout << std::setw(21) << std::setprecision(17) << std::showpoint;
std::cout << static_cast<double>(next) / fib2 << std::endl;
std::cout.unsetf(std::ios_base::showpoint);
fib1 = fib2;
fib2 = next;
}
return;
}
Here's and example. Problems like the Fibonacci are better dealt with recursion. I see that with your do while loops you are trying to use some sort of recursion but it's not really working
int fibonacci(int x)
{
if (x == 0)
return 0;
if (x == 1)
return 1;
return fibonacci(x-1)+fib(x-2);
}
This basically does all you've typed in your main, just supply x and enjoy. Recursion is a difficult concept but once you've got the idea it can preform very effectively but it's pretty limited in my opinion.

C++ long integer oddities?

I'm brushing up on some beginner's algorithms as I familiarize myself with C++. There are already some bugs I have no idea where to start fixing.
1) The following gives me seg faults around the time when the fib() function returns its results. EDIT: with inputs >= 9
#include <iostream>
using namespace std;
int fib(int n) {
int fibs[] = {1, 1}; // dynamic array
int i = 2; // start at 3rd element
while(i < n) {
fibs[i] = fibs[i-2] + fibs[i-1];
cout << "DEBUG: fibs[" << i << "] = " << fibs[i] << endl;
i = i+1;
}
cout << "about to return to main()" << endl;
return fibs[n-1];
}
int main() {
cout << "\n================= Hello cruel world =================" << endl;
cout << "Enter a number: ";
int x;
cin >> x;
cout << "fib(" << x << ") = " << fib(x) << endl;
cout << "================ Goodbye cruel world ================\n" << endl;
return 0;
}
Otherwise, the code works just fine, the numbers are found correctly. But 2) when I change the function to support long integers, it starts acting weird:
#include <iostream>
using namespace std;
long fib(int n) {
long fibs[] = {1L, 1L}; // dynamic array
int i = 2; // start at 3rd element
while(i < n) {
fibs[i] = fibs[i-2] + fibs[i-1];
cout << "DEBUG: fibs[" << i << "] = " << fibs[i] << endl;
i = i+1;
}
cout << "about to return to main()" << endl;
return fibs[n-1];
}
int main() {
cout << "\n================= Hello cruel world =================" << endl;
cout << "Enter a number: ";
int x;
cin >> x;
cout << "fib(" << x << ") = " << fib(x) << endl;
cout << "================ Goodbye cruel world ================\n" << endl;
return 0;
}
Output:
================= Hello cruel world =================
Enter a number: 7
DEBUG: fibs[2] = 2
DEBUG: fibs[0] = 1
DEBUG: fibs[1] = 30071067265
DEBUG: fibs[2] = 30071067266
DEBUG: fibs[14] = 0
about to return to main()
fib(7) = 140733637791872
================ Goodbye cruel world ================
It doesn't make any sense to me. Thanks for any help.
int fibs[] = {1, 1};
is equivalent to:
int fibs[2] = {1, 1};
In another word, the array fibs(in both programs) has only two elements, it's illegal to access fibs[n] if n is bigger than 1.
In
long fibs[] = {1L, 1L};
the [] does not mean "as big as it needs to be", it means "count the number of initializers". It's the same as
long fibs[2] = { 1L, 1L };
And the comment
// dynamic array
is just plain WRONG.
The other answers explain what's wrong. To fix it, you can declare fibs as a vector instead:
vector<int> fibs(n, 1);
which will construct a vector of n integers and initialize them all to 1. Replacing that single line of code should be all you need!
Yes it will fail because fibs[2] doesn't exist!
This is not dynamic array by any mean. Its array of 2 long
long fibs[] = {1L, 1L}; // dynamic array