This is a program to sort three inputted integers in order, from least to greatest. I would like to have it reviewed.
#include <iostream>
void Sort(int &a, int &b, int &c){
if(a>b){
int tmp = a;
a = b;
b = tmp;
}
if(a>c){
int tmp = a;
a=c;
c = tmp;
}
if(b>c){
int tmp = b;
b=c;
c=tmp;
}
return;
}
int main(){
std::cout << "Enter three integers: " << std::endl;
int num1;
int num2;
int num3;
std::cin >> num1 >> num2 >> num3;
int output1 = num1;
int output2 = num2;
int output3 = num3;
Sort(output1,output2,output3);
std::cout << num1 << " " << num2 << " " << num3 << " "
<< " in sorted order: ";
std::cout << output1 << " " << output2 << " " << output3 << std::endl;
return 0;
}
4 Answers 4
Things you should change:
Sort()
is explicitly returning at the end (return;
). The return statement is implicit once you reach the end of a void function, so should not appear.Pay attention to the spacing between the
=
sign. In some places you haveb=c;
while in others you havea = b;
Be consistent with the spacing. I suggest the latter, as it seems more readable to me.You don't have to
return 0
from main. Formain()
, the return zero is implicit if not added.
This is also a great opportunity for you to learn about C++ templates. I will suggest you a base implementation that you can study, test, and better understand the awesomeness of this language feature:
template<typename T>
void swap_if_greater(T& a, T& b)
{
if (a > b)
{
T tmp(a);
a = b;
b = tmp;
}
}
template<typename T>
void sort(T& a, T& b, T& c)
{
swap_if_greater(a, b);
swap_if_greater(a, c);
swap_if_greater(b, c);
}
Just as in the example provided by @EngieOP, I've added a swap function to reuse more code.
I've also better separated common code by moving the conditional inside the swap function (swap_if_greater()
), since it is common to all inputs.
sort()
is now a template function, meaning is can operate on any type, including int
, float
, double
, char
, ... It is a generic function, just as many of the functions in the standard C++ library. This concept promotes great code reuse and low redundancy of functionality.
-
4\$\begingroup\$ I would recommend using
std::swap
instead of implementing it inswap_if_greater
. \$\endgroup\$R Sahu– R Sahu2014年10月05日 07:51:05 +00:00Commented Oct 5, 2014 at 7:51 -
\$\begingroup\$ Concerning
return 0;
frommain
, I've always thought that leaving it out looks wrong. That feature is there to makehello, world
simple for beginners, but there's no harm in putting thereturn
statement in, and no need to remove it if it's there. \$\endgroup\$Pete Becker– Pete Becker2014年10月05日 14:02:46 +00:00Commented Oct 5, 2014 at 14:02 -
\$\begingroup\$ @PeteBecker, Adding the return 0 on main always seemed to me like adding the return at the end of a void function. Seems like boilerplate code to me. But I'll agree that opinions may vary on the subject. \$\endgroup\$glampert– glampert2014年10月05日 15:24:02 +00:00Commented Oct 5, 2014 at 15:24
-
\$\begingroup\$ @glampert - but
main
isn't avoid
function; it returnsint
, and the returned value is detectable by the caller. Leaving out the return is a convenience. \$\endgroup\$Pete Becker– Pete Becker2014年10月05日 15:44:46 +00:00Commented Oct 5, 2014 at 15:44
You can use std::swap
to swap values, and it will shorten the Sort
method by quite a bit:
void Sort(int &a, int &b, int &c){
if (a > b) {
std::swap(a, b);
}
if (a > c) {
std::swap(a, c);
}
if (b > c) {
std::swap(b, c);
}
}
Tip: the program will be a little bit easier to test if you allow the input as command line arguments too, in addition to stdin:
int main(int argc, char ** argv) {
int num1, num2, num3;
if (argc >= 4) {
num1 = std::stoi(argv[1]);
num2 = std::stoi(argv[2]);
num3 = std::stoi(argv[3]);
} else {
std::cout << "Enter three integers: " << std::endl;
std::cin >> num1 >> num2 >> num3;
}
Thanks to @glampert for recommending the modern std::stoi
instead of atoi
!
-
1\$\begingroup\$ I would recommend replacing
atoi
in your example withstd::stoi
, which is the new standard. It is very likely that the OP will have a C++ compiler by now. \$\endgroup\$glampert– glampert2014年10月05日 15:29:43 +00:00Commented Oct 5, 2014 at 15:29 -
\$\begingroup\$ @glampert: well, you can tell by the OP's use of references in the question. \$\endgroup\$Laurent LA RIZZA– Laurent LA RIZZA2014年10月06日 06:48:36 +00:00Commented Oct 6, 2014 at 6:48
-
1\$\begingroup\$ @LaurentLARIZZA, that was a typo, I meant a C++11 compiler. Of course the code in question was C++ :) \$\endgroup\$glampert– glampert2014年10月06日 13:40:14 +00:00Commented Oct 6, 2014 at 13:40
Notice how the function Sort()
is performing the same operation on three different pairs of variables?
I suggest writing a separate function called Swap()
. This shortens and simplifies the code.
Swap()
can be something like this:
void Swap(int &x, int &y){
int tmp = x;
x = y;
y = tmp;
return;
}
Your Sort()
function should look like this:
void Sort(int &a, int &b, int &c){
if(a>b){
Swap(a,b);
}
if(a>c){
Swap(a,c);
}
if(b>c){
Swap(b,c);
}
return;
}
Instead of declaring three more integers to hold the output, do the following. You're passing references to avoid copying anyway.
std::cout << num1 << " " << num2 << " " << num3 << " in sorted order: ";
Sort(num1,num2,num3);
std::cout << num1 << " " << num2 << " " << num3 << std::endl;
I'm sure other reviews may show examples of using C++11
to simplify things.
-
\$\begingroup\$ I thought it was simple enough that I didn't have to write a separate function. \$\endgroup\$user54356– user543562014年10月05日 00:56:16 +00:00Commented Oct 5, 2014 at 0:56
-
\$\begingroup\$ Okay. For a program this simple, you can do without writing a separate function. But do you really want to do all that extra typing? Plus, it looks cleaner don't you think? \$\endgroup\$Quaxton Hale– Quaxton Hale2014年10月05日 01:16:40 +00:00Commented Oct 5, 2014 at 1:16
-
4
-
1\$\begingroup\$ Yes. :) But since we're including
algorithm
, might as well just usestd::sort
. To what extent do we hold back for abeginner
tagged question? \$\endgroup\$Quaxton Hale– Quaxton Hale2014年10月05日 03:27:06 +00:00Commented Oct 5, 2014 at 3:27 -
\$\begingroup\$ @EngieOP: Sure, a beginner can learn how swap works, but using the STL version results in less code and less to maintain. \$\endgroup\$Jamal– Jamal2014年10月05日 19:30:08 +00:00Commented Oct 5, 2014 at 19:30
First off this is pretty good for a beginner. These are some notes that mostly say use the build in standard library which you are not familiar with yet.
I dislike the variable declarations
int num1; int num2; int num3;
Those 3 numbers belong together:
std::array<int, 3> numbers;
.
An alternative would beint numbers[3];
.
std::array
has some advantages such as having asize
method and it can be passed as a parameter. Build in arrays will decay to pointers instead.- You do not need to invent your own sorting algorithm, use
std::sort
. - You do not check for read errors. If
std::cin
fails to read the numbers your program will output garbage.
Complete program:
#include <array>
#include <algorithm>
#include <iostream>
int main(){
std::cout << "Enter three integers:\n";
std::array<int, 3> numbers;
for (auto &n : numbers){
if (!(std::cin >> n)){
std::cout << "Failed reading number\n";
return -1;
}
}
for (auto &n : numbers){
std::cout << n << ' ';
}
std::cout << " in sorted order: ";
std::sort(std::begin(numbers), std::end(numbers));
for (auto &n : numbers){
std::cout << n << ' ';
}
std::cout << '\n';
}